9장 컴퓨터 비전을 위한 고급 딥러닝 2부

감사말: 프랑소와 숄레의 Deep Learning with Python, Second Edition 9장에 사용된 코드에 대한 설명을 담고 있으며 텐서플로우 2.6 버전에서 작성되었습니다. 소스코드를 공개한 저자에게 감사드립니다.

tensorflow 버전과 GPU 확인

9.3 합성곱 신경망 기본 아키텍처

모델 아키텍처는 모델 설계방식을 의미하며 딥러닝 모델을 구성할 때 매우 중요하다. 주어진 데이터셋과 해결해야 문제에 따라 적절한 층을 적절하게 구성해서 모델을 구현해야 한다. 좋은 모델 아키텍처를 사용할 수록 적은 양의 데이터을 이용하여 보다 빠르게 좋은 성능의 모델을 얻을 가능성이 높아진다. 아쉽게도 좋은 모델 아키텍처와 관련된 이론은 없으며 많은 경험을 통한 직관이 보다 중요한 역할을 수행한다.

여기서는 실전에서 최고 성능을 발휘한 합성곱 신경망 몇 개를 이용하여 주요 합성곱 신경망 모델의 기본이 되는 아키텍처 3 개를 살펴본다.

9.3.1 블록, 계층, 재활용

모든 유명한 합성곱 신경망 모델은 블록(모듈)계층적으로 쌓아 올린 구조를 갖는다. 여기서 블록(모듈)은 여러 개의 층(레이어)으로 구성되며, 하나의 블록(모듈)이 여러 번 재활용되기도 한다. 예를 들어, 8장에서 다룬 VGG16 모델은 "Conv2D, Conv2D, MaxPooling2D" 로 구성된 블록(모듈)을 계층적으로 구성하였다.

대부분의 합성곱 신경망 모델의 또다른 특징는 특성 피라미드 형식의 계층적 구조를 사용하는 점이다. VGG16의 경우에 필터 수를 32, 64, 128 등으로 수를 늘리는 반면에 특성맵(feature maps)의 크기는 그에 상응하게 줄여 나간다(아래 그림 참조).

그림 출처: Deep Learning with Python(Manning MEAP)

좁은 층 깊은 신경망 모델

일반적으로 많은 유닛이 포함된 층을 몇 게 쌓는 것보다 적은 유닛이 포함된 층을 높이 쌓을 때 모델의 성능이 좋아진다. 하지만 층을 높이 쌓을 수록 전달되어야 하는 손실값(오차)의 그레이디언트 소실 문제(vanishing gradient problem)가 발생하여 이를 극복해야 하는 아키텍처(설계방식)을 사용해야 한다. 이를 위한 대표적인 아키텍처는 잔차 연결(residual connections)이다.

참고: 층을 통과할 때 어쩔 수 없이 발생하는 노이즈(잡음) 때문에 그레이디언트 소실 문제가 발생한다.

9.3.2 잔차 연결

블록(모듈)의 입력값을 블록을 통과하여 생성된 출력값과 합쳐서 다음 블록으로 전달하는 아키텍처이다(아래 그림 참조). 이 방식을 통해 블록의 입력값에 대한 정보가 보다 정확하게 상위 블록에 전달되어, 그레이디언트 소실 문제를 해결하는 데에 많은 도움을 준다. 실제로 잔차 연결을 이용하면 블록을 매우 높게 쌓아도 모델 훈련이 가능하다.

참고: 잔차 연결 아키텍처는 2015년에 소개된 ResNet 계열의 모델에서 처음 사용되었으며, 2015년 ILSVRC 이미지 분류 경진대회에서 1등을 차지했다.

그림 출처: Deep Learning with Python(Manning MEAP)

잔차 연결 핵심: 모양(shape) 맞추기

잔차 연결을 사용할 때 주의해야할 기본사항은 블록의 입력텐서와 출력테서의 모양을 맞추는 일이다. 이때 맥스풀링 사용여부에 따라 보폭(strides)의 크기가 달라진다.

먼저, 맥스풀링을 사용하지 않는 경우엔 Conv2D에서 사용된 필터 수를 맞추는 데에만 주의하면 된다.

맥스풀링을 사용하는 경우엔 보폭을 활용해야 한다.

예제

아래 코드는 잔차 연결을 사용하는 활용법을 보여준다. 맥스풀링과 필터 수에 따른 구분을 사용함에 주의하라.

모델 구성 요약은 다음과 같다.

9.3.3 배치 정규화

정규화(normalization)는 다양한 모양의 샘플을 정규화를 통해 보다 유사하게 만들어 모델의 학습을 도와주고 훈련된 모델의 일반화 성능을 올려준다. 지금까지 살펴 본 정규화는 모델의 입력 데이터를 전처리 과정에서 평균을 0으로, 표준편차를 1로 만드는 방식이었다. 이는 데이터셋이 정규분포를 따른다는 가정 하에 진행된 정규화였다. 아래 그림은 주택가격 예측 데이터의 특성 중에 주택가격과 건축년수를 정규화한 경우(오른편)와 그렇지 않는 경우(왼편)의 데이터 분포의 변화를 보여준다.

참고: 정규분포를 따르지 않는 데이터에 대한 분석은 기본적으로 머신러닝(딥러닝) 기법을 적용할 수 없다.

그림 출처: Batch Normalization — Speed up Neural Network Training

하지만 입력 데이터셋에 대한 정규화는 출력값의 정규화를 전혀 보장하지 않는다. 따라서 다음 층으로 넘겨주기 전에 정규화를 먼저 진행하면 보다 훈련이 잘 될 수 있다. 더 나아가 출력값을 먼저 정규화한 후에 활성화 함수를 적용할 때 보다 좋은 성능의 모델이 구현될 수 있음이 발혀지기도 했다.

그림 출처: Batch Normalization — Speed up Neural Network Training

배치 정규화(batch normalization)가 바로 앞서 설명한 기능을 대신 처리하며, 2015년에 발표된 한 논문에서 소개되었다. 케라스의 경우 layers.BatchNormalization 층이 배치 정규하를 지원한다.

배치 정규화로 인한 모델 성능 향상에 대한 구체적인 이론은 아직 존재하지 않는다. 다만 경험적으로 많은 합성곱 신경망 모델의 성능에 도움을 준다는 사실만 알려져 있을 뿐이다. 잔차 연결과 함께 배치 정규화 또한 모델 훈련과정에 그레이디언트 역전파에 도움을 주어 매우 깊은 딥러닝 모델의 훈련에 도움을 준다. 예를 들어, ResNet50, EfficientNet, Xception 모델 등은 배치 정규화 없이는 제대로 훈련되지 않는다.

배치 정규화 사용법

BatchNormalization 층을 Conv2D, Dense 등 임의의 층 다음에 사용할 수 있다. 주로 사용되는 형식은 다음과 같다.

x = ...
x = layers.Conv2D(32, 3, use_bias=False)(x)
x = layers.BatchNormalization()(x)
x = layers.Activation("relu")(x)
x = ...

모델 미세조정(fine-tuning)과 배치 정규화

배치 정규화 층이 포함된 모델을 미세조정할 때 해당 배치 정규화 층을 동결(freeze)할 것을 추천한다. 미세조정의 경우 모델 파라미터가 급격하게 변하지 않기에 배치 정규화에 사용된 평균값과 표준편차를 굳이 업데이트할 필요는 없기 때문이다(라고 추정된다).

예제

아래 그림은 2017년에 소개된 Xception 모델의 구조를 보여준다. 빨강색 사각형으로 표시된 부분에 BatchNormalization 층이 사용되었다.

그림 출처: Xception: Deep Learning with Depthwise Separable Convolutions

9.3.4 채널 분리 합성곱

케라스의 SeparableConv2D 층은 Conv2D 층보다 적은 수의 가중치 파라미터를 사용하여 보다 적은 양의 계산으로 성능이 좀 더 좋은 모델을 생성한다. 2017년 Xception 모델 논문에서 소개되었으며 당시 최고의 이미지 분류 성능을 보였다.

참고: 최신 이미지 분류 모델의 성능은 Image Classification on ImageNet을 참조한다.

SeparableConv2D 작동법

SeparableConv2D는 필터를 채널 별로 적용한 후 나중에 채널 별 결과를 합친다. 이렇게 작동하는 층이 채널 분리 합성곱(depthwise separable convolution) 층이며 아래 그림처럼 채널 별로 생성된 결과를 합친 후 1x1 합성곱 신경망을 통과시킨다.

그림 출처: Deep Learning with Python(Manning MEAP)

SeparableConv2D 작동 원리

이미지에 저장된 정보가 채널 별로 서로 독립적이라는 가정을 사용한다. 따라서 채널 별로 서로 다른 필터를 사용한 후 결과들을 1x1 모양의 필터를 사용하여 합친다. 이때 원하는 종류의 채널 수 만큼의 1x1 모양의 필터를 사용하여 다양한 정보를 추출한다.

Conv2DSeparableConv2D의 서로 다른 작동과정은 다음과 같이 설명된다.

그림 출처: Depth-wise Convolution and Depth-wise Separable Convolution

학습가능한 파라미터 수 비교

채널 분리 합성곱 신경망이 Conv2D 층을 사용하는 경우보다 몇 배 이상 적은 수의 파라미터를 사용한다.

경우 1(위 그림): 3x3 모양의 필터 64개를 3개의 채널을 갖는 입력 데이터에 사용할 경우 학습가능한 파라미터 수는 각각 다음과 같다.

경우 2: 3x3 모양의 필터 64개를 10개의 채널을 갖는 입력 데이터에 사용할 경우 학습가능한 파라미터 수는 각각 다음과 같다.

경우 2: 3x3 모양의 필터 64개를 64개의 채널을 갖는 입력 데이터에 사용할 경우 학습가능한 파라미터 수는 각각 다음과 같다.

SeparableConv2D의 약점

채널 분리 합성곱에 사용되는 알고리즘이 CUDA에서 지원되지 않는다. 따라서 GPU를 사용하더라도 기존 Conv2D 층만을 사용한 모델에 비해 학습 속도에 별 차이가 없다. 즉 채널 분리 합성곱이 비록 훨씬 적은 수의 파라미터를 학습에 사용하지만 이로 인해 시간상의 이득은 주지 않는다. 하지만 적은 수의 파라미터를 사용하기에 일반화 성능이 보다 좋은 모델을 구현한다는 점이 매우 중요하다.

참고: CUDA와 cuDNN

예제: Xception 모델

케라스에서 지원하는 Xception 모델의 구성은 2017년 모델과 조금 다르지만 기본적으로 SeparableConv2DBatchNormalizaiton 층을 효율적으로 활용한 블록을 잔차 연결과 함께 사용하여 깊게 쌓은 모델이다.

9.3.5 미니 Xception 모델

미니 Xception 모델을 직접 구현하여 강아지-고양이 이항분류 작업을 실행해본다.

모델 구현에 사용되는 기법을 정리하면 다음과 같다.

참고: 여기서는 비록 이미지 분류 모델을 예제로 활용하지만 앞서 언급된 모든 기법은 컴퓨터 비전 프로젝트 일반에 적용될 수 있다. 예를 들어 DeepLabV3 모델은 Xception 모델을 이용하는 2021년 기준 최고의 이미지 분할 모델이다.

이미지 다운로드 및 데이터 적재

사용하는 데이터셋은 8장에서 사용한 캐글(kaggle)의 강아지-고양이 데이터셋이며, 이미지 다운로드와 훈련셋 등의 적재는 8장에서 사용한 방식과 동일하다.

모델 구현

과대적합은 50번 정도의 에포크 실행 후에 발생한다.

직접 구현한 모델이지만 테스트셋에 대한 정확도가 90% 정도 나온다. 8장에서 직접 구현해서 훈련시켰을 때의 성능인 83% 정도보다 훨씬 높게 나온다.

성능 높이기

보다 성능을 높이려면 하이퍼파라미터 미세조정 및 앙상블 학습을 활용해야 한다(13장 참조).