본문 바로가기
Data Science/딥러닝

5장 컴퓨터 비전을 위한 딥러닝2

by 코딩은 잼있어 2020. 9. 23.
728x90

5장 컴퓨터 비전을 위한 딥러닝2

5.3 사전에 훈련된 커브넷 사용하기

작은 이미지 데이터셋에 딥러닝을 적용하는 일반적이고 효과적인 방법은 사전에 훈련된 네트워크를 사용하는 것입니다. 사전 훈련된 네트워크(pretrained network)는 일반적으로 대규모 이미지 분류 문제를 위해 대량의 데이터셋에서 미리 훈련되어 저장된 네트워크 입니다.

사전훈련된 네트워크를 사용하는 방법은 두가지 있습니다. 특성추출(feature extraction), 미세조정(fine tuning)입니다. 먼저 특성추출부터 시작해봅시다.

5.3.1 특성추출(feature extraction)

특성추출은 사전에 학습된 네트워크의 표현을 사용하여 새로운 샘플에서 흥미로운 특성을 뽑아내는것입니다. 이러한 특성을 활용하여 새로운 분류기를 처음부터 훈련합니다.

이미지 분류를 위해 두 부분으로 구성되는데, 먼저 합성곱층과 풀링층을 포함한 합성곱 기반층(convolutional base)으로 시작해서 완전 연결 분류기로 끝납니다.

컨브넷에서의 특성 추출은 사전에 훈련된 네트워크의 합성곱 기반층을 선택하여 새로운 데이터를 통과시키고, 그 출력으로 새로운 분류기를 훈련합니다.

특성 합성곱층에서 추출한 표현의 일반성 수준은 모델에 있는 층의 깊이에 달려있습니다. 모델의 하위층은 지역적이고 매우 일반적인 특성맵, 상위층('강아지 눈')은 좀 더 추상적인 개념을 추출합니다.

ImageNet의 클래스 집합에는 여러 종류의 동물이 있기 때문에, 원본 모델의 완전 연결층에 있는 정보를 재사용하는 것이 도움이 될것같다.

쉽게 말해서, 적은 데이터의 단점을 보완하기 위해 기존에 대량의 데이터가 학습되있는 모델의 특성을 뽑아내어 정확도를 높이는 과정

ImageNet 데이터셋을 활용하여 VGG16모델을 만들어 봅시다.

conv_base = VGG16(weights='imagenet',
                  include_top=False,
                  input_shape=(150, 150, 3))
  • weights : 모델을 초기화할 가중치 체크포인트를 지정합니다.
  • include_top : 네트워크의 최상위 완전 연결 분류기를 포함할지 안할지 지정합니다.
  • input_shape : 네트워크에 주입할 이미지 텐서의 크기

데이터 증식을 사용한 특성 추출

# 5-20 합성곱 기반 층위에 완전 분류기 추기하기
from keras import models
from keras import layers

model = models.Sequential()
model.add(conv_base)        # 완전 분류기
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

모델을 컴파일하고 훈련하기 전에 합성곱 기반 층을 동결하는 것이 아주 중요합니다.

동결(freezing) 한다는 것운 훈련기간동안 가중치가 업데이드 되지 않도록 막는다는 뜻입니다. 동결하지 않는다면 매우 큰 가중치 업데이트 값이 네트워크에 전파되면서 사전에 학습된 표현을 크게 훼손하게 됩니다.

conv_base.trainable = False # 동결한다
conv_base.trainable = True # 동결하지 않는다.

False로 하게 되면 추가한 2개의 Dense층의 가중치만 훈련을 합니다.

#5-21 동결된 합성곱 기반층과 함께 모델을 엔드투 엔드로 훈련하기
from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(
      rescale=1./255,
      rotation_range=20,
      width_shift_range=0.1,
      height_shift_range=0.1,
      shear_range=0.1,
      zoom_range=0.1,
      horizontal_flip=True,
      fill_mode='nearest')

# 검증 데이터는 증식되어서는 안 됩니다!
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # 타깃 디렉터리
        train_dir,
        # 모든 이미지의 크기를 150 × 150로 변경합니다
        target_size=(150, 150),
        batch_size=20,
        # binary_crossentropy 손실을 사용하므로 이진 레이블이 필요합니다
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=2e-5),
              metrics=['acc'])

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=50,
      verbose=2)

5.3.2 미세 조정(fine- tuning)

미세 조정은 특성 추출에서 사용했던 동결 모델의 상위층 몇개를 동결에서 해제하고 모델에 새로 추가한 층과 함꼐 훈련하는 것 입니다. 미세 조정은 특성 추출에서 사용했던 동결 모델의 상위 층 몇개를 동결에서 해제하고 완전 연결 분류기와 함께 훈련하는것입니다.

네트워크를 미세조정하는 단계는 다음과 같습니다.

  1. 사전에 훈련된 기반 네트워크 위에 새로운 네트워크를 추가합니다.
  2. 기반 네트워크를 동결합니다.
  3. 새로 추가한 네트워크를 훈련합니다.
  4. 기반네트워크에서 일부 층의 동결을 해제합니다.
  5. 동결을 해제한 층과 새로 추가한 층을 함께 훈련합니다.

그렇다면 왜? 전체가 아닌 일부의 합성곱 기반층만 미세조정을 할까 ??

  • 합성곱 기반층에 있는 하위층들은 좀 더 일반적이고 재사용 가능한 특성들을 인코딩하고, 상위층은 좀더 특성화된 특성을 인코딩 합니다. 그래서 구체적인 특성을 가진 상위층의 미세 조정하는것이 유리합니다.
  • 훈련해야할 파라미터가 많을수록 과대적합의 위험이 커집니다.

그러므로 최상위 2~3개의 층만 미세조정하는 것이 좋습니다.

# 5-22 특정층까지 모든 층 동결하기
conv_base.trainable = True
set_trainable = False
for layer in conv_base.layers:
    if layer.name == 'block5_conv1':
        set_trainable = True
    if set_trainable:
        layer.trainable = True
    else:
        layer.trainable = False

# 5-23 모델 미세 조정하기
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-5),
              metrics=['acc'])

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=100,
      validation_data=validation_generator,
      validation_steps=50)

이전과 동일한 코드로 그래프를 그리면 아래와 같습니다.

img

728x90