1. CNN (Convolution Neral Network)
1.1 CNN
- 이미지 영상인식의 혁명같은 CNN
- CNN은 이미지의 특징을 검출하여, 분류하는 것
- CNN은 특징을 찾는 레이어와 분류를 하는 레이어로 구성됨
1.2 Convolutional Filter
- Convolution : 특정 패턴이 있는지 박스로 훑으며 마킹하는 것
- 위 아래선 필터, 좌우선 필터, 대각선 필터, 각종 필터로 해당 패턴이 그림위에 있는지 확인
- 필터는 이미지의 특징을 찾아내기 위한 파라미터 위 그림에서는 주황색의 3 x 3 행렬 (CNN에서 Filter와 Kernel은 같은 의미로 사용됨)
- 필터는 일반적으로 4 x 4 or 3 x 3과 같은 정사각 행렬로 정의됨.
- CNN에서 학습을 통해 필터를 구할 수 있음
- CNN은 입력 데이터를 지정된 간격으로 순회하며 채널별로 합성곱을 하고 모든 채널(컬러의 경우 3개)의 합성곱의 합을 Feature Map로 만듬
- 위 그림은 채널이 1개인 입력 데이터를 (3, 3) 크기의 필터로 합성곱하는 과정을 나타냄
1.3 Pooling
- 풀링은 점점 더 멀리서 보는것 -> 그림의 크기를 줄이는것
1.4 MaxPooling
- 그림의 사이즈를 점진적으로 줄이는 법 MaxPooling
- n x n(pool)을 중요한 정보(Max) 한개로 줄임
- 선명한 정보만 남겨서 판단과 학습이 쉬워지고 노이즈가 줄면서 덤으로 융통성도 확보됨
- 4 x 4 행렬 -> 2 x 2 행렬이 됨
- Stride : 좌우로 몇칸씩 이동할지 설정, 보통 2 x 2
1.5 Conv Layer의 의미
- Conv : 패턴들을 쌓아가며 점차 복잡한 패턴을 인식
- MaxPooling : 사이즈를 줄여가며, 더욱 추상화 해나감
1.6 CNN 모델 및 코드
- 위의 내용으로 만든 CNN 모델의 구조와, 파이썬 코드
1.7 Zero Padding
- Zero Padding : 이미지의 귀퉁이가 짤리니, 사이즈 유지를 위해 Conv 전에 0을 모서리에 추가하고 시작함
1.8 Over Fitting
- 뉴럴넷에 고양이 이미지를 학습 시켰는데, 테스트 이미지가 학습한 이미지와 달라서 제대로 예측하지 못하는 현상
- 즉, 학습 데이터에 과도하게 Fitting되어 있음, 학습 데이터가 아니면 잘 예측하지 못하는것!
1.9 Drop Out
- Overfitting을 방지하기 위한 방법
- 학습 시킬때 일부러 정보를 누락시키거나, 중간 중간에 노드를 끄는것
2. 실습
2.1 MNIST Data load
1
2
3
4
5
6
7
8
9
from tensorflow.keras import datasets
mnist = datasets.mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train, X_test = X_train / 255.0, X_test / 255.0
X_train = X_train.reshape((60000, 28 ,28, 1))
X_test = X_test.reshape((10000, 28 ,28, 1))
- 텐서플로우에서 MNIST 데이터를 불러와서, 데이터 정리
- 255.0으로 나눠준 이유는 이미지가 0 ~ 255 사이의 값을 가지고 있어서, MinMaxScale을 적용한것
2.2 모델 구성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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, kernel_size=(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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_2 (Conv2D) (None, 28, 28, 32) 832
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_3 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 7, 7, 64) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 3136) 0
_________________________________________________________________
dense_2 (Dense) (None, 1000) 3137000
_________________________________________________________________
dense_3 (Dense) (None, 10) 10010
=================================================================
Total params: 3,156,098
Trainable params: 3,156,098
Non-trainable params: 0
_________________________________________________________________
2.3 Fit
1
2
3
4
5
6
7
8
9
import time
model.compile(optimizer='adam', loss = 'sparse_categorical_crossentropy', metrics=['accuracy'])
start_time = time.time()
hist = model.fit(X_train, y_train, epochs=5, verbose = 1, validation_data=(X_test, y_test))
print(f'Fit Time :{time.time() - start_time}')
1
2
3
4
5
6
7
8
9
10
11
Epoch 1/5
1875/1875 [==============================] - 35s 19ms/step - loss: 0.1138 - accuracy: 0.9642 - val_loss: 0.0358 - val_accuracy: 0.9877
Epoch 2/5
1875/1875 [==============================] - 37s 20ms/step - loss: 0.0467 - accuracy: 0.9853 - val_loss: 0.0315 - val_accuracy: 0.9909
Epoch 3/5
1875/1875 [==============================] - 39s 21ms/step - loss: 0.0326 - accuracy: 0.9898 - val_loss: 0.0261 - val_accuracy: 0.9916
Epoch 4/5
1875/1875 [==============================] - 40s 21ms/step - loss: 0.0243 - accuracy: 0.9926 - val_loss: 0.0336 - val_accuracy: 0.9893
Epoch 5/5
1875/1875 [==============================] - 41s 22ms/step - loss: 0.0223 - accuracy: 0.9930 - val_loss: 0.0264 - val_accuracy: 0.9917
Fit Time :190.74329090118408
- Accuracy가 0.99…?
2.4 그래프로 보기
1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt
plot_target = ['loss' , 'accuracy', 'val_loss', '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()
- 학습은 아무 문제없이 잘됨.
2.5 Test
1
2
3
score = model.evaluate(X_test, y_test)
print(f'Test Loss : {score[0]}')
print(f'Test Accuracy : {score[1]}')
1
2
3
313/313 [==============================] - 1s 5ms/step - loss: 0.0264 - accuracy: 0.9917
Test Loss : 0.02644716575741768
Test Accuracy : 0.9916999936103821
- Test도 0.99..
- 틀린 데이터가 궁금해짐
2.6 데이터 예측
1
2
3
4
5
import numpy as np
predicted_result = model.predict(X_test)
predicted_labels = np.argmax(predicted_result, axis=1)
predicted_labels[:10]
1
array([7, 2, 1, 0, 4, 1, 4, 9, 5, 9])
2.7 틀린 데이터만 모으기
1
2
3
4
5
6
wrong_result = []
for n in range(0, len(y_test)):
if predicted_labels[n] != y_test[n]:
wrong_result.append(n)
len(wrong_result)
1
83
- 총 1만개 데이터 중에 83개를 틀림
- 정확도 엄청나다..
2.8 틀린 데이터 16개만 직접 그려보기
1
2
3
4
5
6
7
8
9
10
11
12
13
import random
samples = random.choices(population=wrong_result, k =16)
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()
- 직접봐도 틀릴만한 것들. 1%
2.9 Model Save
1
model.save('MNIST_CNN_model.h5')
- model.save를 사용하여 만든 모델을 저장할 수 있음!
3. 요약
3.1 요약
- 이미지, 영상의 최강자 CNN을 튜토리얼 해보았다.
- 사실 하용호님의 자료가 너무 쉽게 잘 정리되어있어서 참 좋았다.
- 딥러닝은 코드를 짜면서도 구성도를 생각해야 해서, 정말 어려운듯 하다.