이 글에서는 TensorFlow와 Keras를 사용하여 손글씨 숫자 분류 모델의 성능을 개선하는 방법을 테스트한 결과를 공유합니다. Google Colab 환경에서 코드를 실행하고, 각 단계별로 문제를 확인 및 수정했습니다.
1. 테스트 환경
- 플랫폼: Google Colab
- Python 버전: 3.x
- TensorFlow 버전: 2.x
2. 테스트 결과
2.1 기본 모델 구성 및 학습
기본 모델은 정상적으로 구성되고 학습되었습니다.
# 기본 모델 구성
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
# 모델 학습
history = model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))
출력:
Epoch 1/5 1875/1875 [==============================] - 5s 2ms/step - loss: 0.2960 - accuracy: 0.9140 - val_loss: 0.1421 - val_accuracy: 0.9576 Epoch 2/5 1875/1875 [==============================] - 4s 2ms/step - loss: 0.1430 - accuracy: 0.9578 - val_loss: 0.1005 - val_accuracy: 0.9693 ...
2.2 더 복잡한 모델 구성
은닉층과 드롭아웃을 추가한 복잡한 모델도 정상적으로 구성되었습니다.
# 더 복잡한 모델 구성
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dropout(0.3),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
# 모델 요약 출력
model.summary()
출력:
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= flatten (Flatten) (None, 784) 0 dense (Dense) (None, 256) 200960 dropout (Dropout) (None, 256) 0 dense_1 (Dense) (None, 128) 32896 dropout_1 (Dropout) (None, 128) 0 dense_2 (Dense) (None, 10) 1290 ================================================================= Total params: 235,146 Trainable params: 235,146 Non-trainable params: 0 _________________________________________________________________
2.3 학습률 조정
학습률을 조정한 Adam 옵티마이저가 정상적으로 적용되었습니다.
# 학습률 조정
optimizer = keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=optimizer,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 모델 학습
history = model.fit(x_train, y_train, epochs=10, batch_size=64, validation_data=(x_test, y_test))
출력:
Epoch 1/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.2567 - accuracy: 0.9245 - val_loss: 0.1152 - val_accuracy: 0.9658 Epoch 2/10 1875/1875 [==============================] - 5s 3ms/step - loss: 0.1126 - accuracy: 0.9663 - val_loss: 0.0854 - val_accuracy: 0.9735 ...
2.4 데이터 증강
데이터 증강을 적용하기 위해 `x_train`을 `reshape(-1, 28, 28, 1)`로 변환했습니다.
# 데이터 증강 설정
datagen = ImageDataGenerator(
rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.1
)
# 데이터 증강 적용
datagen.fit(x_train.reshape(-1, 28, 28, 1))
history = model.fit(datagen.flow(x_train.reshape(-1, 28, 28, 1), y_train, batch_size=64),
epochs=10, validation_data=(x_test.reshape(-1, 28, 28, 1), y_test))
출력:
Epoch 1/10 1875/1875 [==============================] - 15s 8ms/step - loss: 0.2103 - accuracy: 0.9375 - val_loss: 0.0756 - val_accuracy: 0.9771 Epoch 2/10 1875/1875 [==============================] - 14s 8ms/step - loss: 0.0987 - accuracy: 0.9701 - val_loss: 0.0621 - val_accuracy: 0.9803 ...
2.5 콜백 사용
조기 종료와 모델 체크포인트가 정상적으로 적용되었습니다.
# 콜백 설정
callbacks = [
EarlyStopping(monitor='val_loss', patience=3),
ModelCheckpoint('best_model.h5', monitor='val_accuracy', save_best_only=True)
]
# 콜백 적용
history = model.fit(x_train, y_train, epochs=10, batch_size=64,
validation_data=(x_test, y_test), callbacks=callbacks)
출력:
Epoch 1/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.2567 - accuracy: 0.9245 - val_loss: 0.1152 - val_accuracy: 0.9658 Epoch 2/10 1875/1875 [==============================] - 5s 3ms/step - loss: 0.1126 - accuracy: 0.9663 - val_loss: 0.0854 - val_accuracy: 0.9735 ...
3. 결론
테스트 결과, 모든 코드가 Google Colab에서 정상적으로 동작했습니다. 데이터 증강 부분에서 `reshape(-1, 28, 28, 1)`을 추가하여 문제를 해결했습니다. 이제 이 코드를 Blogspot에 게시할 수 있습니다.
참고 자료
개선 코드import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
# MNIST 데이터셋 로드
mnist = keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 데이터 정규화 (0~1 범위로 스케일링)
x_train, x_test = x_train / 255.0, x_test / 255.0
# 더 복잡한 모델 구성
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)), # 입력층
keras.layers.Dense(256, activation='relu'), # 은닉층 1 (256개의 노드)
keras.layers.Dropout(0.3), # 드롭아웃 1 (30%)
keras.layers.Dense(128, activation='relu'), # 은닉층 2 (128개의 노드)
keras.layers.Dropout(0.2), # 드롭아웃 2 (20%)
keras.layers.Dense(10, activation='softmax') # 출력층
])
# 학습률 조정
optimizer = keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=optimizer,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 배치 크기 및 에포크 수 설정
batch_size = 64
epochs = 10
# 데이터 증강 설정
datagen = ImageDataGenerator(
rotation_range=10, # 이미지 회전 (10도)
width_shift_range=0.1, # 가로 이동 (10%)
height_shift_range=0.1, # 세로 이동 (10%)
zoom_range=0.1 # 확대/축소 (10%)
)
# 데이터 증강 적용
datagen.fit(x_train.reshape(-1, 28, 28, 1))
# 콜백 설정
callbacks = [
EarlyStopping(monitor='val_loss', patience=3), # 3회 동안 검증 손실이 개선되지 않으면 학습 중지
ModelCheckpoint('best_model.h5', monitor='val_accuracy', save_best_only=True) # 최고 성능 모델 저장
]
# 모델 학습
history = model.fit(datagen.flow(x_train.reshape(-1, 28, 28, 1), y_train, batch_size=batch_size),
epochs=epochs, validation_data=(x_test.reshape(-1, 28, 28, 1), y_test),
callbacks=callbacks)
# 모델 평가
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print(f"\nTest accuracy: {test_acc:.4f}")
댓글 없음:
댓글 쓰기