기존의 데이터는 정형화된 DataFrame 형태로 입력을 해왔는데, 이미지 데이터는 그렇지 않다. 컴퓨터에게 이미지는 각 픽셀 값을 가진 숫자 배열로 인식된다. 이미지를 픽셀이란 작은 정사각형 단위로 나눠서 각 색깔에 맞게 값이 지정되는 것이다.
이미지 전 처리
모두 같은 크기를 갖는 이미지로 통일한다.
1) 가로 세로 픽셀 사이즈를 표현하는 해상도 통일을 먼저 진행한 후,
2) 색을 표현하는 방식을 통일한다(RGB, HSV, Gray-scale, Binary, ...)
MNIST 데이터는 이미지 데이터이지만 가로 길이와 세로 길이만 존재하는 2차원 데이터이다. CNN 모델은 채널(RGB 혹은 흑백)까지 고려한 3차원 데이터를 입력으로 받기에 채널 차원을 추가해 데이터의 모양(Shape)을 바꿔준다.
합성곱 신경망(Convolution Neural Network)
기존 다층 퍼셉트론 기반 신경망을 통해서 이미지를 처리하면 극도로 많은 수의 파라미터가 필요하고, 이미지에 변화가 있기라도 하면 데이터 변화도 심해진다. 이런 단점은 분류 성능을 저하시킨다. 이를 해결하기 위한 모델로 CNN이 있다.
합성곱 신경망은 작은 필터를 순환시키는 방식으로, 이미지의 패턴이 아닌 특징을 중점으로 인식한다.
Convoultion Layer와 Pooling Layer가 특징을 추출해서 Fully-Connected Layer가 분류하는 과정으로 동작한다. 분류를 수행하는 FC Layer는 지금껏 사용했던 딥러닝 모델이라 생각하면 된다. 노드끼리 모두 연결돼있기 때문에 이렇게 부른다.
Convoultion Layer
이미지에서 어떠한 특징이 있는 지를 구하는 과정이며, 필터가 이미지를 이동하여 새로운 이미지(피쳐맵)을 생성한다. 특정 필터로 해당 특징이 있는지를 조사하여 그 특징이 있으면 큰 값을 피쳐맵에 할당하게 되는 구조이다. 수많은 필터들을 통해 필터에 있는 이미지와 입력 이미지가 비슷한 점이 있는지를 확인하고 그 위치를 알려준다.
피쳐맵은 두 가지 요소에 따라 크기를 변형할 수 있다.
Padding : 원본 이미지의 상하좌우에 한 줄씩 추가. 필터를 통해 이미지 처리를 하면 원본 이미지보다 크기가 작아지기 때문에 의미없는 값(0)을 채워서 원본 사이즈와 같은 크기로 피쳐맵을 출력하기 위해 추가하는 것이다.
Striding : 필터를 이동시키는 거리(Stride) 조정. 필터를 이동시킬 때 한 칸 움직일 것인지, 두 칸 움직일 것인지 Stride로 조절할 수 있다.
Pooling Layer
이미지의 왜곡의 영향(노이즈)를 축소하는 과정이다. Max Pooling은 구역의 최대값으로, Average Pooling은 구역의 평균값으로 축소한다. 특징이 있었는지 없었는지, 어디에 있었으냐가 중요한 정보이기 때문에 Pooling Layer를 통해 노이즈도 없애고 정보도 압축하는 것이다. 사실상 Max Pooling이 자주 사용된다.
Fully Connected Layer
Convoultion Layer와 Pooling Layer를 통해 나온 결과물이 1차원 배열로 만들어진다. 각 특징들이 1차원 배열로 정리되는 것이다. 추출된 특징을 사용하여 이미지를 분류하는 과정이다. 이 분류 마지막 계층에 Softmax 활성화 함수를 사용한다. 많은 label에 대해 예측을 해야 할 경우에 Softmax를 사용하고, 마지막 Layer에 있는 unit의 개수는 예측해야 하는 범주(Layer)의 개수만큼이다. Softmax 함수를 통과해서 나온 출력값 각각은 확률값이며, 그 총합은 1이다. 가장 큰 확률 값이 예측된 결과라고 생각할 수 있다.
Convolution Layer는 특징을 찾아내고, Pooling Layer는 처리할 맵(이미지) 크기를 줄여준다. 이를 N번 반복한다. 반복할 때마다 줄어든 영역에서의 특징을 찾게 되고, 영역의 크기는 작아졌기 때문에 빠른 학습이 가능해진다. 합성곱과 풀링은 여러 번 가능한데, 특징 안에서도 세부 특징을 또 분석하는 과정이 반복된다는 말이다. 풀링 또한 반복되기 때문에 데이터의 전체적인 양은 크지 않다. 최종적으로 Fully Connected Layer를 통해 활성함수로 분류하게 된다.
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from visual import *
from plotter import *
from elice_utils import EliceUtils
elice_utils = EliceUtils()
import logging, os
logging.disable(logging.WARNING)
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
# 동일한 실행 결과 확인을 위한 코드입니다.
np.random.seed(123)
tf.random.set_seed(123)
# MNIST 데이터 세트를 불러옵니다.
mnist = tf.keras.datasets.mnist
# MNIST 데이터 세트를 Train set과 Test set으로 나누어 줍니다.
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# Train 데이터 5000개와 Test 데이터 1000개를 사용합니다.
train_images, train_labels = train_images[:5000], train_labels[:5000]
test_images, test_labels = test_images[:1000], test_labels[:1000]
# CNN 모델의 입력으로 사용할 수 있도록 (샘플개수, 가로픽셀, 세로픽셀, 1) 형태로 변환합니다.
train_images = tf.expand_dims(train_images, -1)
test_images = tf.expand_dims(test_images, -1)
# CNN 모델을 설정합니다.
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'SAME', input_shape = (28,28,1)),
tf.keras.layers.MaxPool2D(padding = 'SAME'),
tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'SAME'),
tf.keras.layers.MaxPool2D(padding = 'SAME'),
tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'SAME'),
tf.keras.layers.MaxPool2D(padding = 'SAME'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation = 'relu'),
tf.keras.layers.Dense(10, activation = 'softmax')
])
# CNN 모델 구조를 출력합니다.
print(model.summary())
# CNN 모델의 학습 방법을 설정합니다.
model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = 'adam',
metrics = ['accuracy'])
# 학습을 수행합니다.
history = model.fit(train_images, train_labels, epochs = 10, batch_size = 128, verbose = 2)
Visulaize([('CNN', history)], 'loss')
# 평가용 데이터를 활용하여 모델을 평가합니다.
# loss와 accuracy를 계산하고 loss, test_acc에 저장합니다.
loss, test_acc = model.evaluate(test_images, test_labels, verbose = 2)
# 평가용 데이터에 대한 예측 결과를 predictions에 저장합니다.
predictions = model.predict_classes(test_images)
# 모델 평가 및 예측 결과를 출력합니다.
print('\nTest Loss : {:.4f} | Test Accuracy : {}'.format(loss, test_acc))
print('예측한 Test Data 클래스 : ',predictions[:10])
# 평가용 데이터에 대한 레이어 결과를 시각화합니다.
Plotter(test_images, model)
단순해지고 압축되는 정보 변화를 볼 수 있다.
CNN Layer
tf.keras.layers.Conv2D(filters, kernel_size, activation, padding)
입력 이미지의 특징, 즉 처리할 특징 맵(map)을 추출하는 레이어다.
- filters : 필터(커널) 개수
- kernel_size : 필터(커널)의 크기
- acitvaiton : 활성화 함수
- padding : 이미지가 필터를 거칠 때 그 크기가 줄어드는 것을 방지하기 위해서 가장자리에 0의 값을 가지는 픽셀을 넣을 것인지 말 것인지를 결정하는 변수. 'SAME'은 원본 이미지와 같은 크기이고 'VALID'는 넣지 않는 것.
Maxpool Layer
tf.keras.layers.Maxpool2D(padding)
처리할 특징 맵(map)의 크기를 줄여주는 레이어다. padding은 'SAME' 또는 'VALID'를 입력한다.
Flatten Layer
tf.keras.layers.Flatten()
Convolution layer 또는 MaxPooling layer의 결과는 N차원의 텐서 형태이다. 이를 1차원으로 평평하게 만들어준다.
Dense Layer
tf.keras.layers.Dense(node, activation)
node는 노드(뉴런) 개수, activation은 활성화 함수다.
CNN 평가 방법
model.evaluate(X, Y)
evaulate() 메서드는 학습된 모델을 바탕으로 입력한 feature 데이터 X와 label Y의 loss값과 metrics 값을 출력한다.
CNN 예측 방법
model.predict_classes(X)
X 데이터의 예측 label 값을 출력한다. multi-class 사용할 때 쓰는 함수다. 그냥 predict 함수는 해당되는 class의 softmax(확률) 값을 리스트로 출력해줘서 가장 큰 값을 또 비교해줘야 하는데, 이 함수는 가장 큰 값을 label로 설정까지 해준다.
MNIST 분류 task를 MLP와 CNN으로 각각 학습하였을 때의 성능 차이를 비교한 코드다.
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import logging, os
logging.disable(logging.WARNING)
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
# 동일한 실행 결과 확인을 위한 코드입니다.
np.random.seed(123)
tf.random.set_seed(123)
# MNIST 데이터 세트를 불러옵니다.
mnist = tf.keras.datasets.mnist
# MNIST 데이터 세트를 Train set과 Test set으로 나누어 줍니다.
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# Train 데이터 5000개와 Test 데이터 500개를 사용합니다.
train_images, train_labels = train_images[:5000].astype(float), train_labels[:5000]
test_images, test_labels = test_images[:500].astype(float), test_labels[:500]
'''
1. 먼저 MLP 모델을 학습해보겠습니다.
'''
print('========== MLP ==========')
# MLP 모델의 입력으로 사용할 수 있도록 (샘플개수, 가로픽셀 * 세로픽셀) 형태로 변환합니다.
train_images = tf.cast(tf.reshape(train_images, (5000, -1)) / 256., tf.float32)
train_labels = tf.convert_to_tensor(train_labels)
test_images = tf.cast(tf.reshape(test_images, (500, -1)) / 256., tf.float32)
test_labels = tf.convert_to_tensor(test_labels)
# MLP 모델을 설정합니다.
MLP_model = tf.keras.Sequential([
tf.keras.layers.Dense(62, activation = 'relu'),
tf.keras.layers.Dense(32, activation = 'relu'),
tf.keras.layers.Dense(10, activation = 'softmax')
])
# MLP 모델의 학습 방법을 설정합니다.
MLP_model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = 'adam',
metrics = ['accuracy'])
# 학습을 수행합니다.
history = MLP_model.fit(train_images, train_labels, epochs = 10, batch_size = 128, verbose = 2)
# MLP 모델 구조를 출력합니다. weight의 수가 52,650개입니다.
MLP_model.summary()
# 평가용 데이터를 활용하여 정확도를 평가합니다.
loss, test_acc = MLP_model.evaluate(test_images, test_labels, verbose = 0)
# 모델 평가 및 예측 결과를 출력합니다.
print('\nMLP Test Loss : {:.4f} | MLP Test Accuracy : {}\n'.format(loss, test_acc))
'''
2. 다음으로, CNN 모델을 학습해보겠습니다.
'''
print('========== CNN ==========')
# CNN 모델의 입력으로 사용할 수 있도록 (샘플개수, 가로픽셀, 세로픽셀, 1) 형태로 변환합니다.
train_images = tf.reshape(train_images, (5000, 28, 28, 1))
test_images = tf.reshape(test_images, (500, 28, 28, 1))
# CNN 모델을 설정합니다.
CNN_model = tf.keras.Sequential([
tf.keras.layers.Conv2D(filters = 32, kernel_size = (3, 3), activation = 'relu', padding = 'SAME', input_shape = (28,28,1)),
tf.keras.layers.MaxPool2D(padding = 'SAME'),
tf.keras.layers.Conv2D(filters = 32, kernel_size = (3, 3), activation = 'relu', padding = 'SAME'),
tf.keras.layers.MaxPool2D(padding = 'SAME'),
tf.keras.layers.Conv2D(filters = 32, kernel_size = (3, 3), activation = 'relu', padding = 'SAME'),
tf.keras.layers.MaxPool2D(padding = 'SAME'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation = 'relu'),
tf.keras.layers.Dense(10, activation = 'softmax')
])
# CNN 모델의 학습 방법을 설정합니다.
CNN_model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = 'adam',
metrics = ['accuracy'])
# 학습을 수행합니다.
history = CNN_model.fit(train_images, train_labels, epochs = 10, batch_size = 128, verbose = 2)
# CNN 모델 구조를 출력합니다. weight의 수가 52,298개입니다.
CNN_model.summary()
# 평가용 데이터를 활용하여 정확도를 평가합니다.
loss, test_acc = CNN_model.evaluate(test_images, test_labels, verbose = 0)
# 모델 평가 및 예측 결과를 출력합니다.
print('\nCNN Test Loss : {:.4f} | CNN Test Accuracy : {}'.format(loss, test_acc))
Loss, Accuracy 모두 CNN이 이겼다.
'AI / DL > 엘리스 AI 데이터 분석 트랙' 카테고리의 다른 글
[AI 데이터 분석] 산업 데이터를 활용한 인공지능 프로젝트 01. 의류 판매 상품 리뷰 분석을 통한 상품 추천 여부 예측 (0) | 2022.10.10 |
---|---|
[AI 데이터 분석] 딥러닝 시작하기 03. 다양한 신경망 (2) (0) | 2022.10.09 |
[AI 데이터 분석] 딥러닝 시작하기 02. 텐서플로우와 신경망 (0) | 2022.10.08 |
[AI 데이터 분석] 딥러닝 시작하기 01. 퍼셉트론 (0) | 2022.10.08 |
[AI 데이터 분석] 머신러닝 시작하기 04. 지도학습 - 분류 (0) | 2022.10.07 |
댓글