CNN for NLP

13 minute read

본 글은 Understanding Convolutional Neural Networks for NLP를 번역한 글입니다.

자연어 처리를 위한 합성곱 신경망의 이해

합성곱 신경망 (Convolutional Neural Network, CNNs) 을 떠올린다면,

보통 컴퓨터 비전을 떠올리기 마련입니다.

CNN은 이미지 분류에서 중요한 해결책이며

페이스북의 자동 사진 태깅부터 무인자동차에 이르기까지

오늘날의 컴퓨터 비전 시스템의 핵심입니다.

그보다 더 최근에는 CNN을 자연어 처리에 적용하기 시작했고

흥미로운 결과들을 얻었습니다.

이 포스트에서는 CNN이 무엇인지, NLP에서 어떻게 쓰이는지를 요약해보려 합니다.

CNN 뒷면의 직관적인 이해는 컴퓨터 비전에 어떻게 사용되는지 이해하는 것보다 쉽기 때문에

여기서부터 시작해보려 하고,

그 다음 NLP로 천천히 넘어가보겠습니다.

합성곱이란 무엇인가요?

제가 생각했을 때, 합성곱이 무엇인지 가장 이해하기 쉬운 방식은

이를 창을 밀어가면서 행렬에 함수를 적용시키는 것이라 생각하는 것입니다.

설명이 길지만, 사진으로 보면 굉장히 이해하기 쉬워집니다.

conv_vis

(사진 / 합성곱을 거친 특징)

3x3 필터의 합성곱. 출처

왼쪽의 행렬이 흑백 이미지를 나타낸다고 생각해봅시다.

각 엔트리는 하나의 픽셀에 해당하며 0은 흑, 1은 백을 나타냅니다

(보통 0부터 255까지의 grayscale 사진입니다).

옆으로 넘어가는 창은 커널, 필터, 혹은 특징 감지기라고 불립니다.

(kernel, filter, or feature detector)

여기서는 우리는 3x3 필터를 사용하여,

원본 행렬과 원소끼리 곱하고 이들의 합을 구합니다.

전체 합성곱을 구하기 위해 이를 행렬 전체에서 이 필터를 옆으로 밀어가며

이 작업을 각 원소마다 시행합니다.

이걸로 무엇을 할 수 있을지 궁금해하실텐데요,

여기 좀 더 와닿을 수 있는 예를 보여드리겠습니다.

이웃하는 값들의 각 픽셀들에서 평균을 내는 것은 사진을 흐리게 만듭니다:

matrix taj_mahal

픽셀 간의 차를 구하면 이들의 이웃된 값들이 선을 탐지합니다:

(이를 직관적으로 이해하기 위해선, 이미지에서 픽셀의 색이 그 픽셀과 이웃한 것과 같은

부드러운 부분이 어떻게 보일지 생각해봐야 합니다: 더하는 것을 취소하고 결과는 0 혹은 검은색이 됩니다.

아주 날카로운 선이 있다면, 예를 들어 백에서 흑이 되는 작용에선 큰 차이를 낳게 되고 결과는 흰색이 됩니다.)

GIMP manual에는 다른 몇 가지 예가 있습니다.

합성곱이 어떻게 작동하는지를 더 알고 싶으시다면

이 주제에 대한 크리스 올라의 포스트를 읽어보시는 걸 추천드립니다.

합성곱 신경망이란 무엇인가요?

이제 우리는 합성곱이 무엇인지를 압니다. 하지만 CNN에 대해선 어떤가요?

CNN은 기본적으로 그냥 결과에 ReLUtanh 같은 비선형 활성화 함수가 적용되는,

합성곱 계층이 여러개 있는 것입니다.

전통적인 피드포워드 방식의 신경망에선 우리는 각 입력 뉴런을 다음 층의 출력 뉴런에 연결합니다.

이는 완전연결 계층 혹은 affine 계층이라고 불립니다.

CNN에서는 그렇게 하지 않습니다.

대신에, 출력을 계산하기 위해서 입력 층에서 합성곱을 시행합니다.

이 결과로 각 부분의 입력이 출력에 있는 뉴런으로 연결되는 지역적인 연결이 이뤄지게 됩니다.

각 층은 서로 다른 필터를 쓰는데, 위에서 보여드린 것 같이 보통 수백, 수천 개의 필터를 적용하고

이 결과들을 합칩니다.

이는 또한 풀링(pooling 혹은 subsampling) 게층이라고도 불리지만 나중에 설명하겠습니다.

학습 단계 동안 여러분이 실행하고 싶은 작업에 있어 CNN은 자동적으로 그 필터들의 값을 배웁니다.

예를 들어 이미지 분류 작업에서는 CNN은 첫번째 층에서 raw 픽셀들에서 선을 감지하고

두번째 층에선 그 선으로 간단한 모양들을 감지하고,

그보다 더 깊은 층에선 그 모양으로 얼굴 모양 같은 더 고수준의 특징을 결정합니다.

마지막 층에선 이 고수준의 특징을 분류합니다.

conv_summary

이 연산에는 눈 여겨 봐야 할 두 가지 측면인 지역 불변성(Local Invariance)

합성성(Compositionality)이 있습니다.

여러분이 사진에 코끼리가 있는지 없는지 분류하고 싶다고 가정해봅시다.

여러분은 사진 전체에서 필터를 옆으로 밀어가기 때문에

코끼리가 어디에서 나타나는지 별로 신경 쓰지 않습니다.

실제론, 풀링 이 변환, 회전과 스케일링에서 불변성을 부여하지만,

이는 나중에 더 자세하게 설명하겠습니다.

두번째로 중요한 측면은 합성성입니다.

각 필터는 저수준 특징의 지역적인 부분으로 고수준의 대상을 구성합니다.

이것이 컴퓨터 비전에서 CNN이 아주 강력한 이유입니다.

CNN은 여러분이 픽셀에서 선을, 선에서 모양을, 그리고 모양에서 더 복잡한 물체를 만들어내는

직관적인 감각을 만들어냅니다.

그래서, 이게 어떻게 NLP에 적용되는 건가요?

픽셀 대신에, 대부분의 NLP 작업에 입력되는 것들은 행렬로 표현된 문장이나 문서입니다.

행렬의 각 행은 한 토큰에 상응합니다. 보통 단어인데, 글자가 될 수도 있습니다.

따라서 각 행은 단어를 나타내는 벡터입니다.

보통 이 벡터들은 word2vec 이나 GloVe 같은 단어 임베딩 (저차원으로 나타낸) 들이지만

단어(입력값으로서의)를 어휘에 인덱싱하는 원-핫 벡터가 될 수도 있습니다.

100차원 임베딩을 사용하는 10단어의 문장으로

우리는 10x100 차원의 행렬을 입력으로 줄 수 있습니다. 이것이 우리의 “사진”입니다.

시각적으로는 우리의 필터가 사진의 지역적인 부분 단위로 밀고 나가지만

NLP에서는 행렬의 행(단어)을 단위로 밀고 나갑니다. 따라서 필터의 “너비”는

대개 입력 행렬의 너비와 같습니다.

높이, 혹은 크기(region size)는 달라질 수 있습니다만, 창을 한 번에 2-5 단어씩 넘기는 것이 일반적입니다.

이들을 다 합치면 자연어 처리를 위한 합성곱 신경망은 이런 모양을 띄고 있습니다.

(시간을 들여서 이 사진과 차원들이 어떻게 연산되는지 이해하려 해보십시오.

풀링에 대해선 무시하셔도 됩니다. 다음에 다루게 됩니다.)

cnn_for_nlp

문장 분류를 위한 합성곱 신경망의 삽화입니다.

여기선 region size가 2, 3, 4인 세 종류의 필터,

그리고 각 필터가 두 개씩 있습니다.

필터는 모두 문장 행렬에서 합성곱을 수행하고 (다양한 길이의) 특성 맵을 만들어냅니다.

그리고 1-max pooling이 각 맵에서 수행됩니다. 즉 각 특징 맵에서 가장 큰 수가 기록됩니다.

따라서 전체 여섯 개의 맵에서 변수가 하나씩인 벡터가 만들어지고

이 6개의 특징들이 끝에서 두 번째 층의 특징 벡터로 하나로 이어집니다.

마지막으로 소프트맥스 층이 이 특징 벡터를 입력으로 받아 문장을 분류하는데 사용합니다.

이 방법으로 이진 분류를 할 수 있고, 두 종류의 출력이 나올 수가 있는 것을 보여줍니다.

컴퓨터 비전에 쓰였던 멋진 직관은 어쩌고요?

지역 불변성과 지역 합성성은 사진의 직관성을 살렸지만 NLP에서는 별로 그럴 수 없습니다.

여러분은 문장에서 단어가 등장하는 곳에 더 신경을 쓸 것입니다.

서로 가까운 픽셀들은 의미적으로 연관이 되어 있습니다만, (같은 물체의 부분을 나타내므로)

하지만 이는 단어에선 항상 참이 되는 것은 아닙니다.

많은 언어에서 구(phrase)의 부분은 여러가지 다른 단어로 나뉠 수가 있습니다.

합성적인 측면도 명확하지가 않구요.

확실한 것은 명사를 수식하는 형용사 같이 단어들은 특정 방식으로 이어지긴 합니다.

하지만 고수준의 표상이 실제로 무엇을 “의미” 하는지 정확하게 알아내는 방식은

컴퓨터 비전의 예와는 달리 확실하지 않습니다.

이를 다 고려하자면 NLP에선 CNN은 좋은 방식이 아닌 것 같습니다.

순환신경망이 더 직관적으로 말이 됩니다.

순환신경망은 우리가 언어를 어떻게 만드는지를

(혹은 최소한 우리가 언어 처리를 어떻게 한다고 생각하는지를)

닮아있습니다.

왼쪽에서 오른쪽으로 순서대로 읽어나간다던가 하는 것 말이죠.

다행히도, 이게 CNN이 맞지 않는다는 것을 뜻하지는 않습니다.

모든 모델은 틀렸지만, 몇몇은 유용합니다.

NLP 문제에 적용된 CNN은 꽤 좋은 성능을 냅니다.

간단한 백 오브 워즈는 확실히 가정이 잘못되었고 너무 과도하게 단순화된 모델이지만,

그래도 몇 년 간 기준이 되는 접근 방식이었고 결과도 꽤 좋았습니다.

CNN에 대해 한 가지 크게 말할 수 있는게 있다면

CNN은 빠르다는 것입니다. 아주 빠르죠.

합성곱은 컴퓨터 그래픽스의 중심부이고 GPU의 하드웨어 수준에서 구현이 됩니다.

n-grams 같은 것들과 비교하면 CNN은 대상화에 있어 효율적이기도 합니다.

많은 어휘들로, 3-그램 이상의 것을 계산하데 드는 비용은 급속도로 비싸졌습니다.

심지어 구글도 5-그램을 넘어가는 것을 지원하지 않습니다.

합성곱 필터는 모든 어휘들을 다 나타낼 필요 없이 자동으로 표상을 학습합니다.

5보다 큰 필터를 사용하는 것은 완전 합리적인 선택입니다.

첫번째 층에서 학습이 된 많은 필터들은 n-gram과 꽤 비슷한(더 좋을 수도 있습니다) 특징들을

잡아낸다고 생각합니다. 하지만 비용은 덜 들게 되겠죠.

CNN의 하이퍼 파라미터

CNN이 NLP에 적용되는지 설명하기 이전에

CNN을 만들 때 해야할 몇 가지 선택에 대해 알아봅시다.

이 분야에 쓰이는 문서들을 이해하는데 도움이 되기를 바랍니다.

좁은 vs 넓은 합성곱

위에서 합성곱에 대해 설명할 때는 필터를 어떻게 적용하는지에 대한

사소한 디테일을 무시했습니다.

행렬 중앙에 3x3 필터를 적용하는 것은 좋지만, 모서리 부분들은 어떻게 하죠?

행렬에서 위와 왼쪽에 이웃하는 원소가 없는 첫번째 원소에 대해서는 필터를 어떻게 적용하실 건가요?

zero-padding을 사용하실 수 있습니다.

행렬을 벗어나는 모든 원소는 다 0으로 간주합니다.

이로서 여러분의 입력 행렬의 모든 원소에 필터를 적용할 수 있고

더 크거나 같은 크기의 출력을 얻을 수 있습니다.

zero-padding을 더하는 것은 넓은 합성곱으로,

zero-padding을 이용하지 않는 것은 좁은 합성곱으로 불립니다.

1차원에서의 예는 다음과 같습니다.

zero-padding

좁은 vs 넓은 합성곱. 필터 크기 5, 입력 크기 5.

(s = 입력 행렬, c = 필터 적용 후)

입력 크기에 비해 필터가 큰 경우 넓은 합성곱이 얼마나 유용하고 또는 필요한지 보셨을 것입니다.

위에서 좁은 신경망은 출력의 크기가 os 이고,

넓은 신경망은 크기가 os 입니다.

더 일반적으로, 출력 크기를 계산하는 공식은

output_size 입니다.

Stride 크기

여러분의 합성곱에 사용되는 또다른 하이퍼 파라미터는 스트라이드 사이즈입니다.

이는 각 단계 별로 필터를 얼마나 옮길지를 의미합니다.

위의 모든 예에서 스트라이드의 크기는 1이었고,

필터가 연속적으로 겹쳐졌습니다.

스트라이드의 크기가 크면 필터 적용이 적어져 출력 크기가 작아집니다.

스탠포드의 cs231 웹사이트에서 가져온 이 자료는

스트라이드 크기가 1, 2일 때의 1차원 입력을 보여줍니다.

stride

합성곱 스트라이드 크기. 왼쪽: 스트라이드 크기 1, 오른쪽: 스트라이드 크기 2.

이 문서에선 스트라이드의 크기가 1인 것을 주로 보지만,

스트라이드의 크기가 크면 순환신경망과 다소 비슷하게 작동하는 모델을 만들 수도 있습니다.

예를 들어, 트리와도 같아지게 됩니다.

풀링 계층

합성곱 신경망의 주요 측면은 풀링 계층으로, 주로 합성곱 계층 이후에 적용됩니다.

풀링 계층은 입력을 하위 샘플링합니다.

가장 흔한 방법은 각 필터의 결과에 max 동작을 취하는 것입니다.

행렬을 다 풀링을 할 필요는 없으며 창을 씌워서 풀링을 할 수도 있습니다.

예를 들어 다음은 2x2 크기의 창으로 max pooling 하는 모습입니다.

(자연어 처리에선 보통 출력층에 완전히 풀링을 해서 각 필터에서 수 하나만 나오게 합니다.)

pooling

CNN에서의 max pooling. 출처

왜 풀링을 하나요? 몇 가지 이유가 있습니다.

풀링의 한 가지 특징은 고정된 크기의 출력 행렬을 만든다는 것입니다.

(역주 : 풀링 계층은 채널 수를 바꾸지도, 학습(매개변수)이 필요하지도 않으며,

입력의 변화에 영향을 적게 받습니다.)

그리고 이는 분류 작업에서 주로 요구되는 사항입니다.

예를 들어 1000개의 필터가 있고 이를 각각에다가 max pooling을 적용한다면

필터의 크기나 입력의 크기에 상관 없이 여러분은 1000차원의 출력을 얻을 것입니다.

이는 다양한 크기의 문서나 필터를 사용하면서도

분류기에 넣을 수 있는 항상 같은 출력 차원을 얻게 해줍니다.

풀링은 출력 차원을 줄이지만

가장 중요한 정보들을 담고 있습니다.

각 필터가 문장의 특징을 감지하는 것으로 생각해봅시다.

예를 들어 문장이 “대단하지 않은”과 같은

부정적인 의미를 담고 있는지를 감지해낼 수 있습니다.

이 구가 문장의 어디에선가 등장하게 된다면 그 부분에 적용되는 필터는

큰 값을 가지게 되고 다른 부분에선 작은 값을 가지게 됩니다.

최대화를 수행하면서 그 특징이 그 문장에서 나타나는지에 대한 정보를 가져가게 되지만

어디서 나타났는지는 잃어버리게 됩니다.

근데 그 장소에 대한 정보가 그렇게 쓸모있나요?

예, 그렇습니다. 또한 이게 n-gram 모델들이 하는 것이랑 비슷합니다.

장소(문장의 어디서 무엇이 일어나는지)에 대한 전체적인 정보는 잃게 되지만

필터가 포착한 “대단하지 않은”이 “않은 대단하지”와 달라지게 되는 지역적 정보는 가져갈수 있습니다.

이미지 인식에서, 풀링은 사진 변형 (옮기기)와 회전과 같은 것에서 불변성을 가집니다.

한 지역에서 풀링을 하면 출력은 여러분이 이미지를 몇 픽셀 옮기든/회전하든 거의 같을 것입니다.

최대화 작업은 그러거나 말거나 같은 값을 집어낼 것이니 말이죠.

채널

마지막으로 알아야 할 것은 채널입니다.

채널은 여러분의 입력 데이터의 “views”와는 다릅니다.

예를 들어, 이미지 인식에서 여러분은 RGB (red, green, blue) 채널을 가집니다.

여러분은 다르거나 같은 가중치를 가진 채널을 넘나들면서 합성곱을 할 수 있습니다.

자연어 처리에서도 다양한 채널을 가지는 것을 상상할 수 있을 것입니다.

각기 다른 단어 임베딩(word2vecGloVe)에 대한 채널들을 가질 수도 있고,

다른 언어나 다른 방식의 구절로 나타낸 같은 문장에 대해서도 채널을 만들 수도 있습니다.

자연어 처리에 적용된 합성곱 신경망

자연어 처리에의 합성곱 신경망 적용에 대해 알아봅시다.

연구 결과의 몇몇가지를 요약하도록 하겠습니다.

CNN이 자연스럽게 적용되는 대부분의 경우는 감정 분석, 스팸 감지나 주제 분류와 같은

분류 작업인 것 같습니다.

합성곱과 풀링 연산은 단어의 지역적 순서에 대한 정보를 잃어버려서

품사 태깅이나 의미 추출과 같은 sequence tagging 은 순수 CNN 구조에 맞기 힘듭니다.

(불가능한 것은 아닙니다. 위치 정보를 입력에 넣을 수도 있습니다.)

[1]은 다양한 분류 데이터셋에서의 CNN 구조를 평가합니다.

대부분 감정 분석과 주제 분류 작업으로 구성됩니다.

CNN 구조는 데이터셋들 전반, 그리고 최신의 몇몇 데이터에서 아주 좋은 성능을 냅니다.

놀랍게도, 이 논문에 사용된 신경망은 꽤 단순한데

이는 이 합성곱 신경망이 강력한 이유입니다.

입력층은 word2vec 단어 임베딩을 이어붙인 것으로 이뤄진 문장입니다.

이는 여러 필터로 합성곱 층,

max-pooling 계층, 그리고 마지막으로 소프트맥스 분류기를 통과합니다.

이 논문에서는 정적, 동적의 단어 임베딩 형식으로 만들어진

두 개의 다른 채널들로 실험도 또한 진행하였습니다.

한 채널은 훈련 동안 계속 조정되고, 하나는 그렇지 않습니다.

비슷하지만 좀 더 복잡하게, 이 구조는 [2]에 먼저 제시되었습니다.

[6]은 이 구조에 “semantic clustering” 작업을 가하는 계층을 추가합니다.

cnnnlp

[4]는 미리 학습된 word2vec이나 GloVe 없이 밑바닥부터 CNN을 학습시킵니다.

원-핫 벡터에 바로 합성곱을 적용합니다.

저자는 학습해야 할 네트워크의 변수의 수를 줄이면서

공간 활용적인 백오브워즈와도 같은 표상을 입력 데이터에 제시합니다.

[5]에서 저자는 텍스트 지역의 문맥을 예측하는 CNN을 이용하여 학습된

비지도 “지역 임베딩”을 추가해 이 모델을 확장합니다.

이 논문에서 이런 접근은 긴 텍스트(영화 리뷰와 같은)에 대해서 잘 먹힐 것 같지만

짧은 문서(트위터 같은)에 대해서는 확실하지 않습니다.

직관적으로 짧은 텍스트에서 미리 학습된 단어 임베딩을 사용하는 것이

긴 텍스트에 쓰는 것보다는 더 많은 이득을 취할 것입니다.

CNN 구조를 만든다는 것은 선택해야 할 하이퍼 파라미터가 많다는 뜻입니다.

위에서 언급한 것들 중 일부로는 입력할 표상(word2vec, GloVe, one-hot),

합성곱 필터의 크기와 수, 풀링 전략(최대, 평균),

그리고 활성화 함수(ReLU, tanh)가 있습니다.

[7]은 CNN 구조에서 하이퍼 파라미터를 달리하면서 생기는

성능이나 변화같은 영향에 대한 실험적인 평가를 여러 번 진행합니다.

여러분의 문서 분류를 위한 CNN을 구현하기를 원하신다면, 이 논문의 결과를

시작점으로 이용하는 것도 훌륭한 아이디어일 것입니다.

눈에 띄는 결과들로는 max-pooling이 항상 average pooling을 이겼다는 것,

이상적인 필터의 크기 설정은 중요하지만 작업에 따라 다르다는 것,

정규화는 NLP에서는 그다지 큰 차이를 내보이지 않는다는 것들이 있습니다.

이 연구에서의 모든 데이터셋은 그 문서 길이로 봤을 때 꽤 비슷한데,

따라서 이 기준에서 완전 다른 데이터에서는 이 가이드라인이 똑같이 적용되지 않을 수도 있습니다.

[8] 은 관계 추론과 관계 분류 작업에서 CNN을 탐구하고 있습니다.

단어 벡터와 더불어서, 저자는 단어들 간의 상대적인 위치를

합성곱 계층의 입력값의 엔터티로 사용합니다.

이 모델은 엔터티의 위치가 주어지면 각 입력은 한 가지 관계를 가진다고 가정합니다.

[9]와 [10]은 비슷한 모델을 살핍니다.

자연어 처리에서 CNN을 쓰는 또다른 흥미로운 사례는

마이크로소프트 연구소에서 나온 [11]과 [12]에서 찾아볼 수 있습니다.

이 문서는 정보 회수(Information Retrieval)에 쓰일 수 있는

문장들의 semantically meaningful representations 을 어떻게 배울 수 있는지에 대해서 설명합니다.

이 논문에서 든 예에는 독자들이 현재 읽고 있는 것에 기반해

독자들이 흥미를 느낄 만한 문서를 추천해주는 것도 있습니다.

문장 표상은 검색 엔진 로그 데이터로 학습됩니다.

대부분의 CNN 구조는 학습 과정의 일부로서

한 가지 혹은 여러가지 방법으로 단어와 문장의 임베딩을 배웁니다.

모든 논문이 학습의 이런 측면을 다루거나

학습된 임베딩이 얼마나 의미있는지는 다루지 않습니다.

[13]은 페이스북 게시글의 해시태그를 예측하는 CNN구조를 선보입니다.

그와 동시에 단어와 문장의 의미있는 임베딩도 만들어냅니다.

이렇게 학습된 임베딩은 클릭스트림 데이터로 훈련된

사용자에게 흥미를 느낄만한 문서 추천해주기 같은

또 다른 작업들에게 적용됩니다.

글자 레벨의 CNN

지금까지의 모델들은 모두 단어에 기반했습니다.

하지만 CNN을 바로 글자에 적용하는 연구도 있어왔습니다.

[14]는 글자 수준의 임베딩을 학습하고, 미리 학습된 단어 임베딩과 조합하여

CNN을 품사 태깅에 활용합니다.

[15], [16]은 미리 학습된 임베딩에 대한 필요 없이

CNN을 글자에 바로 적용하는 방법에 대해 탐구합니다.

특히, 저자는 총 9층의 상대적으로 깊은 신경망을 사용하고,

이를 감정 분석과 문서 분류 작업에 적용합니다.

결과는 글자 수준 입력에서 바로 배우는 것이 큰 데이터셋(수백만가지의 예)에서는

아주 잘 작동하지만, 그보다 작은 데이터셋(수백, 수천가지의 예)에서는

단순한 모델보다 낮은 성능을 보입니다.

[17]은 글자 수준의 CNN 출력을 LSTM의 각 단계 입력값으로 사용하면서

언어 모델에서 글자 수준의 합성곱 응용을 탐구합니다.

같은 모델이 다양한 언어에 적용됩니다.

놀라운 것은, 근본적으로 위의 논문들이 지난 1~2년 동안 나왔다는 것입니다.

확실히 NLP에의 CNN 연구는

Natural Language Processing (almost) from Scratch와 같이

이전에도 훌륭하게 있어왔지만,

새로운 결과와 최신 시스템의 속도는 분명 점점 더 빨라지고 있습니다.

참조 문헌