본문 바로가기

Study/딥러닝 텐서플로 교과서 - 길벗

[Book]5. 합성곱 신경망 1

개요

  • 책을 보고 공부한 내용을 정리합니다.

딥러닝 텐서플로 교과서

  • 저자 서지영님 
  • 길벗 출판사

코드 출처

https://github.com/gilbutITbook/080263

 

GitHub - gilbutITbook/080263

Contribute to gilbutITbook/080263 development by creating an account on GitHub.

github.com


5. 합성곱 신경망 1

5.1.1 합성곱층의 필요성

  • 이미지, 영상처리에 유용

5.1.2 합성곱 신경망 구조

  • 입력층
  • 합성곱층
  • 풀링층
  • 완전 연결층
  • 출력층
  • 합성곱 신경망은 합성곱층과 풀링층을 거치면서 입력 이미지의 주요 특성 벡터를 추출
  • 추출된 주요 특성 벡터들은 완전 연결층을 거치면서 1차원 벡터로 변환, 마지막으로 출력층에서 활성화 함수인 소프트맥스(softmax) 함수를 사용하여 최종 결과 출력


입력층

  • 이미지 데이터가 최초로 거치는 층
  • 이미지는 단순 1차원의 데이터가 아닌 높이, 너비, 채널의 값을 갖는 3차원 데이터
  • 채널은 이미지가 그레이 스케일이면 1 값을, 컬러면 3 값을 갖는다


합성곱층

  • 입력데이터에서 특성을 추출하는 역할
  • 이미지에 대한 특성을 감지하기 위해 커널이나 필터 사용
  • 커널/필터는 이미지의 모든 영역을 훑으면서 특성을 추출하게 되는데 이 결과물을 특성 맵(feature map)이라고 함


풀링층

  • 합성공츱과 유사하게 특성 맵의 차원을 다운 샘플링
  • 풀링 연산 종류 - 최대풀링(max_pooling), 평균 풀링

맥스 풀링

 

완전 연결층

  • 합성곱층과 풀링층을 거치면서 차원이 축소된 특성 맵은 최종적으로  완전 연결층(fully connected layer)으로  전달
  • 이 과정에서 이미지는 3차원 벡터에서 1차원 벡터로 펼쳐짐

 

 5.1.3. 1D, 2D, 3D 합성곱

1D 합성곱

  • 필터가 시간을 축으로 좌우로만 이동
  • 그래프 곡선을 완화할 때 많이 사용

2D 합성곱

2D 합성곱

3D 입력을 갖는 2D 합성곱

  • 입력이 3D 형태임에도 출력 형태가 3D가 아닌 2D 행렬을 취하는 것

5.2 합성곱 신경망 맛보기

 

  • fashion_mnist
  • colums
  •  0 : T- shirt
  •  1 : Trouser
  • 2 : Pullover
  • 3 : Dress
  • 4 : Coat
  • 5 : Sandal
  • 6 : Shirt
  • 7 : Sneaker
  • 8 : Bag
  • 9 : Ankel boot

 

심층 신경망 VS 합성곱 신경망

1. 심층 신경망

# 심층 신경망
X_train, X_test = X_train / 255.0 , X_test/255.0

model = tf.keras.models.Sequential([
              tf.keras.layers.Flatten(input_shape = (28, 28)),
              tf.keras.layers.Dense(128, activation ='relu'),

              # 과적합 방지 20%를 무작위로 0으로 만듬
              tf.keras.layers.Dropout(0.2),
              tf.keras.layers.Dense(10, activation = 'softmax')
])

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

model.fit(X_train, y_train, epochs = 5)
model.evaluate(X_test, y_test, verbose = 2)

2. 합성곱 신경망

 

model_with_conv = tf.keras.Sequential([
              # 32 : 합성곱 필터 개수
              # (3, 3) : 합성곱 커널의 행과 열
              tf.keras.layers.Conv2D(32, (3, 3), padding = 'SAME', activation = 'relu', input_shape = (28, 28, 1)),

              # 필터 크기 : (2,2)
              tf.keras.layers.MaxPooling2D((2,2), strides =2),

              tf.keras.layers.Conv2D(64, (3, 3), padding = 'SAME', activation = 'relu'),
              tf.keras.layers.MaxPooling2D((2, 2), strides = 2),

              tf.keras.layers.Flatten(),
              tf.keras.layers.Dense(128, activation = 'relu'),
              tf.keras.layers.Dense(10, activation = 'softmax')
])
model_with_conv.compile(optimizer = 'adam',
                        loss = 'sparse_categorical_crossentropy',
                        metrics = ['accuracy'])


5.3 전이 학습

  • 이미지넷(ImageNet)처럼 아주 큰 데이터셋을 써서 훈련된 모델의 가중치를 가져와 우리가 해결하려는 과제에 맞게 보정해서 사용하는 것
  • 전이 학습을 위한 방법에는 특성 추출과 미세 조정 기법이 있음

 

5.3.1 특성 추출 기법

  • ImageNet 데이터셋으로 사전 훈련된 모델을 가져온 후 마지막에 완전 연결층 부분만 새로 만듦
  • 즉, 학습할 떄는 마지막 완전 연결 층만 학습하고 나머지 계층들은 학습되지 않도록 함
  • 합성곱층 :  합성곱층과 풀링층으로 구성
  • 데이터 분류기(완전연결층, fully_connected layer) : 최종적으로 이미지에 대한 클래스 분류하는 부분

# ResNet50
model = ResNet50(include_top = True,
                 weights = 'imagenet',
                 input_tensor = None,
                 input_shape = None,
                 pooling = None,
                 classes = 1000)

# include_top : 네트워크 상단에 완전 연결층을 포함할지 여부 지정, 기본값 True
# weights : None(무작위 초기화) 와 imagenet(IMAGENET 에서 사전 훈련된 값)을 지정
# input_tensor : 입력 데이터의 텐서
# input_shape : 입력 이미지에 대한 텐서 크기
# pooling : -None : 마지막 합성 곱층 출력 , - avg: 마지막 합성곱층에 글로벌 평균 풀링 추가, -max : 마지막 합성곱층에 글로벌 최대 풀링 추가
# classes : weight로 imagenet 사용하려면 1000 적고 , 다른거는 None
# 앞에 생성한 모델에 밀집층 추가
model.trainable = False
model = Sequential([model,
                    Dense(2, activation = 'sigmoid')])
model.summary()

BATCH_SIZE = 32
image_height = 100
image_width = 100
train_dir = 'train_dir_path'
valid_dir = 'valid_dir_path'

# ImageDataGenerator
# 데이터 전처리하는 함수

# rescale = 1./255 
# 원본 영상은 0~255의 RGB 계수로 구성되는데 , 1/255 로 스케일링하여 0~1범위로 변환

# rotation_range = 10
# 이미지 회전 범위, 0~10도 범위 내에서 임의로 원본 이미지를 회전

# width_shift_range = 0.1
# 그림을 수평으로 랜덤하게 평행 이동시키는 범위, 전체 넓이가 100이면, 0.1 값을 적용하면서 10픽셀 내외로 좌우로 이동

# height_shift_range = 0.1
# 전체 높이가 100이면, 0.1 값을 적용하면서 상하 이동

# shear_range = 0.1
# 원본 이미지를 임의로 변형 시키는 범위, 0.1 라디안 내외로 시계 반대 방향으로 이미지 변환

# zoom_range = 0.1
# 임의 확대/축소 범위, 0.9에서 1.1 배의 크기로 이미지를 변환
train = ImageDataGenerator(
                 rescale=1./255,
                 rotation_range=10,
                 width_shift_range=0.1,
                 height_shift_range=0.1,
                 shear_range=0.1,
                 zoom_range=0.1) 

# flow_from_directory
# 폴더 구조를 그대로 가져와서 ImageDataGenerator에 실제 데이터를 채워줌
# -> 먼소리

# trian_dir :  훈련 이미지 경로

# target_size :  이미지 크기, 모든 이미지는 이 크기로 자동 조정

# color_mode : 이미지가 그레이스케일이면 'grayscale'사용, 색상이 있으면 'rgb'

# batch_size :  배치당 generator 에서 생성할 이미지 개수

# seed : 임의로 섞기 위한 랜덤한 숫자

# shuffle : 이미지를 섞어서 사용여부

# class_mode : 예측할 클래스가 두 개면 'binary', 그렇지 않으면 'categorical'
train_generator = train.flow_from_directory(train_dir,
                                            target_size=(image_height, image_width),
                                            color_mode="rgb",
                                            batch_size=BATCH_SIZE,
                                            seed=1,
                                            shuffle=True,
                                            class_mode="categorical")


valid = ImageDataGenerator(rescale=1.0/255.0)

valid_generator = valid.flow_from_directory(valid_dir,
                                            target_size=(image_height, image_width),
                                            color_mode="rgb",
                                            batch_size=BATCH_SIZE,
                                            seed=7,
                                            shuffle=True,
                                            class_mode="categorical")
# 모델 학습
# verbose = 2
# 훈련의 진행과정 보여줌
# 2는 미니 배치마다 훈련 정보를 출력
history = model.fit(train_generator,
                    epochs=10,
                    validation_data=valid_generator,
                    verbose=2)

 

 

텐서 플로 허브

 

  • 사전 훈련된 모델을 이용하는 또 다른 방법
  • 구글에서 공개한 API
model = tf.keras.Sequential([
          hub.KerasLayer("https://tfhub.dev/google/imagenet/resnet_v2_152/feature_vector/4",
                         input_shape=(224,224,3),
                         trainable=False),
          tf.keras.layers.Dense(2, activation='softmax')])

5.3.2 미세 조정 기법(fine-tuning)

 

 

  • 특성 추출 기법에서 더 나아가 사전 훈련된 모델과 합성곱층, 데이터 분류기의 가중치를 업데이트하여 훈련시키는 방식
  • 사전 학습된 모델을 목적에 맞게 재학습 시키거나 학습된 가중치의 일부를 재학습

 


전략

1. 데이터셋이 크고 사전 훈련된 모델과 유사성이 작을 경우 
- 모델 전체를 재학습시킴

2. 데이터셋이 크고 사전 훈련된 모델과 유사성이 클 경우
- 합성곱층의 뒷부분(완전 연결층과 가까운 부분)과 데이터 분류기를 학습

3. 데이터셋이 작고 사전 훈련된 모델과 유사성이 작을 경우
- 합성곱층의 일부분과 데이터 분류기를 학습

4. 데이터셋이 작고 사전 훈련된 모델과 유사성이 클 경우
- 데이터 분류기만 학습