Convolutional Neural Network 구현
import matplotlib.pyplot as plt
# 학습결과 그래프 함수
# loss 그래프
def loss_plot(history):
# plt.figure(figsize=(10,7))
plt.plot(history.history['loss'], label='Train loss')
plt.plot(history.history['val_loss'], label='Validation loss')
plt.title('Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()
# accuracy 그래프
def accuracy_plot(history):
# plt.figure(figsize=(10,7))
plt.plot(history.history['accuracy'], label='Train accuracy')
plt.plot(history.history['val_accuracy'], label='Validation accuracy')
plt.title('accuracy')
plt.xlabel('Epoch')
plt.ylabel('accuracy')
plt.legend()
plt.show()
MNIST CNN 적용
import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers as layers
import numpy as np
np.random.seed(1)
tf.random.set_seed(1)
# 하이퍼파라미터 정의
learning_rate = 0.001
N_EPOCHS = 20
N_BATCH = 100
N_CLASS = 10
(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data()
N_TRAIN = train_images.shape[0]
N_TEST = test_images.shape[0]
train_images.shape, test_images.shape
#(개수, height, width, channel)
# 전처리 - image-0 ~ 1사이로 조정
X_train = train_images/255
X_test = test_images/255
# X의 차원을 3차원->4차원으로 변경. (channel 추가)
# (60000,28,28) => (60000,28,28, 1)
X_train = X_train[..., np.newaxis]
X_test = X_test[..., np.newaxis]
X_train.shape, X_test.shape
# y를 one hot encoding
print(train_labels[:5])
y_train = keras.utils.to_categorical(train_labels, N_CLASS)
y_test = keras.utils.to_categorical(test_labels, N_CLASS)
print(y_train[:5])
# Dataset 구성
train_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))\
.shuffle(N_TRAIN)\
.batch(N_BATCH, drop_remainder=True).repeat()
test_dataset = tf.data.Dataset.from_tensor_slices((X_test, y_test)).batch(N_BATCH)
# 모델 구성 CNN - Conv, Pooling , Dense
def create_model():
model = keras.Sequential()
# Feature Extraction -> Convolution + Pooling layer
# Conv2D(Convolution Layer) + input_shape 지정(height, width, channel)
model.add(layers.Conv2D(filters=32, #필터개수 (1개의 필터가 1개의 특성 찾는다.)
kernel_size=3, #필터의 크기. (3,3) height,width가 같은 경우 하나만 써준다.
padding='SAME',# 패딩방식-SAME,VALID (대소문자 상관없다.
strides=1, #얼만큼씩 이동할지 지정. default: (1,1)
activation='relu',
input_shape=(28,28,1)))
# MaxPooling Layer
model.add(layers.MaxPool2D(pool_size=2, #size: default=(2,2)
strides=2, #기본값: None=>pool size와 동일
padding='SAME'))
model.add(layers.Conv2D(filters=64, kernel_size=3, padding='SAME', activation='relu'))
model.add(layers.MaxPool2D(padding='SAME'))
model.add(layers.Conv2D(filters=128, kernel_size=3, padding='SAME', activation='relu'))
model.add(layers.MaxPool2D(padding='SAME'))
# Classification Layers => Fully Connected Layers
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dropout(0.4))
#출력 layer
model.add(layers.Dense(N_CLASS, activation='softmax'))
return model
# 모델생성 및 컴파일
model = create_model()
model.compile(optimizer=keras.optimizers.Adam(learning_rate),
loss='categorical_crossentropy',
metrics=['accuracy'])
model.summary()
# 학습전에 모델 평가
model.evaluate(test_dataset)
# loss 가 np.log(클래스수) 보다 크면(많이 차이가 나면) 모델을 수정한다.
# [2.3034281730651855, 0.09740000218153]
np.log(N_CLASS) #2.302585092994046
steps_per_epoch = N_TRAIN//N_BATCH
validation_steps = int(np.ceil(N_TEST/N_BATCH))
history = model.fit(train_dataset, epochs=N_EPOCHS, steps_per_epoch=steps_per_epoch,
validation_data=test_dataset, validation_steps=validation_steps)
prediction error가 발생한 example 확인
# test set을 예측
test_pred = model.predict_classes(X_test)
# 실제 label과 예측 결과 비교
error_idx = np.where(np.not_equal(test_labels, test_pred))[0]
error_idx
# 틀린것들 label비교
for idx in error_idx[:10]:
print((test_labels[idx], test_pred[idx]))
plt.figure(figsize=(30,10))
for i in range(10):
idx = error_idx[i]
plt.subplot(1,10, i+1)
plt.imshow(test_images[idx], cmap='Greys')
plt.xticks([])
plt.yticks([])
plt.show()
사진
모델 저장
- 학습이 끝난 모델의 파라미터만 저장
- 모델 전체 저장
- Callback 함수를 이용해 학습시 가장 좋은 지표의 모델 저장
학습한 Weight (파라미터) 저장 및 불러오기
- 가중치를 저장하여 나중에 재학습 없이 학습된 가중치를 사용할 수 있다.
- 저장:
model.save_weights("저장경로")
- 불러오기:
model.load_weights('불러올경로')
- 저장형식
- Tensorflow Checkpoint (기본방식)
- HDF5
save_weights(.., save_format='h5')
import os
cur_dir = os.getcwd() #현재 작업디렉토리
ckpt_dir = 'checkpoints' #weight를 저장할 디렉토리
file_name = 'mnist_cnn_weights.ckpt' #저장파일명
dir = os.path.join(cur_dir, ckpt_dir)
os.makedirs(dir, exist_ok=True)
file_path = os.path.join(dir, file_name)
print(file_path)
# 모델의 weight들을 저장.
model.save_weights(file_path)
# 가중치 불러오기
# 모델 생성
new_model = create_model()
new_model.compile(optimizer=keras.optimizers.Adam(learning_rate),
loss='categorical_crossentropy',
metrics=['accuracy'])
new_model.evaluate(test_dataset) # loss: 2.3040 - accuracy: 0.0910
# 새 모델에 저장된 가중치 설정
new_model.load_weights(file_path)
new_model.evaluate(test_dataset) # loss: 0.0300 - accuracy: 0.9940
전체 모델 저장하고 불러오기
- 저장:
model.save('저장할디렉토리')
- 불러오기:
tf.keras.models.load_model('저장파일경로')
- 저장 형식
- HDF5 형식
save(..., save_format='h5')
로 지정한다.
- Tensorflow SavedModel 형식(기본방식)
- 모델 아키텍처 및 훈련 구성(옵티마이저, 손실 및 메트릭 포함)은 saved_model.pb 에 저장된다.
- 파라미터는 variables/ 디렉토리에 저장된다.
- https://www.tensorflow.org/guide/saved_model?hl=ko#the_savedmodel_format_on_disk
- HDF5 형식
HDF5 형식으로 저장
model_h5_dir = 'save_model/h5'
model_h5_path = os.path.join(cur_dir, model_h5_dir)
model_h5_file = os.path.join(model_h5_path, 'mnist_cnn_h5_model.h5')
os.makedirs(model_h5_path, exist_ok=True)
print(model_h5_file) #/content/save_model/h5/mnist_cnn_h5_model.h5
# 학습한 모델 저장. 모델구조+컴파일내용+weight 모두 저장.
model.save(model_h5_file, save_format='h5')
# 저장한 모델 불러오기
new_model2 = keras.models.load_model(model_h5_file)
new_model2.summary()
new_model2.evaluate(test_dataset) # loss: 0.0300 - accuracy: 0.9940
tensorflow SaveModel 형식으로 저장
#SaveModel 형식은 저장할 디렉토리까지 지정한다.
save_model_path = os.path.join(cur_dir, 'save_model/saved_model/mnist_cnn_sm')
print(save_model_path)
model.save(save_model_path)
# 모델 불러오기
new_model3 = keras.models.load_model(save_model_path)
new_model3.summary()
사진
new_model3.evaluate(test_dataset) # loss: 0.0300 - accuracy: 0.9940
Callback을 사용한 모델 저장 및 Early Stopping
- callback은 학습시 특정 이벤트 발생시 호출되는 다양한 함수를 제공하여 자동화 처리를 지원한다. (cf: 프로그래밍의 콜백함수)
- 다양한 콜백 클래스가 제공된다.
EarlyStopping
: Validation set에 대한 평가지표가 더 이상 개선되지 않을 때 학습을 자동으로 멈춤monitor
: 모니터링할 평가지표 지정. (ex: accuracy)patience
: epoch 수 지정. validation 평가 지표가 개선이 안되더라도 지정한 epoch만큼 반복한다. 지정한 epoch만큼 반복 후에도 개선이 되지 않으면 중단한다.
ModelCheckpoint
: 지정한 평가지표(예:validation loss)가 가장 좋을 때 모델과 weight를 저장하여 overfitting이 발생하기 전의 model을 나중에 불러들여 사용할 수 있음save_best_only=True
: monitoring 중인 measure를 기준으로 최적의 모형의 weight만 저장
- callback 객체들을 리스트로 묶은 뒤 fit()의 callback 매개변수에 전달한다.
model = create_model()
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
ckpt_path = os.path.join(cur_dir, 'callback_ckpt')
os.makedirs(ckpt_path, exist_ok=True)
ckpt_filepath = os.path.join(ckpt_path, 'mnist_cnn_{epoch}.ckpt')
print(ckpt_filepath)
# callback 생성
# epoch마다 학습한 weight들을 저장하는 callback
ckpt_callback = keras.callbacks.ModelCheckpoint(filepath=ckpt_filepath,
save_weights_olny=True #True:weight만저장, False: 모델까지 저장.
)
# early stopping callback
early_stop_callback = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)
history = model.fit(train_dataset, epochs=N_EPOCHS, steps_per_epoch=steps_per_epoch,
validation_data=test_dataset, validation_steps=validation_steps,
callbacks=[ckpt_callback, early_stop_callback])
Functional API
- 함수형 API를 사용하여 모델을 구성
- 각각의 레이어를 만든다.
- 각 레이어를 생성할 때 이전레이어를 지정해서 모델을 만든다.
- input과 output 레이어를 전달하여 모델을 생성한다.
import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers as layers
def create_model_fn():
# Input 레이어
input = layers.Input(shape=(28,28,1))
conv1 = layers.Conv2D(filters=32, kernel_size=3, padding='SAME', activation='relu')(input)
pool1 = layers.MaxPool2D(padding='SAME')(conv1)
conv2 = layers.Conv2D(filters=64, kernel_size=3, padding='SAME', activation='relu')(pool1)
pool2 = layers.MaxPool2D(padding='SAME')(conv2)
flatten = layers.Flatten()(pool2)
dense1 = layers.Dense(256, activation='relu')(flatten)
dropout1 = layers.Dropout(0.5)(dense1)
output = layers.Dense(10, activation='softmax')(dropout1)
#모델 생성
model = keras.Model(inputs=input, outputs=output)
return model
model = create_model_fn()
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
728x90
반응형
'Data Analysis & ML > Deep Learning' 카테고리의 다른 글
[Deep Learning][딥러닝] CNN Image Augmentation(이미지 증식) (0) | 2021.01.24 |
---|---|
[Deep Learning][딥러닝] CNN MNIST 분류 (0) | 2021.01.24 |
[Deep Learning][딥러닝] CNN 개요 (0) | 2020.11.09 |
[Deep Learning][딥러닝] DNN 성능개선 (0) | 2020.11.09 |
[Deep Learning] DNN 분류 (DNN Classification) (0) | 2020.09.23 |