Rylah's Study & Daily Life
[TensorFlow] 03. CNN - Fashion Items 본문
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import numpy as np
import matplotlib.pyplot as plt
from time import time
from keras.datasets import fashion_mnist
from keras.utils.np_utils import to_categorical
from sklearn.metrics import f1_score, confusion_matrix
from keras.models import Sequential
from keras.layers import Flatten
from keras.layers import Dense, InputLayer
from keras.layers import Conv2D, MaxPool2D
# 하이퍼 파라미터
# MY_EPOCH = 0
MY_EPOCH = 3
# MY_EPOCH = 20
MY_BATCH = 300
############ 데이터 준비 ############
# 데이터 파일 읽기
# 결과는 numpy의 n-차원 행렬 형식
(x_train, y_train), (x_test, y_test) = \
fashion_mnist.load_data()
# x_train = x_train[:30000]
# y_train = y_train[:30000]
# 4분할 된 데이터 모양 출력
print('\n학습용 입력 데이터 모양:', x_train.shape)
print('학습용 출력 데이터 모양:', y_train.shape)
print('평가용 입력 데이터 모양:', x_test.shape)
print('평가용 출력 데이터 모양:', y_test.shape)
# 샘플 데이터 출력
print(x_train[0])
# plt.imshow(x_train[0], cmap='gray')
# plt.show()
print('샘플 데이터 라벨:', y_train[0])
# 정규화 - MinMax 정규화 이론 [0, 1] 스케일링
# - 모든 데이터 값을 [0,1] 범위로 전환
# - 경사하강법 실행 시간을 줄여줌
# 제로 원 스케일링 Xmax = 255 Xmin = 0
# 각 화소를 255로 나누는 효과
x_train = x_train / 255.0
x_test = x_test / 255.0
# 이미지 데이터에서 채널의 의미
# - 흑백 : 1
# - 칼라 : 3(RGB)
# Conv2D 입력 데이터 형식
# - 4차원 텐서 요구
# Channel-last 방식 : batch + (rows, cols, channels)
# Conv2D 출력 데이터 형식
# - 4차원 텐서 출력
# Channel-last 방식 : batch + (rows, cols, filters)
# 채널 정보 추가
# 케라스 CNN에서 4차원 정보를 필요로 한다.
train = x_train.shape[0]
x_train = x_train.reshape(train, 28, 28, 1)
test = x_test.shape[0]
x_test = x_test.reshape(test, 28, 28, 1)
# 원핫 인코딩 이론
# 범주형 데이터(Categorical Data) 대상
# - 데이터를 하나의 정수가 아닌 여러개의 2진수로 표현
# 정수 데이터는 의도치 않은 혼동을 초래
# - CNN 예측값 2.0을 어떻게 해석할 것인가
# One hot Encoding은 이런 문제를 해결
# - 출력 숫자는 하나가 아니고 넷
# 출력 데이터 (= 라벨 정보) One Hot Encoding
print('원 핫 인코딩 전 : ', y_train[0])
y_train = to_categorical(y_train, 10)
print('원 핫 인코딩 후 : ', y_train[0])
y_test = to_categorical(y_test, 10)
print('학습용 출력 데이터 모양:', y_train.shape)
print('평가용 출력 데이터 모양:', y_test.shape)
############ 인공 신경망 구현 ############
# CNN 구현 (순차적 방법)
model = Sequential()
# 입력층
model.add(InputLayer(input_shape=(28, 28, 1)))
# 첫 번째 합성곱 블럭
model.add(Conv2D(filters=32,
kernel_size=2,
padding='same',
activation='relu'))
# model.add(Conv2D(filters=32,
# kernel_size=5,
# padding='same',
# activation='relu'))
# model.add(Conv2D(filters=32,
# kernel_size=1,
# padding='same',
# activation='relu'))
# model.add(Conv2D(filters=8,
# kernel_size=2,
# padding='same',
# activation='relu'))
# model.add(Conv2D(filters=128,
# kernel_size=2,
# padding='same',
# activation='relu'))
# model.add(Conv2D(filters=32,
# kernel_size=2,
# padding='same',
# activation='sigmoid'))
# model.add(Conv2D(filters=32,
# kernel_size=2,
# padding='same',
# activation='tanh'))
model.add(MaxPool2D(pool_size=2))
# 두 번째 합성곱 블럭
model.add(Conv2D(filters=64,
kernel_size=2, # 합성 곱 필터의 크기
padding='same', # 14 * 14
activation='relu'))
# model.add(Conv2D(filters=64,
# kernel_size=5, # 합성 곱 필터의 크기
# padding='same', # 14 * 14
# activation='relu'))
# model.add(Conv2D(filters=64,
# kernel_size=1, # 합성 곱 필터의 크기
# padding='same', # 14 * 14
# activation='relu'))
# model.add(Conv2D(filters=16,
# kernel_size=2, # 합성 곱 필터의 크기
# padding='same', # 14 * 14
# activation='relu'))
# model.add(Conv2D(filters=256,
# kernel_size=2, # 합성 곱 필터의 크기
# padding='same', # 14 * 14
# activation='relu'))
# model.add(Conv2D(filters=64,
# kernel_size=2, # 합성 곱 필터의 크기
# padding='same', # 14 * 14
# activation='sigmoid'))
# model.add(Conv2D(filters=64,
# kernel_size=2, # 합성 곱 필터의 크기
# padding='same', # 14 * 14
# activation='tanh'))
model.add(MaxPool2D(pool_size=2))
# SoftMax 활성화 함수
# [0, 1] 정규화의 한 종류
# - 자연 지수, 함수 (e의 y승에 대입)
# - 출력 값들의 총 합은 항상 1: 확률과 동일
# - 분류 문제 해결에서 많이 사용
model.add(Flatten())
# 3136개의 은닉층이 늘어난다. 약 40만개의 시냅스가 사용
model.add(Dense(128,
activation='relu'))
# model.add(Dense(128,
# activation='sigmoid'))
# model.add(Dense(128,
# activation='tanh'))
# 출력
model.add(Dense(10,
activation='softmax'))
print('\nCNN 요약')
model.summary()
########## 인공 신경망 학습 #############
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['acc'])
# model.compile(optimizer='sgd',
# loss='categorical_crossentropy',
# metrics=['acc'])
# model.compile(optimizer='RMSprop',
# loss='categorical_crossentropy',
# metrics=['acc'])
# model.compile(optimizer='adam',
# loss='mse',
# metrics=['acc'])
# model.compile(optimizer='adam',
# loss='poisson',
# metrics=['acc'])
begin = time()
print('\nCNN 학습 시작')
model.fit(x_train,
y_train,
epochs=MY_EPOCH,
batch_size=MY_BATCH,
verbose=1)
end = time()
print('총 학습시간: {:.1f}초'.format(end - begin))
########### 인공 신경망 평가 ###############
# CNN 평가
_, score = model.evaluate(x_test,
y_test,
verbose=0)
print('최종 정확도: {:.2f}%'.format(score * 100))
# CNN 추측
pred = model.predict(x_test)
pred = np.argmax(pred, axis=1)
truth = np.argmax(y_test, axis=1)
# 혼동 행렬
print('\n혼동 행렬')
print(confusion_matrix(truth, pred))
# F1 점수
f1 = f1_score(truth, pred, average='micro')
print('\nF1 점수: {:.3f}'.format(f1))
출력 결과는 더보기를 클릭하면 볼 수 있다. 너무 길어져서 접었다.
학습용 입력 데이터 모양: (60000, 28, 28)
학습용 출력 데이터 모양: (60000,)
평가용 입력 데이터 모양: (10000, 28, 28)
평가용 출력 데이터 모양: (10000,)
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 13 73 0
0 1 4 0 0 0 0 1 1 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 3 0 36 136 127 62
54 0 0 0 1 3 4 0 0 3]
[ 0 0 0 0 0 0 0 0 0 0 0 0 6 0 102 204 176 134
144 123 23 0 0 0 0 12 10 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 155 236 207 178
107 156 161 109 64 23 77 130 72 15]
[ 0 0 0 0 0 0 0 0 0 0 0 1 0 69 207 223 218 216
216 163 127 121 122 146 141 88 172 66]
[ 0 0 0 0 0 0 0 0 0 1 1 1 0 200 232 232 233 229
223 223 215 213 164 127 123 196 229 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 183 225 216 223 228
235 227 224 222 224 221 223 245 173 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 193 228 218 213 198
180 212 210 211 213 223 220 243 202 0]
[ 0 0 0 0 0 0 0 0 0 1 3 0 12 219 220 212 218 192
169 227 208 218 224 212 226 197 209 52]
[ 0 0 0 0 0 0 0 0 0 0 6 0 99 244 222 220 218 203
198 221 215 213 222 220 245 119 167 56]
[ 0 0 0 0 0 0 0 0 0 4 0 0 55 236 228 230 228 240
232 213 218 223 234 217 217 209 92 0]
[ 0 0 1 4 6 7 2 0 0 0 0 0 237 226 217 223 222 219
222 221 216 223 229 215 218 255 77 0]
[ 0 3 0 0 0 0 0 0 0 62 145 204 228 207 213 221 218 208
211 218 224 223 219 215 224 244 159 0]
[ 0 0 0 0 18 44 82 107 189 228 220 222 217 226 200 205 211 230
224 234 176 188 250 248 233 238 215 0]
[ 0 57 187 208 224 221 224 208 204 214 208 209 200 159 245 193 206 223
255 255 221 234 221 211 220 232 246 0]
[ 3 202 228 224 221 211 211 214 205 205 205 220 240 80 150 255 229 221
188 154 191 210 204 209 222 228 225 0]
[ 98 233 198 210 222 229 229 234 249 220 194 215 217 241 65 73 106 117
168 219 221 215 217 223 223 224 229 29]
[ 75 204 212 204 193 205 211 225 216 185 197 206 198 213 240 195 227 245
239 223 218 212 209 222 220 221 230 67]
[ 48 203 183 194 213 197 185 190 194 192 202 214 219 221 220 236 225 216
199 206 186 181 177 172 181 205 206 115]
[ 0 122 219 193 179 171 183 196 204 210 213 207 211 210 200 196 194 191
195 191 198 192 176 156 167 177 210 92]
[ 0 0 74 189 212 191 175 172 175 181 185 188 189 188 193 198 204 209
210 210 211 188 188 194 192 216 170 0]
[ 2 0 0 0 66 200 222 237 239 242 246 243 244 221 220 193 191 179
182 182 181 176 166 168 99 58 0 0]
[ 0 0 0 0 0 0 0 40 61 44 72 41 35 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]]
샘플 데이터 라벨: 9
원 핫 인코딩 전 : 9
원 핫 인코딩 후 : [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
학습용 출력 데이터 모양: (60000, 10)
평가용 출력 데이터 모양: (10000, 10)
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 8s 42ms/step - loss: 0.6037 - acc: 0.7875
Epoch 2/3
200/200 [==============================] - 8s 42ms/step - loss: 0.3675 - acc: 0.8686
Epoch 3/3
200/200 [==============================] - 8s 42ms/step - loss: 0.3269 - acc: 0.8831
총 학습시간: 25.6초
최종 정확도: 88.21%
혼동 행렬
[[804 0 9 22 5 2 145 0 13 0]
[ 1 966 1 23 3 0 4 0 2 0]
[ 14 1 783 7 94 0 95 0 6 0]
[ 25 4 7 872 32 0 53 0 7 0]
[ 1 2 53 18 847 0 76 0 3 0]
[ 0 0 0 1 0 951 0 31 1 16]
[112 2 66 19 79 0 704 0 18 0]
[ 0 0 0 0 0 8 0 950 2 40]
[ 2 1 0 3 2 1 6 5 980 0]
[ 0 0 0 0 0 3 1 30 2 964]]
F1 점수: 0.882
Process finished with exit code 0
기본적인 것을 돌렸을 때 결과는 train 이미지가 저렇게 나오고 CNN 학습 결과로 88.21%의 정확도로 물체가 무엇인지 인공지능이 강화학습이 된 것을 확인할 수 있다.
세세하게 수치를 조절해보자.
1. EPOCH 조절
a) EPOCH가 0인 경우
전의 결과는 EPOCH 학습을 3번하는 경우이다. 이것을 0으로 바꾸면 어떻게될까?
출력 결과는 아래에서 볼 수 있다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
총 학습시간: 0.1초
최종 정확도: 13.79%
혼동 행렬
[[895 54 17 0 0 0 2 0 1 31]
[845 13 19 1 0 0 0 0 0 122]
[297 123 438 0 0 0 5 0 0 137]
[844 30 11 6 0 0 1 0 4 104]
[331 69 417 0 0 0 3 0 0 180]
[ 25 482 190 44 0 0 36 12 197 14]
[599 94 190 1 0 0 2 0 1 113]
[ 3 416 22 180 0 0 44 0 313 22]
[245 500 127 5 0 0 1 4 12 106]
[ 32 151 58 1 0 0 56 2 687 13]]
F1 점수: 0.138
Process finished with exit code 0
결과는 보다시피 학습시간은 0.1초로 매우 짧아졌으며, 정확도는 13.79%로 매우 낮은편이라고 할 수 있다.
혼동행렬은 대각선 수치 이외의 모든 수치들이 증가한 것을 볼 수 있다.
b) EPOCH가 20인 경우
이번에는 20번을 강화학습을 진행해보자.
결과는 다음과 같다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/20
200/200 [==============================] - 9s 45ms/step - loss: 0.5841 - acc: 0.7971
Epoch 2/20
200/200 [==============================] - 9s 45ms/step - loss: 0.3593 - acc: 0.8713
Epoch 3/20
200/200 [==============================] - 9s 45ms/step - loss: 0.3178 - acc: 0.8856
Epoch 4/20
200/200 [==============================] - 9s 46ms/step - loss: 0.2883 - acc: 0.8959
Epoch 5/20
200/200 [==============================] - 9s 45ms/step - loss: 0.2687 - acc: 0.9032
Epoch 6/20
200/200 [==============================] - 9s 45ms/step - loss: 0.2479 - acc: 0.9115
Epoch 7/20
200/200 [==============================] - 9s 46ms/step - loss: 0.2333 - acc: 0.9159
Epoch 8/20
200/200 [==============================] - 9s 46ms/step - loss: 0.2249 - acc: 0.9180
Epoch 9/20
200/200 [==============================] - 9s 46ms/step - loss: 0.2098 - acc: 0.9243
Epoch 10/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1980 - acc: 0.9276
Epoch 11/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1892 - acc: 0.9307
Epoch 12/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1792 - acc: 0.9349
Epoch 13/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1735 - acc: 0.9366
Epoch 14/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1647 - acc: 0.9399
Epoch 15/20
200/200 [==============================] - 9s 47ms/step - loss: 0.1529 - acc: 0.9449
Epoch 16/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1480 - acc: 0.9463
Epoch 17/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1408 - acc: 0.9486
Epoch 18/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1331 - acc: 0.9517
Epoch 19/20
200/200 [==============================] - 9s 46ms/step - loss: 0.1233 - acc: 0.9553
Epoch 20/20
200/200 [==============================] - 9s 45ms/step - loss: 0.1179 - acc: 0.9581
총 학습시간: 184.7초
최종 정확도: 91.55%
혼동 행렬
[[809 0 26 14 2 1 141 0 6 1]
[ 0 985 0 9 4 0 2 0 0 0]
[ 11 1 892 7 38 0 51 0 0 0]
[ 14 11 12 899 19 0 44 0 1 0]
[ 1 1 47 23 870 0 57 0 1 0]
[ 0 0 0 0 0 974 0 20 0 6]
[ 57 0 44 18 48 0 828 0 5 0]
[ 0 0 0 0 0 2 0 992 1 5]
[ 3 0 1 5 2 2 2 3 982 0]
[ 1 0 0 0 0 7 0 68 0 924]]
F1 점수: 0.915
Process finished with exit code 0
c) 결론
EPOCH 강화학습을 변화시키는 데서 얻는 결과는 다음과 같이 변화한다.
EPOCH | 시간 | 정확도 | 혼동행렬 |
0 | 0.1sec | 13.8% | 3과는 다르게 대각선이 아닌 몰려있는 숫자가 많음 |
3 | 25.6sec | 88.21% | 대각선 이외의 수치는 균일하게 낮은 편 |
20 | 184.7sec | 91.55% | 3일때보다 대각행렬 이외의 숫자들이 더 낮은 경향이 있음 |
학습을 여러번 시키면 정확도가 상승한다. 하지만, 6배 이상 늘린거에 비해 정확도의 개선이 엄청 뛰어나지는 것은 아니고, 시간은 훨씬 많이 늘어났다.
적절한 학습 수치 혹은 데이터셋에서 최적화 할 수 있는 데이터셋이 필요한 것 같다.
2. 최적화 방법 교체
알고리즘별 최적화는 다음과 같이 요약된다 하지만 실제로 수치를 보자.
a) SGD로 변경
기존에 사용된 것은 Adam이다. 이를 SGD로 변경해보자. 예상은 정확도가 조금 더 떨어지고 시간은 비슷할 것 같다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 9s 45ms/step - loss: 1.8648 - acc: 0.4335
Epoch 2/3
200/200 [==============================] - 9s 45ms/step - loss: 0.8996 - acc: 0.6692
Epoch 3/3
200/200 [==============================] - 9s 45ms/step - loss: 0.7484 - acc: 0.7279
총 학습시간: 27.6초
최종 정확도: 71.75%
혼동 행렬
[[638 23 2 80 3 1 233 0 20 0]
[ 0 865 10 83 7 0 33 0 2 0]
[ 2 4 548 5 77 1 352 0 11 0]
[ 16 143 0 666 17 1 153 0 4 0]
[ 0 18 329 34 266 0 347 0 6 0]
[ 1 0 0 1 0 774 1 120 5 98]
[ 98 17 103 40 37 0 681 0 24 0]
[ 0 0 0 0 0 39 0 875 0 86]
[ 1 2 2 8 2 7 54 5 918 1]
[ 0 0 0 1 0 9 0 44 2 944]]
F1 점수: 0.718
Process finished with exit code 0
정확도 71.75%로 줄어들었고 학습시간은 27.6초로 조금 늘어났다.
혼동행렬 또한 크게 상승한 300대가 대각 행렬 이외에 보인다.
b) RMSProp으로 변경
이번에는 RMSProp으로 변경해보자.
RMSProp은 RNN에서 많이 사용되는 알고리즘이다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 9s 46ms/step - loss: 0.6091 - acc: 0.7801
Epoch 2/3
200/200 [==============================] - 9s 46ms/step - loss: 0.3762 - acc: 0.8645
Epoch 3/3
200/200 [==============================] - 9s 46ms/step - loss: 0.3188 - acc: 0.8856
총 학습시간: 28.1초
최종 정확도: 87.70%
혼동 행렬
[[932 0 15 15 2 1 24 0 11 0]
[ 3 974 0 17 2 0 2 0 2 0]
[ 27 2 902 8 30 0 27 0 4 0]
[ 57 10 14 880 14 0 18 0 7 0]
[ 2 3 198 41 687 0 67 0 2 0]
[ 0 0 0 0 0 969 0 26 0 5]
[243 2 139 20 53 0 526 0 17 0]
[ 0 0 0 0 0 7 0 980 1 12]
[ 3 2 4 2 1 2 2 4 979 1]
[ 0 0 0 0 0 6 0 52 1 941]]
F1 점수: 0.877
Process finished with exit code 0
c) 결론
최적화 알고리즘을 변화하는데서 얻는 결과는 다음과 같이 변화한다.
Algorithm | 시간 | 정확도 | 혼동행렬 |
Adam | 25.6sec | 88.21% | 100대 두어개 외에는 낮은 상태 |
SGD | 27.6sec | 71.75% | 대각선 이외의 값이 300대가 관찰 |
RMSProp | 28.1sec | 87.70% | 200대 수치 하나와 100대 하나를 제외하고는 낮은 수치 |
전체적으로 CNN 학습에서는 Adam을 많이 쓰는 이유가 나온 것 같다.
정확도도 높은 편이고 시간도 상대적으로 적게 걸리는 편이다.
시간은 큰 차이는 안났지만 정확도는 꽤 유의미하게 난 것 같다.
3. 손실 함수 교체
손실 함수를 crossentropy에서 이전에 DNN에서 사용했던 mse 그리고 possion으로 변경해보자.
a) MSE
MSE는 숫자를 맞추는 회귀문제에 사용된다. 집값 예측에 사용했을 때 사용했었다.
분류 문제에서 과연 효율적일까?
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 9s 45ms/step - loss: 0.0304 - acc: 0.7872
Epoch 2/3
200/200 [==============================] - 9s 43ms/step - loss: 0.0187 - acc: 0.8728
Epoch 3/3
200/200 [==============================] - 9s 43ms/step - loss: 0.0164 - acc: 0.8881
총 학습시간: 26.7초
최종 정확도: 88.50%
혼동 행렬
[[770 1 22 82 8 3 99 0 15 0]
[ 0 960 1 32 4 0 1 0 2 0]
[ 11 0 790 19 119 0 59 0 2 0]
[ 3 3 7 947 15 0 21 0 4 0]
[ 1 1 35 57 848 0 55 0 3 0]
[ 0 0 0 1 0 974 0 18 0 7]
[ 90 0 69 60 91 0 670 0 20 0]
[ 0 0 0 0 0 16 0 956 1 27]
[ 0 1 3 7 2 3 4 2 978 0]
[ 0 0 0 1 0 4 0 37 1 957]]
F1 점수: 0.885
Process finished with exit code 0
학습 시간은 거의 차이가 나지 않았지만, MSE가 조금 더 정확도가 미세하게 높았습니다. 시작점이 어디냐에 따라 오차가 있는 것을 감안하면 큰 차이가 안난다고 결론을 내릴 수 있습니다. 다만 분류 문제에서는 crossentropy가 대체적으로 더 정확해서 MSE를 덜 사용한다고 한다.
어느게 더 나은지는 실험해보고 정해줄 정도의 차이인 것 같다.
b) Possion으로 변경
이번에는 Possion으로 변경해보자.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 9s 43ms/step - loss: 0.1605 - acc: 0.7835
Epoch 2/3
200/200 [==============================] - 9s 44ms/step - loss: 0.1369 - acc: 0.8701
Epoch 3/3
200/200 [==============================] - 9s 44ms/step - loss: 0.1315 - acc: 0.8888
총 학습시간: 26.6초
최종 정확도: 88.31%
혼동 행렬
[[910 0 13 18 11 1 38 0 9 0]
[ 2 981 0 10 4 0 1 0 2 0]
[ 23 1 822 8 108 0 35 0 3 0]
[ 29 22 10 849 55 0 31 0 4 0]
[ 1 3 53 13 902 0 27 0 1 0]
[ 0 0 0 1 0 970 0 20 0 9]
[203 5 101 18 153 0 509 0 11 0]
[ 0 0 0 0 0 17 0 952 0 31]
[ 5 2 2 4 5 3 3 3 973 0]
[ 0 0 0 0 0 4 0 32 1 963]]
F1 점수: 0.883
Process finished with exit code 0
의외로 정확도에서는 큰 차이가 나지 않았다. 시간은 1초정도 더 소요되었다.
c) 결론
손실 함수를 교체하는데서 얻는 결과는 다음과 같이 변화한다.
Function | 시간 | 정확도 | 혼동행렬 |
categorical_crossentropy | 25.6sec | 88.21% | 대각 행렬 이외에 100대 두어개 외에는 낮은 상태 |
MSE | 26.7sec | 88.50% | 대각 행렬 이외에 100단위는 보이지 않는 99까지 있는 상태 |
possion | 26.6sec | 88.31% | 대각 행렬 이외에 200대, 100대가 하나씩 보이는 상태 |
4. 합성곱 필터 사이즈 조절
현재는 2*2 필터로 거르고 있는데, 이 필터를 변경하면 어떻게 될까?
- Convoltion에서 필터, kernal의 값은 학습이 되는 가중치이다.
- CNN 정확도 증가가 가능하다.
- 하지만 학습 시간이 증가할 것이다.
a) 5*5
5*5로 변경하고 돌리면 다음과 같다.
CNN 요약
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) 51264
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 454,922
Trainable params: 454,922
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 16s 80ms/step - loss: 0.5799 - acc: 0.7904
Epoch 2/3
200/200 [==============================] - 15s 77ms/step - loss: 0.3526 - acc: 0.8737
Epoch 3/3
200/200 [==============================] - 15s 75ms/step - loss: 0.3036 - acc: 0.8909
총 학습시간: 47.1초
최종 정확도: 88.95%
혼동 행렬
[[857 0 14 16 7 3 85 0 17 1]
[ 2 973 0 18 3 0 2 0 2 0]
[ 13 1 779 6 125 0 74 0 2 0]
[ 18 4 14 892 37 0 28 0 7 0]
[ 1 1 47 30 868 0 51 0 2 0]
[ 0 0 0 0 0 979 0 15 0 6]
[147 2 54 25 97 0 656 0 19 0]
[ 0 0 0 0 0 23 0 953 0 24]
[ 1 1 1 4 4 2 1 4 982 0]
[ 0 0 0 0 0 4 1 39 0 956]]
F1 점수: 0.889
Process finished with exit code 0
Total Params가 454,922로 증가했다. (기존 411,242)
정확도는 88.9%로 증가했고 학습시간은 47.1초로 느려졌다.
하지만 정확도는 0.74%로 매우 적게 증가했다.
b) 1 * 1
1 * 1로 변경하면 시간은 짧아지고 정확도는 내려갈 것이다.
결과는 다음과 같다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 64
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 2112
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 405,002
Trainable params: 405,002
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 8s 38ms/step - loss: 0.7421 - acc: 0.7362
Epoch 2/3
200/200 [==============================] - 7s 37ms/step - loss: 0.5026 - acc: 0.8166
Epoch 3/3
200/200 [==============================] - 7s 36ms/step - loss: 0.4659 - acc: 0.8297
총 학습시간: 22.6초
최종 정확도: 82.91%
혼동 행렬
[[748 8 5 61 4 3 155 0 16 0]
[ 1 906 8 63 5 0 15 0 2 0]
[ 11 1 714 11 149 1 105 0 8 0]
[ 14 37 11 862 26 1 47 0 2 0]
[ 0 5 108 49 717 1 112 0 8 0]
[ 1 0 0 1 0 953 0 23 2 20]
[139 6 101 43 97 0 584 0 30 0]
[ 0 0 0 0 0 56 0 889 0 55]
[ 0 1 7 2 2 4 14 4 965 1]
[ 0 0 0 0 0 13 0 33 1 953]]
F1 점수: 0.829
Process finished with exit code 0
생각보다 정확도가 많이 떨어졌고, 시간은 적게 짧아졌다.
c) 결론
Convolution Filer Size를 교체하면 다음과 같다.
Convolution Filer Size | 시간 | 정확도 | Total Params |
2 * 2 | 25.6sec | 88.21% | 411,242 |
5 * 5 | 47.1sec | 88.95% | 454,922 |
1 * 1 | 22.6sec | 82.91% | 405,002 |
필터 수를 늘렸을 때 획기적인 변화는 감지되지 않는다. 다만 Color 사진의 경우에는 유의미하게 변한다고 한다. 현 이미지는 흑백 이미지라서 그런 것이다.
5. CNN 채널 수 조절 (Convolustion Channel filters)
Convolution에서 출력 채널의 숫자는 필터의 숫자와 같은 개념이다.
- 채널 감소 = 필터 숫자 감소
- 가중치도 감소하고 정확도도 감소할 것이다.
- 학습 시간도 감소될 것이다.
a) 1/4로 줄인 경우
- 32 -> 8 / 64 -> 16으로 필터 수를 줄였다.
- 결과는 다음과 같다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 8) 40
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 8) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 16) 528
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 16) 0
_________________________________________________________________
flatten (Flatten) (None, 784) 0
_________________________________________________________________
dense (Dense) (None, 128) 100480
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 102,338
Trainable params: 102,338
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 3s 16ms/step - loss: 0.7718 - acc: 0.7374
Epoch 2/3
200/200 [==============================] - 3s 16ms/step - loss: 0.4322 - acc: 0.8456
Epoch 3/3
200/200 [==============================] - 3s 16ms/step - loss: 0.3819 - acc: 0.8647
총 학습시간: 10.0초
최종 정확도: 87.00%
혼동 행렬
[[854 0 12 52 6 1 65 0 10 0]
[ 2 973 0 16 6 0 2 0 1 0]
[ 22 1 807 8 91 1 67 0 3 0]
[ 34 22 7 876 33 0 25 0 3 0]
[ 1 5 100 41 779 1 72 0 1 0]
[ 1 0 0 0 0 932 1 45 1 20]
[151 3 84 36 99 1 619 0 7 0]
[ 0 0 0 0 0 10 0 972 1 17]
[ 5 3 3 8 5 3 13 6 954 0]
[ 0 0 0 0 0 8 0 57 1 934]]
F1 점수: 0.870
Process finished with exit code 0
Total params가 102,338개로 거의 1/4이 줄었다.
그런데 수치는 87%로 약간 떨어졌고 시간은 1/4로 줄었다.
b) 4배로 늘린 경우
- 32 -> 128 / 64 -> 256으로 필터 수를 늘렸다.
- 결과는 다음과 같다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 128) 640
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 128) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 256) 131328
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 256) 0
_________________________________________________________________
flatten (Flatten) (None, 12544) 0
_________________________________________________________________
dense (Dense) (None, 128) 1605760
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 1,739,018
Trainable params: 1,739,018
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 38s 190ms/step - loss: 0.5159 - acc: 0.8162
Epoch 2/3
200/200 [==============================] - 38s 190ms/step - loss: 0.3164 - acc: 0.8873
Epoch 3/3
200/200 [==============================] - 37s 186ms/step - loss: 0.2710 - acc: 0.9018
총 학습시간: 114.1초
최종 정확도: 89.50%
혼동 행렬
[[839 1 17 42 3 1 90 0 6 1]
[ 0 976 0 20 0 0 2 0 2 0]
[ 13 1 823 13 57 0 93 0 0 0]
[ 9 5 5 949 6 0 25 0 1 0]
[ 1 2 58 70 753 0 116 0 0 0]
[ 0 0 0 1 0 965 0 23 0 11]
[116 3 40 41 45 0 745 0 10 0]
[ 0 0 0 0 0 7 0 956 0 37]
[ 2 2 2 6 1 1 3 4 979 0]
[ 0 0 0 0 0 4 1 30 0 965]]
F1 점수: 0.895
Process finished with exit code 0
c) 결론
Convolution Channel을 교체하면 다음과 같다.
Convolution Filers | 시간 | 정확도 | Total Params |
32, 64 | 25.6sec | 88.21% | 411,242 |
8, 16 | 10.0sec | 87.00% | 102,338 |
128, 256 | 114.1sec | 89.50% | 1,739,018 |
정직하게 Filter가 늘어나면 연산 시간이 길어지고 정확도는 향상된다. 다만 적정한 필터 수여야 효율적일 것 같다.
Total Params도 배수만큼 늘린 그대로 반영되었다.
6. 합성화 함수 교체
- relu는 음수부분은 0 양수는 1로 기울기가 고정된다.
a) Sigmoid
- Sigmoid 함수는 음수는 0에 수렴 양수도 0에 수렴한다.
- Sigmoid는 기울기 유실에 취약하다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 9s 46ms/step - loss: 2.1338 - acc: 0.2202
Epoch 2/3
200/200 [==============================] - 9s 45ms/step - loss: 0.7370 - acc: 0.7435
Epoch 3/3
200/200 [==============================] - 9s 45ms/step - loss: 0.5637 - acc: 0.7953
총 학습시간: 27.5초
최종 정확도: 80.25%
혼동 행렬
[[832 14 5 79 2 3 52 0 13 0]
[ 4 930 8 48 6 0 3 0 1 0]
[ 17 2 616 18 162 1 170 0 14 0]
[ 38 40 1 844 29 1 43 0 4 0]
[ 2 7 123 52 701 0 107 0 8 0]
[ 1 0 0 2 0 913 0 61 3 20]
[235 7 117 72 105 0 437 0 27 0]
[ 0 0 0 0 0 50 0 894 0 56]
[ 5 3 7 10 2 7 20 7 938 1]
[ 0 0 0 1 0 16 0 62 1 920]]
F1 점수: 0.802
Process finished with exit code 0
정확도는 약 8%가 감소되었다.
시간은 큰 차이가 나지 않았다.
기울기 유실이 심각하다.
b) tanh
- SIGMOID의 변형판으로 함수 중심점을 0으로 옮겨 최적화 과정에서 느려지는 것을 막았다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
200/200 [==============================] - 9s 44ms/step - loss: 0.5109 - acc: 0.8181
Epoch 2/3
200/200 [==============================] - 9s 44ms/step - loss: 0.3318 - acc: 0.8811
Epoch 3/3
200/200 [==============================] - 9s 45ms/step - loss: 0.2915 - acc: 0.8949
총 학습시간: 27.0초
최종 정확도: 88.41%
혼동 행렬
[[751 0 22 51 3 1 161 0 11 0]
[ 0 975 0 15 5 0 3 0 2 0]
[ 8 2 783 8 90 0 106 0 3 0]
[ 11 11 9 887 36 0 42 0 4 0]
[ 0 2 47 28 802 0 120 0 1 0]
[ 0 0 0 1 0 961 0 20 0 18]
[ 77 1 51 27 49 0 780 0 15 0]
[ 0 0 0 0 0 11 0 965 1 23]
[ 4 1 1 6 2 1 6 5 974 0]
[ 0 0 0 0 0 3 0 33 1 963]]
F1 점수: 0.884
Process finished with exit code 0
c) 결론
Activation Function을 교체하면 다음과 같다.
Activation Function | 시간 | 정확도 | 혼동 행렬 |
RELU | 25.6sec | 88.21% | - |
SIGMOID | 27.5sec | 80.25% | 대각선 행렬 이외의 수치가 증가 |
TANH | 27.0sec | 88.41% | 대각행렬 수치가 비슷하다. (100단위 3개) |
RELU가 시간 대비 정확도가 가장 균일함을 보였으며 TANH는 수치적으로 정확도가 높게 나왔지만 이론상 SIGMOID의 문제점이 해결 된 것이 아니라서 RELU가 좀 더 낫다는 사실을 알 수 있다.
7. 데이터 셋 숫자
- 데이터 양과 질은 기계학습에서 중요한 성패를 가른다.
- 학습 데이터를 줄이면 그만큼 정확도에 영향을 미친다.
- numpy의 indexing 기법으로 사용
a) 30000
- 수치가 줄어드는 만큼 줄어들 것이다.
CNN 요약
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 32) 160
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 8256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 3136) 0
_________________________________________________________________
dense (Dense) (None, 128) 401536
_________________________________________________________________
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 411,242
Trainable params: 411,242
Non-trainable params: 0
_________________________________________________________________
CNN 학습 시작
Epoch 1/3
100/100 [==============================] - 4s 45ms/step - loss: 0.7475 - acc: 0.7338
Epoch 2/3
100/100 [==============================] - 4s 45ms/step - loss: 0.4383 - acc: 0.8416
Epoch 3/3
100/100 [==============================] - 4s 45ms/step - loss: 0.3823 - acc: 0.8632
총 학습시간: 13.9초
최종 정확도: 85.81%
혼동 행렬
[[819 0 11 61 11 2 87 0 9 0]
[ 1 973 1 20 3 0 0 0 2 0]
[ 15 1 672 15 211 1 83 0 2 0]
[ 23 17 5 882 39 0 34 0 0 0]
[ 1 5 27 34 900 0 32 0 1 0]
[ 1 0 0 3 0 953 0 24 0 19]
[146 4 59 36 188 1 559 0 7 0]
[ 0 0 0 0 0 29 0 904 1 66]
[ 8 3 1 8 8 3 12 4 952 1]
[ 0 0 0 1 0 4 1 27 0 967]]
F1 점수: 0.858
Process finished with exit code 0
정확도가 미세하게 감소하고
시간은 절반이 줄었고
학습 시간은 절반으로 줄었다.
b) 학습용 데이터 추가
- 추가할 여력이 없어서 실습하지는 않았지만 정확도가 올라가고 시간이 올라갈 것이다.
- 하지만 큰 폭의 상승은 없을 것이다.
c) 결론
DataSet을 교체하면 다음과 같다.
DataSet | 시간 | 정확도 | 혼동 행렬 |
60000 | 25.6sec | 88.21% | - |
30000 | 13.9sec | 85.81% | 대각시간이외의 위치에서 증가 |