6. MNIST 예제를 통해 모델 구성하기
- keras.datasets에 포함되어 있는 데이터셋
- modules import
import tensorflow as tf
from tensorflow.keras.datasets.mnist import load_data
from tensorflow.keras.models import Sequential
from tensorflow.keras import models
from tensorflow.keras.layers import Dense, Input, Flatten
from tensorflow.keras.utils import to_categorical, plot_model
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt
- 데이터셋 로드
- MNIST 데이터셋을 로드
- Train Data 중 30%를 검증 데이터(validation data)로 사용
tf.random.set_seed(111)
(x_train_full, y_train_full), (x_test, y_test) = load_data(path = 'mnist.npz')
x_train, x_val, y_train, y_val = train_test_split(x_train_full, y_train_full, test_size = 0.3, random_state = 111)
- 데이터 확인
# 데이터 형태 확인
num_x_train = (x_train.shape[0])
num_x_val = (x_val.shape[0])
num_x_test = (x_test.shape[0])
print("학습 데이터: {}\t레이블: {}".format(x_train_full.shape, y_train_full.shape))
# train과 val 데이터로 split 한 뒤의 데이터
print("학습 데이터: {}\t레이블: {}".format(x_train.shape, y_train.shape))
print("검증데이터: {}\t레이블: {}".format(x_val.shape, y_val.shape))
print("테스트 데이터: {}\t레이블: {}".format(x_test.shape, y_test.shape))
# 출력 결과
학습 데이터: (60000, 28, 28) 레이블: (60000,)
학습 데이터: (42000, 28, 28) 레이블: (42000,)
검증데이터: (18000, 28, 28) 레이블: (18000,)
테스트 데이터: (10000, 28, 28) 레이블: (10000,
# 랜덤으로 5개의 데이터 추출하여 데이터 확인
num_sample = 5
random_idxs = np.random.randint(60000, size = num_sample)
plt.figure(figsize = (14, 8))
for i, idx in enumerate(random_idxs):
img = x_train_full[idx, :]
label = y_train_full[idx]
plt.subplot(1, len(random_idxs), i+1)
plt.imshow(img)
plt.title("Indes: {}, Label: {}".format(idx, label))
- 데이터 전처리
- Normalization
# 최대 255의 값으로 이루어진 x데이터를 255로 나누어 0과 1사이로 정규화
x_train = x_train / 255.
x_val = x_val / 255.
x_test = x_test / 255.
# 정수형인 y 레이블을 원-핫인코딩
y_train = to_categorical(y_train)
y_val = to_categorical(y_val)
y_test = to_categorical(y_test)
- 모델 구성(Sequential)
model = Sequential([Input(shape = (28, 28), name = 'input'),
Flatten(input_shape = [28, 28], name= 'flatten'),
Dense(100, activation = 'relu', name = 'dense1'),
Dense(64, activation = 'relu', name = 'dense2'),
Dense(32, activation = 'relu', name = 'dense3'),
Dense(10, activation = 'softmax', name = 'output')])
model.summary()
# 출력 결과
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense1 (Dense) (None, 100) 78500
dense2 (Dense) (None, 64) 6464
dense3 (Dense) (None, 32) 2080
output (Dense) (None, 10) 330
=================================================================
Total params: 87,374
Trainable params: 87,374
Non-trainable params: 0
_________________________________________________________________
# 각 레이어의 형태까지 출력
plot_model(model, show_shapes = True)
- 모델 컴파일
model.compile(loss = 'categorical_crossentropy',
optimizer = 'sgd',
metrics = ['accuracy'])
- 모델 학습
- 모델 시각화를 위해 history라는 변수에 학습 과정을 담음
history = model.fit(x_train, y_train,
epochs = 50,
batch_size = 128,
validation_data = (x_val, y_val))
- 학습 결과 시각화
# history에 학습 과정이 저장되어 있는지 확인
history.history.keys()
# 출력 결과
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])
history_dict = history.history
loss = history_dict['loss']
val_loss = history_dict['val_loss']
epochs = range(1, len(loss) + 1)
fig = plt.figure(figsize = (12, 6))
ax1 = fig.add_subplot(1, 2, 1)
ax1.plot(epochs, loss, color = 'blue', label = 'train_loss')
ax1.plot(epochs, val_loss, color = 'red', label = 'val_loss')
ax1.set_title('Train and Validation Loss')
ax1.set_xlabel('Epochs')
ax1.set_ylabel('Loss')
ax1.grid()
ax1.legend()
accuracy = history_dict['accuracy']
val_accuracy = history_dict['val_accuracy']
ax2 = fig.add_subplot(1, 2, 2)
ax2.plot(epochs, accuracy, color = 'blue', label = 'train_accuracy')
ax2.plot(epochs, val_accuracy, color = 'red', label = 'val_accuracy')
ax2.set_title('Train and Validation Accuracy')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Accauracy')
ax2.grid()
ax2.legend()
plt.show()
- 모델 평가(1)
- evaluate()
model.evaluate(x_test, y_test)
# 출력 결과
313/313 [==============================] - 2s 6ms/step - loss: 0.1235 - accuracy: 0.9609
[0.12354850769042969, 0.9609000086784363]
- 학습된 모델을 통해 값 예측
pred_ys = model.predict(x_test)
print(pred_ys.shape)
np.set_printoptions(precision = 7)
# 가장 첫번째(인덱스가 0인)데이터가 0~9까지 총 10개의 정답 각각에 속할 확률 출력
print(pred_ys[0])
# 출력 결과
# 7일 확률이 0.99로 가장 높음
313/313 [==============================] - 3s 9ms/step
(10000, 10)
[3.5711932e-06 3.6218420e-08 4.6535680e-04 5.5227923e-04 1.9860077e-07
2.2765586e-07 2.0107932e-12 9.9897194e-01 1.8151616e-06 4.6298537e-06]
arg_pred_y = np.argmax(pred_ys, axis = 1)
plt.imshow(x_test[0])
plt.title("predicted label: {}".format(arg_pred_y[0]))
plt.show()
- 모델 평가(2)
- 혼돈행렬(Confusion Matrix)
from sklearn.metrics import confusion_matrix
plt.figure(figsize = (8, 8))
cm = confusion_matrix(np.argmax(y_test, axis = -1), np.argmax(pred_ys, axis = -1))
sns.heatmap(cm, annot = True, fmt = 'd', cmap = 'Blues')
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.show()
- 모델 평가(3)
- 분류 보고서
from sklearn.metrics import classification_report
print(classification_report(np.argmax(y_test, axis = -1), np.argmax(pred_ys, axis = -1)))
7. 모델 저장과 복원
- save()
- load_model()
- (주의)
Sequential API, 함수형 API에서는 모델의 저장 및 로드가 가능하지만 서브클래싱 방식으로는 할 수 없음 - 서브클래싱 방식
아래의 두 가지를 통해 모델의 파아미터만 저장 및 로드
save_weights()
load_weights()
- JSON 형식
- model.to_json() (저장)
- tf.keras.models.model_from_json(file_path) (복원)
- YAML로 직렬화
- model.to_yaml() (저장)
- tf.keras.models.model_from_yaml(file_path) (복원)
# 모델 저장
model.save('mnist_model.h5')
# 모델 복원
loaded_model = models.load_model('mnist_model.h5')
loaded_model.summary()
# 출력 결과
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense1 (Dense) (None, 100) 78500
dense2 (Dense) (None, 64) 6464
dense3 (Dense) (None, 32) 2080
output (Dense) (None, 10) 330
=================================================================
Total params: 87,374
Trainable params: 87,374
Non-trainable params: 0
_________________________________________________________________
8. 콜백
- fit() 함수의 callbacks 매개변수를 사용하여 케라스가 훈련의 시작이나 끝에 호출할 객체 리스트를 지정할 수 있음
- 여러 개 사용 하능
- ModelCheckpoint
- tf.keras.callbacks.ModelCheckpoint
- 정기적으로 모델의 체크포인트를 저장하고, 문제가 발생할 때 복구하는데 사용
- EarlyStopping
- tf.keras.callbacks.EarlyStopping
- 검증 성능이 한동안 개선되지 않을 경우 학습을 중단할 때 사용
- LearningRateSchedular
- tf.keras.callbacks.LearningRateScheduler
- 최적화를 하는 동안 학습률(learning_rate)를 동적으로 변경할 때 사용
- TensorBoard
- tf.keras.callbacks.TensorBoard
- 모델의 경과를 모니터링할 때 사용
# 위의 MNIST 데이터와 모델 그대로 사용(함수로 묶어서 사용)
(x_train_full, y_train_full), (x_test, y_test) = load_data(path = 'mnist.npz')
x_train, x_val, y_train, y_val = train_test_split(x_train_full, y_train_full, test_size = 0.3, random_state = 111)
print("학습 데이터: {}\t레이블: {}".format(x_train_full.shape, y_train_full.shape))
print("학습 데이터: {}\t레이블: {}".format(x_train.shape, y_train.shape))
print("검증데이터: {}\t레이블: {}".format(x_val.shape, y_val.shape))
print("테스트 데이터: {}\t레이블: {}".format(x_test.shape, y_test.shape))
x_train = x_train / 255.
x_val = x_val / 255.
x_test = x_test / 255.
y_train = to_categorical(y_train)
y_val = to_categorical(y_val)
y_test = to_categorical(y_test)
def build_model():
model = Sequential([Input(shape = (28, 28), name = 'input'),
Flatten(input_shape = [28, 28], name= 'flatten'),
Dense(100, activation = 'relu', name = 'dense1'),
Dense(64, activation = 'relu', name = 'dense2'),
Dense(32, activation = 'relu', name = 'dense3'),
Dense(10, activation = 'softmax', name = 'output')])
model.compile(loss = 'categorical_crossentropy',
optimizer = 'sgd',
metrics = ['accuracy'])
return model
model = build_model()
model.summary()
# 출력 결과
학습 데이터: (60000, 28, 28) 레이블: (60000,)
학습 데이터: (42000, 28, 28) 레이블: (42000,)
검증데이터: (18000, 28, 28) 레이블: (18000,)
테스트 데이터: (10000, 28, 28) 레이블: (10000,)
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense1 (Dense) (None, 100) 78500
dense2 (Dense) (None, 64) 6464
dense3 (Dense) (None, 32) 2080
output (Dense) (None, 10) 330
=================================================================
Total params: 87,374
Trainable params: 87,374
Non-trainable params: 0
_________________________________________________________________
# 콜백 라이브러리 import
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, LearningRateScheduler, TensorBoard
- ModelCheckpoint
check_point_cb = ModelCheckpoint('keras_mnist_model.h5')
history = model.fit(x_train, y_train, epochs = 10, callbacks = [check_point_cb])
# 출력 결과
Epoch 1/10
1313/1313 [==============================] - 8s 5ms/step - loss: 0.8994 - accuracy: 0.7532
Epoch 2/10
1313/1313 [==============================] - 6s 5ms/step - loss: 0.3294 - accuracy: 0.9059
Epoch 3/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.2614 - accuracy: 0.9247
Epoch 4/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.2208 - accuracy: 0.9360
Epoch 5/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.1919 - accuracy: 0.9437
Epoch 6/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.1696 - accuracy: 0.9507
Epoch 7/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.1511 - accuracy: 0.9565
Epoch 8/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.1356 - accuracy: 0.9611
Epoch 9/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.1229 - accuracy: 0.9646
Epoch 10/10
1313/1313 [==============================] - 4s 3ms/step - loss: 0.1122 - accuracy: 0.9674
loaded_model = load_model('keras_mnist_model.h5')
loaded_model.summary()
# 출력 결과
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense1 (Dense) (None, 100) 78500
dense2 (Dense) (None, 64) 6464
dense3 (Dense) (None, 32) 2080
output (Dense) (None, 10) 330
=================================================================
Total params: 87,374
Trainable params: 87,374
Non-trainable params: 0
_________________________________________________________________
- 최상의 모델만을 저장
- save_best_only = True
model = build_model()
cp = ModelCheckpoint('keras_best_model.h5', save_best_only = True)
history = model.fit(x_train, y_train, epochs = 10,
validation_data = (x_val, y_val), callbacks = [cp])
# 출력 결과
Epoch 1/10
1313/1313 [==============================] - 12s 8ms/step - loss: 0.8529 - accuracy: 0.7606 - val_loss: 0.3651 - val_accuracy: 0.8924
Epoch 2/10
1313/1313 [==============================] - 8s 6ms/step - loss: 0.3209 - accuracy: 0.9075 - val_loss: 0.2884 - val_accuracy: 0.9141
Epoch 3/10
1313/1313 [==============================] - 11s 8ms/step - loss: 0.2551 - accuracy: 0.9254 - val_loss: 0.2353 - val_accuracy: 0.9296
Epoch 4/10
1313/1313 [==============================] - 13s 10ms/step - loss: 0.2147 - accuracy: 0.9371 - val_loss: 0.2123 - val_accuracy: 0.9366
Epoch 5/10
1313/1313 [==============================] - 10s 8ms/step - loss: 0.1869 - accuracy: 0.9451 - val_loss: 0.1972 - val_accuracy: 0.9410
Epoch 6/10
1313/1313 [==============================] - 12s 9ms/step - loss: 0.1661 - accuracy: 0.9513 - val_loss: 0.1818 - val_accuracy: 0.9450
Epoch 7/10
1313/1313 [==============================] - 10s 8ms/step - loss: 0.1491 - accuracy: 0.9566 - val_loss: 0.1700 - val_accuracy: 0.9488
Epoch 8/10
1313/1313 [==============================] - 5s 4ms/step - loss: 0.1350 - accuracy: 0.9608 - val_loss: 0.1476 - val_accuracy: 0.9552
Epoch 9/10
1313/1313 [==============================] - 5s 4ms/step - loss: 0.1229 - accuracy: 0.9637 - val_loss: 0.1414 - val_accuracy: 0.9572
Epoch 10/10
1313/1313 [==============================] - 6s 4ms/step - loss: 0.1128 - accuracy: 0.9663 - val_loss: 0.1337 - val_accuracy: 0.9595
- EarlyStopping
- 일정 에포크(patience)동안 검증 세트에 대한 점수가 오르지 않으면 학습을 멈춤
- 모델이 향상되지 않으면 학습이 자동으로 중지되므로, epochs 숫자를 크게 해도 무방
- 학습이 끝난 후의 최상의 가중치를 복원하기 때문에 모델을 따로 복원할 필요없음
model = build_model()
cp = ModelCheckpoint('keras_best_model2.h5', save_best_only = True)
early_stopping_cb = EarlyStopping(patience = 3, monitor = 'val_loss',
restore_best_weights = True)
# 50번의 반복을 하며 가장 성능 좋은 모델을 저장함
# validation loss값을 보며 더 이상 돌지 않아도 된다고 판단하면 학습 중단
history = model.fit(x_train, y_train, epochs = 50,
validation_data = (x_val, y_val), callbacks = [cp, early_stopping_cb])
- 30번만에 학습을 중단하고 최적의 값으로 판
- LearningRateSchedular
def scheduler(epoch, learning_rate):
if epoch < 10:
return learning_rate
else:
return learning_rate * tf.math.exp(-0.1)
# learning rate 설정 전
model = build_model()
round(model.optimizer.lr.numpy(), 5)
# 출력 결과
0.01
# learning rate 설정 후
lr_scheduler_cb = LearningRateScheduler(scheduler)
history = model.fit(x_train, y_train, epochs = 15,
callbacks = [lr_scheduler_cb], verbose = 0)
round(model.optimizer.lr.numpy(), 5)
# 출력 결과
0.00607
- Tensorboard
- 텐서보드를 이용하여 학습과정 모니터링
- 텐서보드를 사용하기 위해 logs 폴더를 만들고, 학습이 진행되는 동안 로그 파일을 생성
TensorBoard(log_dir = '.logs', histogram_freq = 0, write_graph = True, write_images = True)
# 출력 결과
<keras.callbacks.TensorBoard at 0x1c034d086a0>
log_dir = '.logs'
tensor_board_cb = [TensorBoard(log_dir = log_dir, histogram_freq = 1, write_graph = True, write_images = True)]
model = build_model()
model.fit(x_train, y_train, batch_size = 32, validation_data = (x_val, y_val),
epochs = 30, callbacks = [tensor_board_cb])
# 출력 결과
- load하는데 시간 소요
- load가 안된다면 port 번호를 바꿔서 실행
- ex) %tensorboard --logdir {log_dir} port 8000
%load_ext tensorboard
%tensorboard --logdir {log_dir}
- 웹 환경에서 다양한 지표를 그래프로 확인 가능
'Python > Deep Learning' 카테고리의 다른 글
[딥러닝-케라스] 케라스 자동차 연비 예측 모델 (0) | 2023.04.28 |
---|---|
[딥러닝-케라스] 케라스 보스턴 주택 가격 모델 (0) | 2023.04.28 |
[딥러닝-케라스] 케라스 기초(1) (0) | 2023.04.26 |
[딥러닝-텐서플로우] 텐서플로우 회귀 모델 (0) | 2023.04.26 |
[딥러닝-텐서플로우] 텐서플로우 기초 (0) | 2023.04.25 |