※ 본 게시물에 사용된 내용의 출처는 대다수 <펭귄브로의 3분 딥러닝-파이토치맛>에서 사용된 자료이며, 개인적인 의견과 해석이 추가된 부분도 존재합니다. 그림의 경우 교재를 따라 그리거나, 제 임의대로 추가 수정한 부분도 존재합니다. 저 역시도 공부하고자 포스팅한 게시물이니, 잘못된 부분은 댓글로 알려주시면 감사하겠습니다.
- CNN(Convlutional Neural Network)의 기초
- Convolutional filter(kernel), Feature map, Padding, Pooling
컴퓨터의 이미지 처리
- 이미지 : 픽셀 값을 가로, 세로로 나열한 일종의 행렬
- 기초적인 인공 신경망(FC layer)기반의 이미지 처리
: 이전에 다루었던 Fully Connected Layer는 다수의 뉴런 집합체이며, 이전 챕터에서 다루었던 FashionMNIST처럼 미리 전처리된, 동일한 패턴(중앙에 숫자가 위치), 흑백, 작은 사이즈의 이미지에서는 간단한 분류 작업이 원활하게 수행되었다.
다만, 일반적인 인공신경망은 다양한 형태의 입력에 대한 확장성, 즉 다양한 데이터에 대한 일반화 능력이 떨어진다. 상단 그림처럼 이미지의 정 중앙에 글씨가 있는 데이터를 위주로 학습한 모델은 Test image도 Train image와 비슷하게 정 중앙에 주요 정보가 포함된 이미지를 사용할 경우에만 성능을 보장할 수 있다. 이는 네트워크가 특징 추출 방법을 학습할 때 이미지의 중앙에만 집중하도록 학습되었기 때문이다.
이런 것을 방지하기 위해서 앞선 예제에서 transform함수를 사용해 이미지를 뒤집고, 늘리는 등 여러 조작을 수행하며, 데이터를 늘렸었다. 하지만 실제 고화질의 이미지(ex. 1920x1080)를 다룰 경우 모든 이미지를 다 수정하는것은 학습 데이터의 개수를 무한대로 늘리는 꼴이며, 만든다 하더라도 모든 변수를 다 반영한다는 것이 불가능에 가까움을 알 수 있다.
이 외에도 FC를 사용한 방식은 이미지의 지역적인 정보를 반영하지 못한다는 치명적인 단점이 존재한다.
하단 이미지를 보면 더 이해하기 쉬운데, 일반적으로 FC layer는 입력 데이터를 일자로 나열하여 데이터를 주는 방식이다. 예로 이전 코드 내 네트워크의 정의부엔 "self.fc1 = nn.Linear(784, 256)" 와 같이 Input Image(28x28)를 일자로 나열한 784개의 입력을 주는 것을 알 수 있다. 또한, 네트워크의 forward 함수만 봐도 2차원의 데이터를 "x = x.view(-1, 784)" 코드를 사용하여, 1차원으로 변경하는 것을 알 수 있는데, 이는 다른의미로 보면 아래 그림과 같이 우리가 아는 2차 행렬의 이미지를 가로로 한줄씩 잘라 쭉 이어붙이는 형태라 볼 수 있다.
이럴 경우 사람처럼 이미지의 연속적인 주변부 특징(context)을 추출할 수 없게 되는데, 다른말로 하면 인접한 픽셀 이미지 간의 상관관계를 무시하는 것을 의미하며, 다시 말해 정보가 손실됨을 뜻한다.
Convolution(컨볼루션)
사람의 관점에서 이미지 처리하는 방법을 살펴보면 아래 그림과 같다.
사람은 누구나 자연스럽게 점, 선의 특징을 보고 눈, 코, 입, 배경, 질감 등 부분적인 특징들은 추출하여 전체 이미지를 유추할 수 있다. 이처럼 컴퓨터도 사람과 같이 계층적인 구조로 이미지를 이해할 수 있게끔 하는 절차가 요구된다.
이를 위해 그림과 같이 주어진 이미지의 윤곽선, 채도를 추출하기 위해 원본 이미지에 특정 필터를 곱하고 더하여 연산하는 방법이 개발되었으며, 이 방법이 바로 컨볼루션(Convolution)이다. 여기서 말하는 필터는 이미지에서 추출하고자 하는 대상(윤곽선, 채도, 질감 이미지 등)에 따라 서로 다른 값을 지닌 필터가 적용된다. 예를 들어 Filter A의 역할이 곡선을 찾는 필터라 생각하면, Filter A는 이미지를 쭉 훑으면서, 매 순간 Convolution연산을 수행하게 되고, 이때 나온 연산결과가 탐지 대상(여기선 곡선)이 내가 훑은 픽셀 영역 안에 있는지 없는지를 검출해주는 도구(함수)라고 생각하면 된다.
상단 GIF가 실제 CNN에서의 Convolution 과정을 간단히 표현한 그림이며, 일정한 크기의 노란색 필터가 이미지를 훑어 나가며, 각 source pixel 값과 filter의 값을 함께 곱하고, 더하여 신규 feature맵(Convolved Feature)를 갱신함을 알 수 있다.
필터의 역할을 조금 더 확실하게 보기 위해 아래 예제를 보자.
상단 이미지와 같이 곡선을 검출하는 특정 필터가 있다고 봤을 때, 아래 이미지처럼 쥐 그림에서 곡선이 있는 부위에 해당 필터를 적용할 경우, 행렬곱이 수행되면서 6600이라는 큰 숫자가 나온다. 이는 이 필터를 적용한 영역에 곡선이 있다는 것을 알 수 있다.
반대로 하단과 같이 필터의 곡선과 다르게 생긴 영역에 필터를 적용하면, 결과값이 0에 수렴한다.
즉, 필터는 내가 훑은 데이터(즉, Input data)에서 해당 특성을 갖고있으면 연산 결과가 크게 나오고, 특성이 없으면 결과값을 0에 수렴하게 주게 된다. 따라서, 해당 특성의 유무를 알 수 있게 해준다.
예전에는 이러한 필터를 특징 추출 전문가가 수작업으로 설계하여 적용했었다. 하지만 이 과정은 이미지가 크고 복잡한 경우에 시간, 비용 측면에서 부담된다는 단점이 존재하였고, 이를 해결하기 위해 딥러닝 모델 스스로 필터 값을 학습하게끔 하는 과정이 CNN(Convolutional Neural Network)이라 할 수 있다. 좀 더 자세한 CNN의 구조는 아래에서 다루도록 한다.
CNN(Convolutional Neural Network)
CNN : 영상(image) 처리를 위한 네트워크
- CNN에서는 Filter == kernel이 같은 의미이며, 이때 Filter(kernel)은 하나의 신경망이라 할 수 있다.
- 앞에서 다뤘던 것처럼 Filter란 현재 내가 훑은 픽셀 영역에 찾고자 하는 대상이 있는지 없는지를 판별하는 모델이며, 실제 컴퓨팅 연산을 해보면 만약 대상이 있을 경우 연산 결과가 크고, 없을 경우 연산 결과가 0에 수렴하게 된다.
- 즉, CNN은 특징(feature)을 추출하는 필터(kernel)를 학습하여 이미지의 특징을 이해하는 모델.
- Convolutional Layer+Activation Function(ex. ReLU)+Pooling Layer+(Dropout, FC, softmax....)
상단의 이미지는 일반적인 CNN이 적용된 DNN을 보여주는 그림이며, CNN은 주로 Pooling, Activation Function이 같이 사용된다. 추가로 마지막에 CNN으로 추출된 이미지 특징에 Softmax나 Fully Connected Layer로 클래스 분류를, 학습 방식에 따라 Dropout을 추가 적용하여 DNN을 구성하는 경우도 많다.
간단한 역할을 설명하면 아래와 같다. 자세한 기능은 다음 절에서 설명한다.
- Conv Layer : 이미지 특징 추출
- Pooling Layer : 여러 특징 중 가장 중요한 특징을 선별 = 덜 중요한 특징 삭제, 차원 감소 효과
- FC + softmax : 최종 클래스 분류 단계
Convolutional Layer
- 합성곱(Convolution)연산을 수행하는 뉴런(Filter)들로 구성됨.
- Filter크기, 모양, 개수, Stride 등을 직접 조정 가능.
+) Stride :
- Filter가 Source pixel(input image)을 훑으며 연산을 할 때, 한번에 이동하는 pixel의 개수
- 데이터의 크기를 줄이는 역할도 수행.
- Filter마다 각자의 역할(탐지하는 종류)가 존재하며, 각 역할은 딥러닝 모델이 학습과정에서 알아서 결정
(ex. Filter 1 : 눈, Filter 2 : 코, Filter 3 : 입 ...)
- Filter의 가중치(weight)를 학습.
상단의 2개의 이미지는 Convolution layer의 연산 과정을 도식화 그림이며, 둘의 의미는 같지만 형태에 따라 이해도가 다를 것 같아, 두 이미지를 모두 가져와봤다. 좌측 이미지는 Convolution에 대한 연산 과정이며, 우측 이미지는 동일한 연산과정이지만, R, G, B 색에 따른 채널의 관점을 추가한 그림이다.
일단 두 이미지 모두 통용되는 사실은 Convolution 연산은 왼쪽 이미지처럼 실제 Source pixel에 Filter 값을 대응시키며, 새로운 1개의 픽셀 값을 결정하는 과정임을 확인할 수 있다. 이때 사람이 정의한다는 부분은 바로 저 Filter의 크기, 모양, 개수를 뜻하며 Filter의 내부 값(weight)은 초기 정의 단계에서 주로 랜덤값을 많이 부여한다. 점차 학습이 진행되면서 각 필터의 역할에 따라 내부 weight가 갱신되어 간다.
우측의 이미지는 맨 처음 Input data로부터 3개의 채널(R, G, B)로 분리됨을 알 수 있다. 이 3개의 채널마다 각각의 파라미터가 다른 feature map이 존재하며, 이때 각각의 채널에 3종류의 서로 다른 Filter가 적용되어 Convolution Result of Channel이라는 각 채널 별 연산 결과가 생성됨을 알 수 있다. 이때 생성된 각 결과물은 하나로 합쳐져 (4, 4, 3)의 Input data에 대하여 최종 Feature Map이 생성된 것을 확인할 수 있다.
Padding
(본 책에서는 Padding에 대한 내용이 없지만, CNN에서 padding은 빠질 수 없는 개념이라 추가해보았다.)
- Convolution 연산을 수행하기 전 Input data(image) 주변에 특정 값을 채워 사이즈를 늘리는 과정.
- 이미지의 가장자리 픽셀 정보가 유실되는 것을 방지하기 위한 기능
- 매 Convolution layer마다 연산된 출력 데이터(feature map)의 크기가 줄어드는 것을 방지하는 기능
(=딥 네트워크로 인해 초반에 정보가 너무 축소되어 버린다는 단점, 이는 곧 성능에 악영향을 끼치기 때문에 이와 같은 상황을 방지)
- 주변부에 아무런 값이 없는 0를 넣는 zero-padding을 많이 사용
Pooling
- 특정 크기의 Pool을 정하고, 데이터의 크기를 축소하는 과정.
- Feature Map 중 주요(중요한) 내용을 추출하는 과정 == Sampling 과정.
- 쓸데없는 데이터를 삭제하는 역할이자, 너무 데이터에 과적합되는 것을 방지
- 연산 방식에 따라 Max Pooling, Min Pooling, Average Pooling, 2D Pooling, 1D Pooling, 3D Pooling...etc.
- 주로 앞에서 본 Padding을 Convolution layer에 적용함으로써, Convolution 연산된 Feature map사이즈는 그대로 유지하고, Pooling 계층에서 크기를 줄여나가는 방식을 많이 사용한다.
==> (개인적으로) 이 과정은 최대한 Convolution 단계에서는 연산을 통해 손실이 없는 feature map을 가져오되, 실제 pooling을 거치면서 중요한 정보만 쏙쏙 합쳐서 핵심 정보를 매 단계마다 생성하는 것이라고 해석된다.
- Max, Min, Avg pooling은 말그대로 특정 사이즈의 윈도우(아래 그림에선 윈도우 사이즈가 (2, 2))내의 값 중 Max(최대), Min(최소), Average(평균)값만을 대표로 뽑아 가져오면 된다. 아래의 GIF를 보면 조금 더 이해하기 쉽다.
CNN의 특징
- 이미지와 같이 Spatial Info가 중요한 지역적 특징 추출 가능
- 고차원 데이터 처리 가능(이미지, 영상,...)
- Weight 수가 Fully Connected 기반의 DNN보다 적다.
- 입출력 데이터 크기가 고정되지 않는다. == 레이어 종류에 따라 다른 크기
- Conv layer+ Activation function + Pooling +(경우에 따라 Dropout)
CNN은 앞에서 다룬 것처럼 주로 Conv layer+ Activation function(특히 ReLU)를 하나의 Convolution 단계로 묶어 사용한다. Activation Function을 사용하는 이유는 앞선 포스팅에서도 말했듯이 Vanishing Gradient와 같은 문제점도 해결하지만, CNN에서의 Activation Function은 Convolution의 결과로 나온 Feature map내의 정량적 연산 결과(제일 처음 예제에서 6600, 0)를 있다, 없다 형태의 비선형 값으로 바꿔주는 역할을 수행한다.
CNN모델에서 Activation Function으로 ReLU를 많이 사용하는 이유는 CNN과 같이 전체 모델의 신경망이 깊은 DNN모델들은 간단한 연산을 수행하는 ReLU가 Sigmoid나 tanh보다 학습 성능면에서 더 효율적이기에 주로 ReLU를 많이 사용한다.
주로 각 단계(Conv + ReLu + Pooling)이 지나면서 이미지가 점점 고차원으로 압축되고, 아래 그림과 같이 (점 --> 선 --> 부위 --> 물체 ...) 등의 계층적 특징을 잡아나간다 보면 이해하기 쉽다.
CNN과 관련된 코드는 다음 포스팅으로 이어간다.