본문 바로가기
빅데이터 부트캠프/머신러닝&딥러닝

빅데이터 부트캠프 26&27일차

by Mecodata 2022. 8. 10.

CNN(Convertion Neural Network, 합성곱 신경망)

- 입력 데이터의 전체에 가중치를 적용하는 것이 아니라 일부 가중치를 곱하여 계산

- Convertion(합성곱) = 설정한 가중치의 개수에 따라 한 칸씩 아래로 이동하면서 출력을 만드는 것

- CNN에서는 뉴런을 필터 혹은 커널이라 부름

- Feature map(특성 맵) = 합성곱 계산을 통해 얻은 출력

 

Padding

- 입력 배열의 주위를 가상의 원소로 채우는 것 (주로 0으로)

ex) (4,4) 크기의 입력에 1번 패딩 -> (6,6) 크기 (6 = 4+1x2) 

 

Pooling

- 특성 맵의 가로세로 크기를 줄이는 것 (특성 맵 자체의 개수는 변함X)

- Max Pooling = 필터를 적용한 부분의 최대값을 출력

- Average Pooling = 필터를 적용한 부분의 평균값을 출력 

 

Dropout

- 훈련과정에서 층에 있는 일부 뉴런을 랜덤하게 꺼서 과대적합을 막는 방법

- 이전 층의 일부 뉴런이 랜덤하게 꺼지면 특정 뉴런에 과대하게 의존하는 것줄일 수 있기 때문

 

Conv2D

- 2차원 이미지를 다루는 컨볼루션 레이어

- input_shape = (행 픽셀,열 픽셀, 차원 수)
- kernel_size = 필터 행렬의 크기

- activation = 활성화 함수 지정 
- filters = 필터의 개수 (너무 많을 경우 학습 속도가 느려질 수 있고 과적합 발생 가능성 있음)
- padding : 연산전 입력 이미지 주변에 빈 값을 넣을지 지정하는 옵션
- strides : 필터가 계산 과정에서 한 스텝마다 이동하는 크기

 

# 데이터를 채널을 가진 이미지 형태(1차원-> 3차원)으로 바꾸기

train_X = train_X.reshape(-1,28,28,1) # (픽셀크기, 차원) train 데이터 자체는 1차원이므로 맨뒤에 1
test_X = test_X.reshape(-1,28,28,1) # 맨앞에 -1을 입력하면 알아서 차원을 바꿔줌 (필요에 따라 입력 안해줘도 무방)

# 데이터를 0~255에서 0~1로 정규화 (.은 데이터 타입을 float으로 변경하기 위해)
train_X = train_X/255.
test_X = test_X/255.

 

MaxPool2D

- 하이퍼파라미터 = 풀링의 크기(기본값 2 = 2x2 픽셀), strides(풀링의 크기에 맞추어 자동 설정), padding 

- Conv2D 층 사이사이에 입력

 

callback

- 훈련 중간에 어떤 작업을 수행할 수 있게 하는 객체

 

- EarlyStopping = 과대적합이 시작되기 전에 훈련을 미리 중지하도록 설정

- tf.keras.callbacks.EarlyStopping(monitor= 기준 변수, patience= 기준 변수가 상승하는 것을 몇번 참을지 설정)

 

- ModelCheckpoint = 에포크마다 모델을 저장하도록 설정

- tf.keras.callbacks.ModelCheckpoint(filepath= 파일 경로, monitor= 기준 변수, verbose= 진행상황 메세지 출력 여부 설정 (0=출력X, 1=작업수행시 메세지 표시, 2=한줄마다 메세지 표시), save_best_only=가장 결과가 좋은 모델을 저장할지 설정 그렇다면 True 아니면 False)

save_best_only=True 일 경우 모델의 정확도가 증가하지 않으면 모델을 저장하지 못함

import tensorflow as tf

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(input_shape=(28,28,1), kernel_size=(3,3), filters=16),
    tf.keras.layers.MaxPool2D(strides=(2,2)),
    tf.keras.layers.Conv2D(kernel_size=(3,3), filters=32),
    tf.keras.layers.MaxPool2D(strides=(2,2)),
    tf.keras.layers.Conv2D(kernel_size=(3,3), filters=64),
    tf.keras.layers.Flatten(), # 데이터의 특성을 3번 추출해서 1차원의 벡터열로 만들어줌 
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dropout(rate=0.3), # 제외시킬 뉴런의 비율
    tf.keras.layers.Dense(units=10, activation='softmax')]
)

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

early_stopping_callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3)

history = model.fit(train_X, train_Y, epochs=25, validation_split=0.25, callbacks=[early_stopping_callback])

 

Tensorboard

- TensorFlow 시각화 도구

- tf.keras.callbacks.TensorBoard(log_dir=데이터 출처 경로, histogram_freq=1)

 

# 시간정보를 활용하여 폴더 생성
import datetime

# 학습데이터의 log를 저장할 폴더 생성 (지정)
log_dir = "logs/my_board/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

# 텐서보드 콜백 정의 하기
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)

# 학습
import tensorflow as tf

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(input_shape=(28,28,1), kernel_size=(3,3), filters=16),
    tf.keras.layers.Conv2D(kernel_size=(3,3), filters=32),
    tf.keras.layers.Conv2D(kernel_size=(3,3), filters=64),
    tf.keras.layers.Flatten(), # 데이터의 특성을 3번 추출해서 1차원의 벡터열로 만들어줌 
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dense(units=10, activation='softmax')]
)

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

early_stopping_callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3)

history = model.fit(train_X, train_Y, epochs=25, validation_split=0.25, callbacks=[early_stopping_callback, tensorboard_callback])

# 확인
history.summary()

# 텐서보드 extension 로드를 위해서
%load_ext tensorboard

# 텐서보드 로드
%tensorboard --logdir {log_dir}

 

ImageDataGenerator

- 출력될 이미지에 대한 상세한 속성 설정

- flow = 훈련 데이터에 없는 이미지를 훈련 데이터를 바탕으로 다시 새롭게 만들어서 훈련데이터 보강

(보다 더 좋은 퀄리티의 훈련 데이터 사용을 위해서)

 

※ ImageDataGenerator 하이퍼파라미터

- rotation_range = 이미지 각도, zoom_range = 줌 비율 설정, shear_range = 이미지를 어느정도로 찌그러 트릴지

- width_shift_range = 사진 좌우 이동 비율, height_shift_range = 이미지 상하 이동 비율

- horizontal_flip = 좌우반전 설정, vertical_flip = 상하반전 설정 (True or False) 

 

import matplotlib.pyplot as plt
import numpy as np
import os
import sys
import tensorflow as tf
from keras.datasets import fashion_mnist

# 시간정보를 활용하여 폴더 생성
import datetime

# 학습데이터의 log를 저장할 폴더 생성 (지정)
log_dir = "logs/my_board/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

#### 1) 데이터 수집 및 가공
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
train_X = train_X.reshape(-1,28,28,1) # 차원 변환
test_X = test_X.reshape(-1,28,28,1)
X_train = X_train[..., np.newaxis].astype('float32')  / 255   #  0 ~ 1 사이값 반환하기 위해서 255로 나눔
X_test = X_test[..., np.newaxis].astype('float32')  / 255

datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    rotation_range=10,  
    zoom_range=0.1,  
    shear_range=0.5,
    width_shift_range=0.1,  
    height_shift_range=0.1,  
    horizontal_flip=True,  
    vertical_flip=False
) # 이미지 데이터 상세 설정

# 랜덤하게 30000 보강
augment_size = 30000

X_train_augment, y_train_augment= datagen.flow(X_train, y_train,  batch_size=augment_size, shuffle=True).next()
X_test_augment, y_test_augment= datagen.flow(X_test, y_test,  batch_size=augment_size, shuffle=True).next()
print(X_train.shape, X_train_augment.shape) # (60000, 28, 28, 1) (30000, 28, 28, 1)
print(X_test.shape, X_test_augment.shape) # (60000, 28, 28, 1) (30000, 28, 28, 1)
print(y_train.shape, y_train_augment.shape) # (60000,) (30000,)
print(y_test.shape, y_test_augment.shape) # (60000,) (30000,)

#### 2) 모델생성 및 층 추가
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(input_shape=(28,28,1), kernel_size=(3,3), filters=16),
    tf.keras.layers.MaxPool2D(strides=(2,2)),
    tf.keras.layers.Conv2D(kernel_size=(3,3), filters=32),
    tf.keras.layers.MaxPool2D(strides=(2,2)),
    tf.keras.layers.Conv2D(kernel_size=(3,3), filters=64),
    tf.keras.layers.MaxPool2D(strides=(2,2)),
    tf.keras.layers.Flatten(), # 데이터의 특성을 3번 추출해서 1차원의 벡터열로 만들어줌 
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dropout(rate=0.3), # 제외한 뉴런의 비율
    tf.keras.layers.Dense(units=10, activation='softmax')]
)

#### 3) 최적화 알고리즘과 손실함수 및 측정지표 지정
model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics=['accuracy'])

# 파일저장 ( 매 epoch마다 모델의 정확도를 함께 기록 )
MODEL_DIR = './model/'
if not os.path.exists(MODEL_DIR):
    os.mkdir(MODEL_DIR)

# filepath로 파일을 설정하고 monitor로 val_loss 변수로 해서 save_best_only=True로 가장 좋은 결과 하나만을 자세히 입력하게 설정
modelpath="./model/final-{epoch:02d}-{val_loss:.4f}.hdf5"
checkpointer = tf.keras.callbacks.ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1, save_best_only=True)

# 조기 종료
early_stopping_callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

# 텐서보드 콜백 정의 하기
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)

#### 4) 모델 훈련
history = model.fit(X_train_augment, y_train_augment,
                    validation_data=(X_test_augment, y_test_augment),
                    epochs=30,
                    batch_size=200, verbose=0,
                    callbacks=[early_stopping_callback,checkpointer, tensorboard_callback])

#### 5) 측정지표 확인 및 시각화

plt.figure(figsize=(12, 4))

plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], 'b-', label='loss')
plt.plot(history.history['val_loss'], 'r--', label='val_loss')
plt.xlabel('Epoch')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], 'g-', label='accuracy')
plt.plot(history.history['val_accuracy'], 'k--', label='val_accuracy')
plt.xlabel('Epoch')
plt.ylim(0.7, 1)
plt.legend()

plt.show()

#### 5) 모델 평가
print("\n Test Accuracy: %.4f" % (model.evaluate(X_test_augment, y_test_augment)[1]))

댓글