합성곱 신경망을 이용한 이미지 분류
합성곱 신경망을 이용한 이미지 분류
from tensorflow import keras
from sklearn.model_selection import train_test_split
(train_input, train_target), (test_input, test_target) = \
keras.datasets.fashion_mnist.load_data()
train_scaled = train_input.reshape(-1, 28, 28, 1) / 255.0
# 48000x28x28 에서 48000x28x28x1로 체널 추가 3차원에서 4차원으로 변경
# 이미지 데이터라서 /255 로 나누어서 정규화 진행
train_scaled, val_scaled, train_target, val_target = train_test_split(
train_scaled, train_target, test_size=0.2, random_state=42)
# 훈련 세트와 검증세트 나누기
첫 번째 합성곱 층
model = keras.Sequential()
# 첫 번째 합성곱 층
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same', input_shape=(28,28,1)))
# 32개 필터(커널)사용, 필터 크기 3, 활성화 함수 :relu, same padding, 입력배열의 크기 지정(배치차원은 지정하지 않는다.)
# kernel_size는 자동으로 체널의 크기에 맞추어서 바뀌어진다.위의 경우에는 체널1개를 추가했으므로 3x3x1 필터로 만들어진다.
model.add(keras.layers.MaxPooling2D(2))
#MaxPooling2D 평균 풀링보다 더 선호된다.
두 번째 합성곱 층과 완전 연결 층
# 두 번째 합성곱 층
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu', padding='same'))
# 64개 필터 생성, 필터 크기 3x3 그냥 3으로 써도 된다., relu 활성화 함수, same padding , 두 번째 합성곱이기 때문에 input_shape는 필요 없다.
model.add(keras.layers.MaxPooling2D(2))
# 완전 연결 층
model.add(keras.layers.Flatten()) # 입력 배열을 1차원으로 펼치는 역할
model.add(keras.layers.Dense(100, activation='relu'))
# 1차원으로 펼쳐진 뉴런과 100개를 완전 연결
model.add(keras.layers.Dropout(0.4)) # 과대적합을 막기 위해 40% dropout 지정
model.add(keras.layers.Dense(10, activation='softmax')) # 10개의 최종 출력층
model.summary()
모델 summary
-
첫 번째 합성곱 필터 32개
파라미터 320 = 3x3 커널 32개 +32개 절편
-
두번째 합성곱 필터 64개
파라미터 18496 = 3x3x32 커널 64개(18,432) +64개 절편
-
flatten층으로 1차원으로 펼친 뉴런과 100개 뉴런의 은닉층 완전연결
3136x100+100(절편)
-
10개 뉴런 출력층
100x10+10(절편)
합성곱 층은 적은 개수의 파라미터로 이미지의 특징을 잡아낸다.
keras plot model
keras.utils.plot_model(model)
keras.utils.plot_model(model, show_shapes=True, to_file='cnn-architecture.png', dpi=300)
컴파일과 훈련
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
# adam 옵티마이저 , 타깃값이 정수 레이블이기 때문에 sparse_를 붙혀준다. , 정확도 출력위해 accuracy추가
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-cnn-model.h5', save_best_only=True)
# 체크포인트 만들기
early_stopping_cb = keras.callbacks.EarlyStopping(patience=2, restore_best_weights=True)
# 검증 세트의 점수가 2회 이상 감소하지 않으면 조기 종료 이 이전의 가중치로 복원
history = model.fit(train_scaled, train_target, epochs=20,
validation_data=(val_scaled, val_target),
callbacks=[checkpoint_cb, early_stopping_cb])
# 훈련
7에포크부터 val값이 증가하므로 과대적합이 시작된다고 해석할 수 있다.
6번째 값으로 복원해서 사용하는 것으로 보인다.
평가와 예측
model.evaluate(val_scaled, val_target)
#375/375 [==============================] - 1s 3ms/step - loss: 0.2163 - accuracy: 0.9210
#[0.21628820896148682, 0.9210000038146973]
# 손실값 0.2 정확도 92
plt.imshow(val_scaled[0].reshape(28, 28), cmap='gray_r')
plt.show()
preds = model.predict(val_scaled[0:1])
print(preds)
#1/1 [==============================] - 0s 138ms/step
#[[6.7846774e-12 8.1426743e-22 8.9696543e-16 7.7117090e-15 6.6757140e-14
# 1.4335832e-13 3.7601382e-14 3.6749163e-12 1.0000000e+00 1.8052020e-13]]
# 이 이미지의 확률을 추측해본 것
# 마지막 소프트맥스함수를 통과한 10개의 확률값을 출력한다.
# 9번째 이미지(가방)을 매우 높은 확률로 추측하는 것을 볼 수 있다.
테스트 세트 점수
test_scaled = test_input.reshape(-1, 28, 28, 1) / 255.0
# train 데이터와 똑같이 정규화
model.evaluate(test_scaled, test_target)
#313/313 [==============================] - 3s 9ms/step - loss: 0.2423 - accuracy: 0.9156
#[0.24227263033390045, 0.9156000018119812]
# 검증 세트보다는 정확도가 조금 낮게 나옴
참고
박해선,혼자 공부하는 머신러닝, 한빛미디어, 2021,444~463p