Data/자연어처리

자연어 처리를 위한 피드포워드 신경망(2)/ 합성곱 신경망, 파이토치 구현

빛날희- 2021. 7. 22. 18:37

파이토치로 배우는 자연어처리 책을 참고하여 작성하였습니다.

참고 강의


▶ 합성곱 신경망이란

합성곱 신경망은 공간상의 부분 구조를 감지하는 데 적합하기 때문에 이미지 처리에서 많이 사용되는 신경망이다. CNN은 소수의 가중치를 사용해 입력 데이터 텐서를 스캔하여 구조를 인식한다. 

파이토치에서는 1,2,3 차원의 합성곱이 가능한데 각 합성곱이 적합한 분야는 다음과 같다. 

 

- Conv 1d: 1차원 합성곱 연산으로 각 타임 스텝에 특성벡터가 존재하는 시계열에 잘 맞고 자연어처리에서 합성곱 연산으로 대체로 1차원 합성곱으로 이뤄진다. 

- Conv2d: 2차원 합성곱으로 데이터의 두방향을 따라 시공간 패턴을 감지하므로 이미지처리 분야에서 많이 사용된다. 

- Conv3d: 3차원 합성곱으로 데이터의 세 방향을 따라 패턴을 감지하므로 이미지프레임과 시간차원을 통해 데이터를 나타내는 비디오 처리 분야에서 많이 사용된다. 

 

 

 

▶ CNN 핵심 개념

다음으로 CNN을 이해하는 데 필요한 몇가지 개념을 짚고 넘어가자. 

 

▷ 채널 Channel

채널은 입력의 각 포인트에 있는 특성 차원으로 이미지의 경우 Red, Green, Blue에 해당하는 차원 3개가 겹쳐있다. 이 차원들을 입력으로 함께 넣음으로써 색깔이 존재하는 이미지를 입력으로 넣을 수 있다. 텍스트의 경우엔 픽셀이 단어라면 채널의 개수는 어휘사전의 크기로 볼 수 있을 것이다. 

  • in_channels: 입력 채널 개수
  • out_channels: 출력 채널 개수

 

 

▷ 커널 kernel(=filter)

커널은 력으로 들어온 데이터를 스캔하는데 사용되는 일종의 스캔기라고 볼 수 있다. 

다음과 같이 'ㅁ'이라는 텍스트가 있는 이미지 데이터를 입력으로 넣었다고 해보자. 

그림 1. (http://makeyourownneuralnetwork.blogspot.com/2020/02/calculating-output-size-of-convolutions.html)

여기서 커널은 2행 2열의 행렬이다. 하나의 커널을 통해 'ㅁ'이라는 이미지 데이터를 한칸씩 옮기며(stride=1) 스캔한다. 커널 행렬 내에는 위와 같은 요소값들이 존재한다. (0은 검정색, 255는 흰색으로 그림에선 input의 바탕부분이 핑크색이지만 흰색이라고 가정하자)

 

output에선 커널과 커널이 스캔하고 있는 input의 행렬 값들을 서로 곱해서 하나의 요소로 나타낸다. 따라서 output은 커널이 input을 몇번 스캔했는지에 따라 그 크기가 정해진다고 볼 수 있다. 커널의 크기는 커널 행렬의 너비를 말하는 것으로 커널 크기를 늘리면 스캔을 많이 하지 않아도 되기 때문에 출력 값의 크기는 줄어든다.

 

그림 1에서는 커널의 크기를 2로 잡아 행과 열을 5번씩 스캔해서 5x5의 output을 산출했지만 커널의 크기를 4로 잡으면 행과 열을 3번씩 스캔해도 되기 때문에 output은 3x3 크기가 될 것이다. 

  • kernel_size: 커널 크기

 

 

▷ 스트라이드 stride

스트라이드는 합성 곱 간의 스텝크기를 제어한다. 스트라이드가 작을 수록 커널이 많이 겹치고 스트라이드가 클수록 커널이 겹치지 않기 때문에 스캔 수가 줄어들어 output의 크기가 작아진다. 따라서 스트라이드를 높여 텐서크기를 의도적으로 줄여 정보를 요약하여 사용하기도 한다. 

 

그림 1에서는 stride를 1로 잡고 있는 stride를 3으로 잡으면 2x2의 커널을 가지고 3번씩 스캔하면 되기 때문에 output의 크기는 3x3으로 요약될 것이다. 

  • stride: 스트라이드 크기

 

 

▷ 패딩 padding

kernel과 stride를 통해 특성맵(output)을 도출하다보면 그 크기가 작아져 정보의 손실이 발생하는 단점이 생긴다. 이 단점을 해결하기 위해, 즉 특성맵의 크기가 줄어들어 정보손실이 발생하는 것을 막기 위해 인위적으로 입력 텐서를 0으로 둘러싸 그림2와 같이 입력 벡터크기를 늘려줄 수 있다. 이를 제로 패딩이라고 부른다. 

그림 2. 제로패딩 적용

제로 패딩을 하면

첫번째, output의 크기를 이전보다 늘림으로써 정보손실을 완화시킬 수 있다. 

두번째, 입력 벡터의 경계를 제로패딩을 통해 전보다 분명히 인식할 수 있다. 

는 장점이 있다. 

 

 

 

▷ 다일레이션 dilation

다일레이션은 커널이 입력 행렬에 적용되는 방식을 제어하는 것으로 커널의 형태를 달리함으로써 넓은 입력 공간을 요약하는데 유용하게 사용될 수 있다. 

그림 3. 다일레이션 크기에 따른 형태 (https://www.researchgate.net/figure/An-illustration-of-the-receptive-field-for-one-dilated-convolution-with-different_fig1_336002670)

그림 3과 같이 dilation이 하나씩 늘때마다 커널 사이에 공간이 생기면서 커널의 크기가 커진다. 커진 커널은 넓은 입력 공간을 요약할 수 있고 합성 곱 층을 쌓을 때 유용하게 사용될 수 있다. 

 

 

 

▶ 합성곱 신경망 학습 과정

합성곱 신경망은 다음 그림 4와 같이 입력 벡터에 대해 합성곱 층을 거치면서 특성맵을 계속해서 산출하다가 산출된 마지막 특성맵을 대상으로 flatten시켜준다(행렬을 하나의 값으로 만들어 배열에 위치). 마지막으로 flattened를 Fully-connected층에 넣어 값을 예측하고 예측된 값을 실제값과 비교하여 학습시킨다. 

그림4. 합성곱 신경망 학습(https://www.google.com/url?sa=i&url=https%3A%2F%2Ftowardsdatascience.com%2Fa-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53&psig=AOvVaw2JlRi0x18nxLTf-dd2SMoA&ust=1627027478782000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCODunOmb9vECFQAAAAAdAAAAABAI)

 

 

 

▶ 파이토치 구현 - 코드출처

파이토치를 통해 합성곱 층을 구현하는 방법과 층을 거칠 때마다 벡터의 크기가 어떻게 달라지는지 보고자한다. 합성곱 신경망을 통해 원하는 특성벡터를 만드는 것이 목적으로 합성 곱 층을 통해 특성 맵을 추출하고 Fully connected Linear층을 통해 예측벡터를 만들어보고자 한다. 

 

우선 합성곱 층 하나를 만들었다. 입력 사이즈는 처음엔 [2,10,7]이었는데 conv1을 거치면서 채널 크기가 16으로 늘어나고 커널 사이즈가 3이기 때문에 너비는 다음 그림 5와 같이 너비가 7인 벡터를 5번 스캔하여 5로 줄어든다. 

그림 5. 너비 7에 대한 커널3의 스캔

 

 

2번째와 3번째 합성곱 층을 추가하여 출력 텐서 크기를 줄이고 출력의 마지막 차원의 size가 1이 되도록 구성했다. 그리고 크기가 1인 차원을 제거해주는 squeeze함수를 사용해 크기가 1인 차원이 모두 제거된 특성 벡터를 만들었다. 

 

 

이렇게 만들어진 특성벡터를 linear층과 같은 신경망 구성요소에 사용해 예측벡터를 만들 수 있다. 위의 코드에서는 커널을 통해 스캔하면서 하나의 특성 벡터로 줄였는데 이 외에도 추가적으로 다음 두가지 방법을 사용해 줄일 수 있다. 

 

 

위의 intermediate1 벡터를 대상으로 첫번째 방법은 모든 요소들을 하나의 벡터로 펼친것이다. 해당 방식은 모든 정보를 살릴 순 있지만 데이터의 크기가 지나치게 커질 수 있다. 

두번째 방법은 합성곱의 평균을 사용하기 때문에 연산과정에서 필요한 정보를 잃을 수 있다.