Tensorflow - Transfer Learning(전이학습)을 이용하여 딥러닝하기

반응형

Transfer Learning (전이 학습)

  • 하나의 문제를 해결하고 새로운 유사한 문제에 적용하면서 얻은 지식을 저장하는데 초점을 맞춘 것
    • 예시) 자동차를 인식하는 하는 법을 학습하면서 학습을 토대로 트럭을 인식하려고 할 때 적용
  • 인공지능에서의 전이 학습은 사전학습모델(Pre-trained Model)을 이용하는 것을 의미
  • 개념 알기 : https://luvris2.tistory.com/176

데이터 준비

이미지 데이터셋 다운로드

!wget --no-check-certificate \
    https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip \
    -O ./cats_and_dogs_filtered.zip

다운로드 파일 압축 해제

  • 압축 해제 후 파일 디렉토리 변수로 저장
import zipfile
zipfile.ZipFile('cats_and_dogs_filtered.zip').extractall('/tmp/')

train_dir = ('/tmp/cats_and_dogs_filtered/train')
validation_dir = ('/tmp/cats_and_dogs_filtered/validation')

내 환경에 맞게 데이터셋 설정

학습시킬 데이터셋 호출

  • X_train, y_train : 학습을 위한 데이터로 학습 데이터와 결과가 있음
  • train_label : 학습을 위한 데이터의 클래스 분류를 사용자가 알아보기 쉽게 한 데이터
  • X_test, y_test : 성능 테스트를 위한 데이터와 예측 결과가 있음
  • test_label : 성능 테스트를 위한 데이터의 클래스 분류를 사용자가 알아보기 쉽게 한 데이터
  • X_val, y_val : 검증을 위한 데이터와 검증하기 위한 결과 데이터가 있음
  • val_label : 검증을 위한 데이터의 클래스 분류를 사용자가 알아보기 쉽게 한 데이터
# 데이터셋을 분리하는 함수
def load_dataset_from_hdf5_file(hdf_file_path):
  hf = h5py.File(hdf_file_path, 'r')

  X_train = np.array(hf['trainX'])
  y_train = np.array(hf['trainY'])
  train_label = np.array(hf['trainLabels'])

  X_test = np.array(hf['testX'])
  y_test = np.array(hf['testY'])
  test_label = np.array(hf['testLabels'])

  X_val = np.array(hf['devX'])
  y_val = np.array(hf['devY'])
  val_label = np.array(hf['devLabels'])

  return X_train, y_train, train_label, X_test, y_test, test_label, X_val, y_val, val_label


X_train, y_train, train_label, X_test, y_test, test_label, X_val, y_val, val_label\
= load_dataset_from_hdf5_file('/vehicle_datasets/vehicle-type-dataset-SIZE224-train-dev-test-v2.hdf5')

내가 학습시킬 이미지 데이터셋 확인

# 학습 데이터가 이미 전처리가 되어있음
X_train[0]
>>> array([[[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.], ...
X_train.max()
>>> 1.0
X_train.min()
>>> 0.0

# 가로 224, 세로 224, RGB컬러의 이미지 데이터
X_train[0].shape
>>> (224, 224, 3)

# 클래스가 7개로 분류 되는 결과 데이터, 원핫 인코딩이 되어 있음
y_train[0]
>>> ([0, 0, 0, 0, 0, 1, 0])

# 사람이 이해하기 쉽게 정리 한 데이터로 확인, 즉 첫번째 이미지 파일은 오토바이임
train_label[0]
>>> b'motocycle-motorbike-chopper'

# ImageDataGenerator를 위한 이미지의 크기와 채널의 정보를 변수로 저장
IMG_SHAPE = (224, 224, 3)

이미지 데이터셋 전처리 및 이미지 증강 작업

X_train[0]
>>> array([[[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.], ...
# 데이터를 보니 이미 전처리가 되어있음
# 학습의 효율을 높이기 위해 이미지 증강만 진행
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator( rotation_range=20, width_shift_range=0.2,\
                                   height_shift_range=0.2, zoom_range=0.2, horizontal_flip=True)
train_generator = train_datagen.flow(X_train, y_train)

MobileNetV2 기반 모델 생성 (Input Layer)

  • base_model = tf.keras.applications.MobileNetV2 : 사전학습모델을 호출하여 새로운 모델로 정의
    • input_shape : 이미지의 가로, 세로, 채널의 정보
    • include_top : True/False로 구분, 네트워크의 최상단에 완전 연결 레이어를 넣을지의 여부
  • trainable : 학습 여부(True/False), False일 경우 해당 모델의 학습을 하지 않음
    • base_model(MobileNetV2)은 사전학습 된 모델이며, 학습 된 데이터로 특징을 잡아내는 역할
# IMG_SHAPE : 내가 학습시킬 이미지 데이터셋의 정보를 저장한 변수 이름
base_model =  tf.keras.applications.MobileNetV2(input_shape = IMG_SHAPE, include_top = False)

# 학습여부 : 학습하지 않음
base_model.trainable = False

분류 작업을 할 모델 생성 후 모델링 (Output Layer (=Fully-connected Layer))

  • output : 모델의 출력층(output layer)의 연결 여부
    • head_model = base_model.output : 특징이 추출된 출력 데이터를 새 모델의 입력 데이터로 사용
  • GlobalAveragePooling2D : 풀링 작업을 하고 1차원의 배열로 변경 (Convert FC Layer)
  • Dense(7, 'softmax') : 분류 할 클래스가 7개이며, 3개 이상의 분류 모델은 softmax output
# new_model = model.output : 출력층을 새로운 계층(head_model)과 연결
head_model = base_model.output

# 분류를 위한 함수형 모델링
head_model = tf.keras.layers.GlobalAveragePooling2D()(head_model)
head_model = tf.keras.layers.Dense(128, 'relu')(head_model)
head_model = tf.keras.layers.Dense(7, 'softmax')(head_model)

모델 병합

  • model = base model + head model
    • input layer : 특징을 추츨해내는 역할을 하는 base_model(MobileNetV2기반)
    • output layer : 분류 작업을 하는 head_model
# 모델 병합
model = tf.keras.models.Model(inputs = base_model.input, outputs = head_model)

모델 컴파일

  • 최적화 설정 : RMSporp 사용
  • 손실함수 설정 : 원핫 인코딩 처리가 되어 있기 때문에 'categorical_crossentropy' 사용
  •  metrics(결과지표 설정) : 정확도 표시
# 컴파일
model.compile(tf.keras.optimizers.RMSprop(0.0001), 'categorical_crossentropy', ['accuracy'])

모델 학습

  • train_generator : 이미지 증강 처리하고 학습결과까지 포함 (X_train+y_train)
  • epochs : 학습의 반복 정도
  • validation_data : 학습과 별개로 다른 데이터로 검증 여부, 과적합 방지 용도
epoch_history = model.fit( train_generator, epochs=5, validation_data= (X_val, y_val))

>>> Epoch 1/5
19/19 [==============================] - 19s 821ms/step - loss: 1.6215 - accuracy: 0.4146 - val_loss: 1.2126 - val_accuracy: 0.6533
Epoch 2/5
19/19 [==============================] - 13s 689ms/step - loss: 1.0424 - accuracy: 0.6816 - val_loss: 0.8264 - val_accuracy: 0.8533
Epoch 3/5
19/19 [==============================] - 13s 687ms/step - loss: 0.7184 - accuracy: 0.8159 - val_loss: 0.6115 - val_accuracy: 0.8400
Epoch 4/5
19/19 [==============================] - 14s 724ms/step - loss: 0.5368 - accuracy: 0.8590 - val_loss: 0.4643 - val_accuracy: 0.8800
Epoch 5/5
19/19 [==============================] - 15s 762ms/step - loss: 0.4376 - accuracy: 0.8740 - val_loss: 0.3856 - val_accuracy: 0.8933

Fine Tuning (미세 조정)

  • base_model.trainable=True : 동결 해제
  • 모델 특성 조정
    • 참조하여 생성한 모델의 크기 확인, 적정 크기를 학습용으로 분배
    • 모델 크기 확인 : base_model.shape
    • 모델의 동결해제 적정 범위 설정 : base_model [ 0 : N ]
    • 동결 해제 설정 : 반복문을 이용하여 설정한 범위 동결 해제 
# Fine tuning
# 학습 가능 상태로 변경
base_model.trainable=True

# 참조해온 모델 레이어 확인
len(base_model.layers)
>>> 154

# 학습 범위 설정 121 ~ 154
end_layer = 120 # setting N (int)
for layer in base_model.layers[ 0 : end_layer+1 ]:
  layer.trainable = False

# 컴파일
model.compile(tf.keras.optimizers.RMSprop(0.0001), 'categorical_crossentropy', ['accuracy'])

# 학습
epoch_history1 = model.fit( train_generator, epochs=5, validation_data= (X_val, y_val))
반응형