패턴이 복잡한 컬러 이미지는 MLP로는 분류가 힘들다. 이미지는 위치에 맞는 공간적인 특성을 가지고 있다. But, 배웠던 MLP에서는 flatten으로 펴준 뒤 연산하기 때문에, 이런 공간적인 특성을 잘 살려내지 못한다.
CNN은 공간적 특성을 보존하며 학습할 수 있다. 합성곱 층은 이미지의 일부분을 흝으면서 연산이 진행되며 특징을 잡아내어 학습하기 때문에 층이 깊어지더라도 공간적 특성을 최대한 보존한다.
🌀 CNN의 구조
입력값이 이미지로 들어오고, (1) conv+pooling layer반복(Feature extractor), (2) 쭉 펼쳐서 fully connected layer를 만들고 softmax를 이용해 출력값냄. (classifier)
🌀 Convolution & Pooling
convolution : filter값을 어떻게 주느냐에 따라 결과값이 달라지니 굉장히 중요한 값이라고 볼 수 있다.
padding
이미지 테두리 부분을 특정한 값으로 둘러싸서 처리 (zero-padding 많이쓰임)
padding=’same’ : padding=1, stride=1 입력차원과 출력차원을 같게 해준다.
padding=’valid’ : 패딩 안함.
Stride
보폭
filter size, padding, stride에 따른 feature map 크기 변화
(N_out:출력되는 피쳐수 , N_in : 입력 피쳐수, p:padding, k:kernel크기, s:stride
pooling
가로, 세로 방향의 공간을 줄이기 위해 수행 (max pooling, average pooling등)
학습해야 할 가중치가 없으며, 채널 수가 변하지 않는다.
결국엔, 유의미한 값들만 땡겨오겠다는 뜻이겠지.
CNN의 학습
: Convolution층에 있는 filter의 가중치가 학습된다.
아래 그림은 필터가 어떤 부분을 학습하게 되는지를 나타냈다.
CNN 기본 구조 코드
model = Sequential()
# Feature Extractor
model.add(Conv2D(32,(3,3), padding='same', activation='relu'))
# Conv2D(filter 개수, filter size)
model.add(MaxPooling2D(2,2))
model.add(Conv2D(64,(3,3), padding='same', activation='relu'))
model.add(MaxPooling2D(2,2))
model.add(Conv2D(64,(3,3), padding='same', activation='relu'))
# Classifier
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))
🌀 Transfer Learning
일반적으로 전이 학습은 대량의 데이터를 학습한 사전 학습 모델(Pre-trained Model)의 가중치를 그대로 가져온 뒤 분류기, 즉 완전 연결 신경망 부분만 설계해 사용한다.
사전 학습 모델을 바탕으로 새로운 모델 구축한다. 남이 해놓은 것을 가져오는데, 남이 뭘 해놨냐가 중요하겠지.
사전학습된 데이터는 잘 초기화된 가중치 덩어리들로 이루어져있다. 물론 층도 있고 그렇지만. 층별로 만들어준 좋은 가중치들로 가져와서 사용하겠다는 것이 핵심이다. 일반적으로 사전 학습에서 학습된 가중치는 학습되지 않도록 고정한다.
이로써, 빠르게 좋은 결과를 얻을 수 있다.
Pre-trained Model
이미지 분류에 사용되는 주요 사전 학습 모델인 VGG, Inception, ResNet에 대해 알아보자.
VGG
층의 개수에 따라 VGG13, VGG16, VGG19 있다.
- 모든 합성곱 층에서 3x3 크기 필터 사용하되, 층을 깊게 쌓았다.
- 필터 크기가 작으면 큰 volume을 가진것에 대한 것을 볼 수 있다는 장점이 있다. 윤곽같은것들에 대한 학습이 더욱 용이하겠지.
- 대신 층을 깊게 쌓음으로써, 기존 7x7, 11x11 크기의 필터 이상의 표현력을 가질 수 있도록 한다.
- activation=’relu’, He 초기화 사용 → 층이 깊어지더라도, 기울기 소실 문제 발생하지 않음
- FC layer 에 Dropout사용해 overfitting 방지, optimizer=’adam’ 사용
GoogLeNet (Inception)
세로 방향의 깊이뿐만 아니라, 가로 방향으로도 넓은 신경망 층을 가지고 있다. (Inception 구조)
크기가 다른 filter, pooling을 병렬적으로 적용한 뒤 결과를 조합한다.
ResNet
위로 이루어진 화살표 (건너뛰는 형태) : “Residual Connection” ⇒ 기울기 소실 문제 어느정도 막을 수 있다. ⇒ 층을 깊게 쌓을 수 있다.
NLP에서도 skip connection 사용됬었지.
Residual Connection(=skip connection)
층을 거친 데이터의 출력에 거치지 않은 출력을 더해주게 된다. 이로써, 역전파 과정에서 미분을 적용하더라도 1이상의 값으로 보존되기 때문에 층이 깊어짐에 따라 발생하는 기울기 소실 문제를 어느정도 해결한다.
층이 깊어졌을 때 에러율이 적지. 기울기 소실 방지 효과겠지.
BottleNeck또한 같은 residual 방법을 사용한다. 하지만 효과가 다르다.
BottleNeck은 연산량이 줄어들어, total parameter가 줄어든다. 더 효율적인 측면이 있구나.
사전 학습 모델 중, VGG 사용해보자.
tensorflow.keras.applications를 통해 다양한 pre-trained model 불러올 수 있다.
from tensorflow.keras.applications.vgg16 import VGG16
pretrained_model = VGG16(weights='imagenet', include_top=False)
# wieghts : 사용할 가중치 선택 가능 (imagenet: 이미니젯 데이터셋으로 사전훈련) or None(무작위 초기화)
# include_top=False : 분류기 부분은 내가 스스로 구현할게.
model = Sequential()
model.add(pretrained_model) # VGG 모델을 저자한 변수 불러오기
model.add(GlobalAveragePooling2D())
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))
globalaveragepooling2d를 통해 (batch_size, height, width, channel) → (batch_size, channel)로 변경됨!
GlobalAveragePooling2D
max(avearage) pooling보다 더 급격하게 feature의 수를 줄인다. feature를 1차원 벡터로 만든다.
(H,W,D) ⇒ (1,1,D) 어떤 사이즈의 입력이 들어와도 상관없다!!
channel 개수에 맞게끔 하나의 값으로 변환해 확줄여버림.
그림을 보면 filter 3개 → 각 filter 당 평균값 구해주어 1x1x각 필터의 평균값으로 만든다!!!
fully connected layer를 만들지 않고, global average pooling해주면 연산량이 줄어드는 효과!! 와 함께, 파라미터 개수가 FC layer만큼 폭발적으로 증가하지 않아서, overfitting에서 유리함.
결론적으로, GAP 연산 결과 1차원 벡터가 되기 때문에, 최종 출력에 FC layer대신 GAP 사용 가능.
경우에 따라서, FC layer 하기 전, GAP를 이용해 차원을 줄인 다음 FC layer을 통해 사용되기도한다.
그렇다면 도대체 왜 이미지를 처리하는 과정에서 CNN의 성능이 좋을까?
“They also make strong and mostly correct assumptions about the nature of images (namely, stationarity of statistics and locality of pixel dependencies).” - Alex 논문 중CNN 가정 일부
결론부터 말하자면, 이미지의 특성인 stationarity of statistics와 locality of pixel dependencies를 가정하여 만들어졌기 때문에, CNN모델이 이미지를 잘 다룬다. 동일한 특징이 이미지 내 여러지역에 있을 수 있고, 작은 지역 안에 픽셀 종속성이 있다는 가정 하에 paramter sharing하고, sparse interaction을 가지는 필터와 convolution연산을 하는 것은 찰떡궁합이다.
설명하자면,
stationarity는 시간이 지나도 변치 않는다는 것을 의미히며, 시간이 변해도 동일한 패턴이 반복된다는 뜻이다. 이것은 이미지에 시간 대신 위치에 상관없이 동일한 특성들이 존재한다는 가정이다. convolution 연산에서, 이미지를 입력함수, 필터를 대상함수로 보아 이미지 위에 필터를 이동시키며 이미지에 있는 패턴들과 유사한 형태로 학습한다.
paramter sharing한 conv 연산을 하게된다. feature 하나당, parameter sharing하여 필터 한장이 쓰인다. 이것은 전체 input에 걸쳐 작은 local 영역 선형변환에 연산량이 줄어 FC layer보다 훨씬 효울적이다.
또한 convolution연산의 특징인 translation equivariance(입력에 따라 출력이 변함)+parameter sharing ⇒ translation invariant로 바뀌게 된다. 즉, 위치가 어디있냐에 관계없이 특성 label 확률값은 동일하게 되어질 수 있다.
locality of pixel dependencies는 이미지는 작은 특성들(BBox들 생각)로 구성되어있기 때문에 픽셀의 종속성은 특성이 있는 작은 지역으로 한정된다는 말이다. 각 BBox마다 독립적이며 하나의 BBox안에서는 종속적이라고 볼 수 있겠다. 이러한 가정은 CNN이 sparse interactions특성을 갖는 필터로 convolution연산을 하는 것과 찰떡궁합이다.
Conv filter사이즈를 홀수로 놓는 이유
홀수사이즈의 필터경우 중앙 픽셀의 위치가 명확하다. 하지만, 짝수사이즈의 필터경우 어디를 중앙 픽셀로 해야할지 명확하지 않아서, 필터가 쌓일수록 특성맵에 왜곡이 생기기 때문이다.
'Machine Learning' 카테고리의 다른 글
[CV 3] Beyond Classification - Segmentation, Object Dectection (0) | 2023.05.07 |
---|---|
[CV 2] Image Augmentation (0) | 2023.05.07 |
[Neural Networks 4] Hyperparameter Tuning (0) | 2023.04.24 |
[Neural Networks 3] 더 나은 신경망 학습을 위한 방법 (0) | 2023.04.24 |
[Neural Networks 2] Training Neural Networks (0) | 2023.04.24 |