CNN (Convolutional Neural Networks)
: 딥러닝에서 주로 이미지나 영상 데이터를 처리할 때 쓰이며, Convolution이라는 전처리 작업이 들어가는 Neural Network 모델.이미지, 영상 인식의 혁명같은 CNN
일반 DNN은 기본적으로 1차원 형태의 데이터를 사용한다. 이미지(예를들면 1028x1028같은 2차원 형태의)가 입력값이 되는 경우, 이것을 flatten시켜서 한줄 데이터로 만들어야 하는데, 이 과정에서 이미지의 공간적/지역적 정보가 손실되게 된다. 또 추상화과정 없이 바로 연산과정으로 넘어가 버리기 때문에 학습시간과 능률의 효율성이 떨어진다.
이러한 문제점에서부터 고안한 해결책이 CNN. CNN은 이미지를 날것 그대로 받음으로써 공간적/지역적 정보를 유지한 채 특성(feature)들의 계층을 빌드업한다. CNN의 중요 포인트는 이미지 전체보다는 부분을 보는 것, 그리고 이미지의 한 픽셀과 주변 픽셀들의 연관성을 살리는 것.
미분은 변화율을 측정하기 때문에, 변화되는 부분을 따서 이미지의 경계를 인식.
원래 Convolutional Filter를 통해 필터를 만들고, 이 필터를 사용해서 이미지 변환하는 과정을 거쳤는데, CNN은 딥러닝을 사용해서 필터 특징을 검출하고, 찾은 특징을 가지고 분류를 하는 영역으로 나뉨.
Convolutional
: 특정 패턴이 있는지 박스로 훑으며 마킹
Conv 박스로 밀고나면, 숫자가 출력. 그 숫자를 Activation(주로 ReLU)에 넣어 나온 값을 이미지 지도를 그림.
풀링 layer를 지나면 이미지가 줄어든다.
사진을 1cm 거리만 두고 너무 가까이서 확대된 이미지를 보면 인식이 더 어려워 지기 때문에, 멀리에서 보는 것과 비슷.
풀링 필요성의 예
Pooling 종류 중 Maxpooling
💡 stride 옵션은 몇칸 이동하며 훑을 지
conv layer
흰 박스가 pooling layer, 파란 박스가 convolutional layer.
1) 예를 들어 MNIST 데이터 28*28 사이즈 이미지를 다루고 싶다면
2) 첫번째 Convolutional layer는 필터는 5*5로 잡고, activ function은 ReLU, Stride 1 로 해서 한칸씩 밀고나가며 인식하도록 설정. 채널 32개는 사진 크기를 바꾸지 않은 상태로, 32개의 특성을 찾겠다는 것과 비슷. 한 채널안에 필터를 통해 인식된 하나의 특성을 모아 총 32개 특성.
3) pooling layer 만나서 사이즈 줄여준다.
4) 다시 Convolutional layer를 만나 64개 채널로 확장. 그림을 멀리서 크게 보며 특성을 더 찾게 함.
5) 이 과정에서 나온 결과 (7*7) * 64 갯수를 flatten으로 펼침.
input_shape에 (28,28)이나 (28,28,1)이나 같은데 굳이 (28,28,1)로 한 이유는 채널때문.
두번째가 28*28*32로 3차원. 연산 시 여기에 맞춰서 데이터를 설정해줘야 하기 때문에 위와 같이 표기.
융통성 / 과적합 방지 --> 응용력을 주는 것
과적합을 방지하기 위해 학습에 방해를 줘서 일부 노드를 꺼버리는 것.
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train, X_test = X_train / 255, X_test / 255
X_train = X_train.reshape((60000, 28, 28, 1))
X_test = X_test.reshape((10000, 28, 28, 1))
from tensorflow.keras import layers, models
model = models.Sequential([
layers.Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
padding='same', activation='relu', input_shape=(28, 28, 1)),
layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
layers.Conv2D(64, (2, 2), activation='relu', padding='same'),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Dropout(0.25),
layers.Flatten(),
layers.Dense(1000, activation='relu'),
layers.Dense(10, activation='softmax')
])
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 832
max_pooling2d (MaxPooling2D (None, 14, 14, 32) 0
)
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
max_pooling2d_1 (MaxPooling (None, 7, 7, 64) 0
2D)
dropout (Dropout) (None, 7, 7, 64) 0
flatten (Flatten) (None, 3136) 0
dense (Dense) (None, 1000) 3137000
dense_1 (Dense) (None, 10) 10010
=================================================================
Total params: 3,156,098
Trainable params: 3,156,098
Non-trainable params: 0
_________________________________________________________________
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
hist = model.fit(X_train, y_train, epochs=5, verbose=1,
validation_data=(X_test, y_test))
Epoch 1/5
1875/1875 [==============================] - 38s 20ms/step - loss: 0.1172 - accuracy: 0.9630 - val_loss: 0.0541 - val_accuracy: 0.9819
Epoch 2/5
1875/1875 [==============================] - 43s 23ms/step - loss: 0.0442 - accuracy: 0.9862 - val_loss: 0.0345 - val_accuracy: 0.9881
Epoch 3/5
1875/1875 [==============================] - 56s 30ms/step - loss: 0.0355 - accuracy: 0.9890 - val_loss: 0.0359 - val_accuracy: 0.9889
Epoch 4/5
1875/1875 [==============================] - 75s 40ms/step - loss: 0.0254 - accuracy: 0.9918 - val_loss: 0.0313 - val_accuracy: 0.9906
Epoch 5/5
1875/1875 [==============================] - 53s 28ms/step - loss: 0.0206 - accuracy: 0.9935 - val_loss: 0.0277 - val_accuracy: 0.9902
import matplotlib.pyplot as plt
plot_target = ['loss', 'val_loss', 'accuracy', 'val_accuracy']
plt.figure(figsize=(12, 8))
for each in plot_target:
plt.plot(hist.history[each], label= each)
plt.legend()
plt.grid()
plt.show()
score = model.evaluate(X_test, y_test)
print("Test loss : " + str(score[0]))
print("Test accuracy : " + str(score[1]))
313/313 [==============================] - 2s 5ms/step - loss: 0.0277 - accuracy: 0.9902
Test loss : 0.027657995000481606
Test accuracy : 0.9901999831199646
# 틀린 결과 확인 -> 전체 데이터 인덱스 확인
import numpy as np
predicted_result = model.predict(X_test)
predicted_labels = np.argmax(predicted_result, axis=1)
predicted_labels[:10]
array([7, 2, 1, 0, 4, 1, 4, 9, 5, 9], dtype=int64)
wrong_result = []
for n in range(0, len(y_test)):
if predicted_labels[n] != y_test[n]:
wrong_result.append(n)
len(wrong_result)
98
#틀린 데이터 중 랜덤 16개 선택
import random
samples = random.choices(population=wrong_result, k=16)
samples[:3]
[1260, 4078, 2939]
# 틀린 데이터 확인
plt.figure(figsize=(14, 12))
for idx, n in enumerate(samples):
plt.subplot(4, 4, idx+1)
plt.imshow(X_test[n].reshape(28, 28), cmap='Greys', interpolation='nearest')
plt.title('Label : '+str(y_test[n]) + " | Predict : " + str(predicted_labels[n]))
plt.axis('off')
plt.show()
모델은 훈련 중 및 훈련 후에 저장할 수 있다.
모델이 중단된 위치에서 다시 시작하고 긴 훈련 시간을 피할 수 있다.
model.save('./MNIST_CNN_model.h5')
from tensorflow.keras import models
test_model = models.load_model('./MNIST_CNN_model.h5')