2번째로 설명할 faster R-CNN은 Object Detection에 사용되는 모델로, Object Detection의 시초인 R-CNN을 개선한 모델이다. 따라서 faster R-CNN을 설명하기 앞서 R-CNN을 포함한 Object Detection의 주요한 논문들의 흐름을 설명하겠다.

R-CNN

출처 : https://woosikyang.github.io/fast-rcnn.html
출처 : https://yeomko.tistory.com/13


R-CNN은 말 그대로 CNN을 사용하여 Object Detection에서 높은 성능을 보였다. R-CNN의 구조를 그림으로 설명하자면 위의 이미지들로 나타낼 수 있으며, R-CNN의 학습과정을 자세히 설명하자면 다음과 같다.

알고리즘

1. Input으로 들어온 이미지를 Selective Search 알고리즘을 사용하여 후보 영역(Region proposal)을 생성한다. (~2k : 2000여개)
2. 각각의 후보 영역(Region proposal)을 고정된 크기로 Warp하여 CNN input으로 사용한다.
+) CNN은 이미 ImageNet을 활용한 pre-trained된 네트워크를 사용 + fine tune(Object Detection용 데이터 셋 사용)
3. CNN을 통해 나온 feature map을 사용하여 벡터를 추출하고 클래스 별로 SVM Classifier 학습, regressor를 통한 Bounding Box Regression을 진행한다.
+) SVM Classification을 한 후의 2000여개의 박스들은 어떤 물체일 확률 값을 갖게 되며, 2000여개의 박스를 모두 사용하는 것이 아닌, 가장 확률값이 높은 박스만을 사용하기 위해 IoU(Intercetion over Union)을 적용하여 물체 전체를 대상화할 수 있는 박스 한개를 만들어낸다. 이 과정을 Non-Maximun Supperssion이라고 하며, IoU는 쉽게 말해 두 박스의 교집합을 합집합으로 나눠준 값으로 두 박스가 일치할수록 1에 가까운 값이 나오게 된다.
+) Bounding Box Regression을 사용하는 이유는 Selective Search를 통해 찾은 박스 위치가 부정확하기 때문에 모델의 성능을 높이기 위해 박스 위치를 교정하기 위해 사용한다. 박스의 위치를 조절하는 과정은 박스의 좌표 및 너비 높이를 조정하는 함수의 가중치를 곱하며 선형 회귀 학습을 시키기 때문에 Regression이 함께 들어가 있다.

R-CNN의 한계점

  • 합성곱 신경망(conv)의 입력을 위한 고정된 크기를 위해 wraping/crop을 사용해야 하며, 그 과정에서 input 이미지 정보의 손실이 일어난다.
  • 2000여개의 영역마다 CNN을 적용해야 하기 때문에 학습 시간이 오래 걸린다.
  • 학습이 여러 단계(conv-SVM Classifier/Bounding Box Regression)로 이루어지기 때문에 학습 시간이 오래 걸리며, 대용량의 저장 공간을 필요로 한다.
  • Object Detection 속도가 느리다. (이미지 하나당 CPU에서 54', GPU에서 13')

이와 관련해 더 자세한 설명을 필요로한다면 여기를 참고하길 바란다. 설명이 매우 친절히 되어있고 Object Detection에 대한 논문들이 순차적으로 정리되어 있어 이해하기 편하다.









Fast R-CNN을 설명하기에 앞서 SPPNet에 대해서도 설명하면 좋지만 내가 여기서 말하고 싶은 논문은 Faster R-CNN이기 때문에 SPPNet에 대한 내용은 여기여기를 참고하길 바란다.

SPPNet

출처 : https://n1094.tistory.com/30


SPPNet에 대해 간략히 설명하자면 R-CNN의 단점을 보완하고자 만들어진 모델로, R-CNN은 Region proposal을 하나 하나 conv input으로 사용한 반면, SPPNet은 input 이미지 자체를 Convolution Network를 통해 feature map을 만들고 그 feature map으로부터 Region proposal을 만든다는 차이점이 있다. 이 덕에 SPPNet은 학습 속도를 개선할 수 있었다.








Fast R-CNN

출처 : https://bskyvision.com/702
출처 : https://jaehyeongan.github.io/2019/10/10/R-CNN/


Fast R-CNN은 R-CNN과 SPPNet의 단점을 개선하고자 나온 모델이다. R-CNN과 SPPNet의 단점은 학습이 여러 단계로 진행되며, 그로 인해 많은 학습 시간과 GPU 계산 용량이 요구되고 Object Detect에 있어 시간이 오래 걸린다는 것이다.

Fast R-CNN은 CNN 특징 추출 및 Classification, Bounding Box Regression을 모두 하나의 모델에서 학습시키고자 한 모델이다.

알고리즘

1. 전체 이미지를 미리 학습된 CNN을 통과시켜 feature map을 추출한다.
2. feature map에서 RoI(Region of Interest)들을 찾아준다.
+) RoI들은 input 이미지에서 Selective Search를 통해 찾은 것을 feature map에 적용한 것이다.
3. (Selective Search를 통해 찾은) 각각의 RoI에 대해 RoI Pooling을 진행하여 고정된 크기의 벡터를 추출한다.
4. feature vector는 fully vector들을 통과한 후, softmax와 bounding box regression의 input으로 들어간다.
+) softmax는 SVM을 대신하는 방법으로, 해당 RoI가 어떤 물체인지를 classification한다.
+) bounding box regression은 selective search로 찾은 박스의 위치를 조절한다.

Fast R-CNN은 SPPNet처럼 input 이미지를 CNN에 통과한 뒤, 그 feature map을 공유한다.
SPPNet은 그 뒤의 과정이 R-CNN과 동일하지만, Fast R-CNN은 RoI Pooling을 사용하여 end-to-end로 학습 가능하게 했다는 것이 가장 큰 특징이다. 이러한 end-to-end 학습이 가능하게 되면서 학습 속도와 정확도를 모두 향상시킬 수 있게 되었다.

RoI Pooling Layer

Fast R-CNN의 핵심인 RoI Pooling은 RoI 영역에 해당하는 부분만 max-pooling을 통해 feature map으로부터 고정된 길이의 저차원 벡터로 축소하는 단계를 의미한다. RoI Pooling에 대한 자세한 내용은 아래의 그림을 참고하며 설명하도록 하겠다.


위의 h*w의 영역이 바로 CNN의 output인 feature map에서 RoI 영역에 해당한다. 이 RoI 영역은 CNN을 통과한 feature map에 selective search 기반의 region proposal을 통해 추출된다.

이렇게 정의된 RoI(h*w)를 H*W의 고정된 작은 윈도우 사이즈로 나누고, 나눠진 영역에서 max-pooling을 적용하면 결과값으로 항상 H*W 크기의 feature map이 생성된다. 이런 pooling을 하는 이유는, 다 제각각의 크기인 RoI 영역을 동일한 크기로 맞춰 fc(fullly connect) layer로 넘기기 위함이다.

RoI pooling layer


위의 이미지를 보면 RoI 영역 안의 max-pooling 영역이 모두 동일하지 않음을 알 수 있다. 그럼에도 불구하고 고정된 길이의 벡터로 만드는 것이 RoI pooling layer의 역할이다.

이렇게 RoI pooling layer를 통해 전부 동일한 크기가 된 output들은 fully connected layer를 거쳐 softmax classifcation과 bounding box regression이 수행된다.

이 모든 과정들이 하나의 conv 모델에 의해 동시에 수행되기 때문에 연산속도가 빠르고 정확도가 높아질 수 있었다.

Fast R-CNN은 RoI pooling layer를 사용하여 CNN 특징 추출 및 Classification, Bounding Box Regression을 모두 하나의 모델에서 학습시킬 수 있게 되어 R-CNN과 SPPNet에 비해 빠른 연산 속도와 정확도를 나타낼 수 있었다. 하지만 여전히 Region proposal을 selective search로 수행하여 Region proposal 연산이 느리다는 단점이 있다. (selective search 알고리즘은 GPU를 사용하기 부적합하다.)

Fast R-CNN에 대해 더 자세한 설명이 필요하다면 여기, 여기, 여기를 참고하길 바란다.










Faster R-CNN

Faster R-CNN은 이름과 같이 Fast R-CNN의 개선된 모델로, end-to-end 구조를 위한 전체적인 모델 구조는 Fast R-CNN과 동일하다. 하지만 Fast R-CNN의 단점이었던 Region Proposal을 개선하고자 selective search를 사용하지 않고, Region Proposal Network(RPN)를 통해서 RoI를 계산한다. 이 덕분에 GPU를 통해 RoI 연산이 가능해졌으며 RoI 연산도 학습을 시켜 정확도를 높였다. 따라서 기존의 Selective Search는 2000여개의 RoI를 계산하는 반면 RPN은 더 적은 수의 RoI를 계산하면서도 높은 정확도를 보인다.

Faster R-CNN


위의 이미지를 보면 알 수 있다시피, Faster R-CNN은 RoI를 구하는 방법으로 RPN을 사용하는 것 외에는 Fast R-CNN과 모두 동일하다는 것을 알 수 있다. 그렇다면 RPN의 구조는 정확하게 어떻게 생긴걸까? 이에 대한 내용을 아래에 자세히 다루도록 하겠다.

Region Proposal Network

Region Proposal Network(RPN) 구조


참고한 블로그에 의하면 아래의 이미지가 더 직관적으로 RPN의 구조를 이해하기 쉬운 이미지라고 하여 둘 다 갖고 왔다. RPN이 동작하는 원리는 다음과 같다.

알고리즘

1. CNN을 통해 뽑아낸 feature map을 입력으로 받는다. 이 때, feature map의 크기를 H*W*C(세로*가로*채널수)로 잡는다.
2. feature map에 3x3 convolution을 256 channel (or 512 channel)만큼 수행한다. 이 때, padding을 1로 설정해주어 H x W가 보존되도록 진행하며, intermediate layer 수행 결과 H*W*256 (or 512) 크기의 두 번째 featur map을 얻는다.
3. 2번째 feature map을 입력으로하여 classification(cls layer)과 bounding box regression(reg layer) 예측 값을 계산한다.
+) 이 과정은 Fully Connected Layer가 아니라 1 x 1 컨볼루션을 이용하여 계산하는 Fully Convolution Network의 특징을 갖는다. 이는 입력 이미지의 크기에 상관없이 동작할 수 있도록 하기 위함이며 자세한 내용은 Fully Convolution Network을 참고하길 바란다.
4. Classification layer에서는 1 x 1 컨볼루션을 (2(Object인지 아닌지를 나타냄) x 9(앵커(Anchor) 개수)) 채널 수 만큼 수행하며, 그 결과로 H*W*18 크기의 feature map을 얻는다. H*W 상의 하나의 인덱스는 피쳐맵 상의 좌표를 의미하고, 그 아래 18개의 채널은 각각 해당 좌표를 Anchor로 삼아 k개의 앵커 박스들이 object인지 아닌지에 대한 예측 값을 담는다. 즉, 한번의 1x1 컨볼루션으로 H x W 개의 Anchor 좌표들에 대한 예측을 모두 수행할 수 있다. 이제 이 값들을 적절히 reshape 해준 다음 Softmax를 적용하여 해당 Anchor가 Object일 확률 값을 얻는다.
+) 여기서 앵커(Anchor)란, 각 슬라이딩 윈도우에서 bounding box의 후보로 사용되는 상자를 의미하며 이동불변성의 특징을 갖는다.
5. Bounding Box Regression 예측 값을 얻기 위한 1 x 1 컨볼루션을 (4 x 9) 채널 수 만큼 수행하며 regression이기 때문에 결과로 얻은 값을 그대로 사용한다.
6. Classification의 값과 Bounding Box Regression의 값들을 통해 RoI를 계산한다.
+) 먼저 Classification을 통해서 얻은 물체일 확률 값들을 정렬한 다음, 높은 순으로 K개의 앵커를 추려낸다. 그 후, K개의 앵커들에 각각 Bounding box regression을 적용하고 Non-Maximum-Suppression을 적용하여 RoI을 구한다.

Training

Faster R-CNN은 크게 RPN과 Fast R-CNN으로 구성되어있는 것으로 나눌 수 있고, 결론적으로 RPN이 RoI를 제대로 만들어야 학습이 잘 되기 때문에 4단계에 걸쳐 모델을 번갈아 학습시킨다. 4단계는 다음과 같다.

1. ImageNet pretrained 모델을 불러온 후, Region Proposal을 위해 end-to-end로 RPN을 학습시킨다.
2. 1단계에서 학습시킨 RPN에서 기본 CNN을 제외한 Region Proposal layer만을 가져와 Fast R-CNN을 학습시킨다.
+) 첫 feature map을 추출하는 CNN까지 fine tune을 시킨다.
3. 학습시킨 Fast R-CNN과 RPN을 불러와 다른 가중치들(공통된 conv layer 고정)을 고정하고 RPN에 해당하는 layer들만 fine tune 시킨다.
+) 이 때부터 RPN과 Fast R-CNN이 conv weight를 공유하게 된다.
4. 공유된 conv layer를 고정시키고 Fast R-CNN에 해당하는 레이어만 fine tune 시킨다.

이러한 과정을 통해 만들어진 Faster R-CNN은 굉장히 빠른 속도와 높은 정확도를 보인다. 여기에 쓰지는 않았지만 Faster R-CNN의 손실함수에 대해 알고 싶다면 여기를 참고하길 바란다.


또한 내가 Faster R-CNN을 공부하면서 참고했던 유튜브와 블로그의 링크를 남길테니 참고하길 바란다.
Object Detection 전체 흐름을 알려주는 블로그, 유튜브1, 유튜브2










R-CNN / SPPNet / Fast R-CNN / Faster R-CNN (계보) 요약

R-CNN RoI(Selective Search) ☞ conv ☞ SVM, Bbox reg
SPPNet conv ☞ RoI(Selective Search) ☞ SVM, Bbox reg
Fast R-CNN conv ☞ RoI(Selective Search) RoI pooling layer Softmax, Bbox reg
Faster R-CNN conv ☞ RoI(Region Proposal Network) RoI pooling layer ☞ Softmax, Bbox reg




'인공지능 > 논문 리뷰' 카테고리의 다른 글

1. Attention Is All You Need  (3) 2020.11.02

 

 

좋은 기회로 ML Research 인턴을 할 수 있게 되었는데, 이래 저래 논문을 많이 볼거 같아서 아예 게시판을 하나 새로 팠다...

열심히 써야지... 논문... 화이팅...!!!!!! 내 인생도 화이팅!!!!!!!!!

 

 

Attention Is All You Need

이 논문은 8명의 리서처가 만든 모델이다. (2차 면접 때 공부해오라고 하셨던 논문이었는데 ppt 만들면서 이걸 언급하니까 굳이 왜 넣으냐고 하셨음ㅋㅋㅋㅋ 내가 생각해도 그렇긴한데ㅋㅋㅎ,, 그냥 말문 트려고 여기서도 또 넣는다 ㅎㅋ) 2017년 12월 6일에 나온 논문으로 굉장히 유명한 논문이다. 대략적으로 말하자면 이 논문은 기존의 RNN 모델의 단점을 보완하고자 Attention만을 활용하여 만든 모델 구조라고 보면 되겠다. 그렇다면 더 자세히 보도록 하자.

 

 

RNN 구조의 문제점

Recurrent Neural Network

 

RNN은 Recurrent Neural Network의 약자로 순환신경망이라는 뜻이다. RNN의 나름 자세한 설명은 여기를 참고하길 바란다. 여기서는 논문 이야기만으로도 빡빡하니 대략적으로 RNN에 대해 설명하고 넘어가도록 하겠다. 우리는 왜 RNN을 사용하는가? 그 이유는 시계열 데이터를 예측하기 위해서이다. 대표적인 시계열 데이터로는 자연어가 있겠다.

 

나는 방금 밥을 먹었다. 그래서 지금 나는 배가 (         ).

 

여기서 괄호 안에 들어올 말을 예측하기 위해서는 앞의 데이터에 대한 정보도 함께 갖고 있어야 한다. 나는 방금 밥을 먹었기 때문에 지금은 배가 고프지 않을것이다. 따라서 괄호 안에는 '고프지 않다'가 들어가는 것이 맞다고 볼 수 있겠다. 이렇게 문맥을 파악해야만 단어를 유추할 수 있는 자연어를 처리하기 위해 우리는 RNN, 즉 순환신경망을 사용한다. RNN은 데이터의 입력 순서를 기억하며 맥락을 파악하고 원하는 위치에 나오는 문장을 예측한다.

 

seq2seq 구조

 

위의 이미지는 RNN 종류 중 하나인 LSTM으로 구성된 seq2seq 구조를 보여준다. 자, 그러면 이제 본론으로 들어가 RNN의 문제점이 무엇인지 보도록 하자. 위의 이미지를 보면 Hi I am Sooft ware 가 Encoding 층의 입력 데이터로 주어지고 이것을 인코더의 LSTM이 잘 기억하고 학습하여 Decoder의 LSTM으로 전달하며 Decoder는 안녕하세요 Sooft ware 입니다 라는 문장을 출력한다. 이 구조에서 문장 길이에 비례하는 만큼의 (혹은 비례하는 만큼의 크기인 매개변수) LSTM이 필요하다는 것을 볼 수 있고 LSTM이 순차적으로 정보를 입력받고 넘겨주는 것을 볼 수 있을 것이다.

 

Encoder의 입력 데이터가 Hi I am Sooft ware 로 짧아서 다행이지, 만약 The animal didn't cross the street because it was too tired 와 같이 긴 문장에서 it이 가르키는 것이 무엇인지 seq2seq 구조의 모델은 이해할 수 있을까?

 

이와 같이 학습되는(입력되는) 문장이 길어지면 길어질수록 서로 멀리 떨어진 문장에 대한 정보가 줄어들면서 제대로된 예측을 할 수 없는 것을 Long-term dependency problem 이라고 한다.

 

또한 순차적으로 연산을 하다보니 병렬화가 불가능하여 연산 속도가 저하된다는 단점 또한 존재한다. 컴퓨터는 고도로 병렬 연산에 최적화되어있기 때문에 병렬 연산을 하지 못한다는 것은 아주 큰 손해이다.

 

다시 한번 정리하자면 결국 기존 RNN 구조는 Long-term dependency problem과 병렬 연산 불가능으로 인한 연산 속도 저하의 문제점이 있다고 볼 수 있다.

 

 

Transformer

위의 RNN의 단점을 보완하고자 기존의 seq2seq 구조에서 오직 Attention만을 사용하는 것을 바로 Transformer라고 하며 논문에서 설명하고 있는 모델의 구조가 바로 Transformer를 의미한다. Attention에 대한 자세한 내용은 여기를 참고하길 바란다. 결론적으로 Attention이란, 단어의 전체적인 정보를 저장하는 것이라고 이해하면 된다. (너무 간략하기 짝이 없으니 꼭 더 찾아보길 바란다.)

 

Transformer가 얼마나 성능이 좋은지를 나타내는 그래프 (논문에 있음)

 

위의 그래프는 모델 별 BLEU score와 Training Cost를 보여준다. 결론적으로 Transformer는 다른 Model들에 비해 Training Cost도 적으면서 높은 BLEU 점수를 받았다는 것을 자랑 보여주는 것이다. 이렇게 완벽하고 멋진 Transformer의 구조에 대해 이제 자세히 알아보도록 하자.

 

Transformer 구조

 

논문 순서와는 약간 다르게 나는 모델의 입력 데이터부터 순차적으로 올라가도록 하겠다.

 

 

 

Input(Embedding & Positional Encoding)

Input 데이터는 수백만개의 문장 데이터이다. 이 문장 데이터를 어떻게 컴퓨터가 이해할 수 있을까? 컴퓨터는 최강 공돌이 공순이라서 숫자밖에 모르는 바보인데 말이다. 그래서 우리는 바보한테 맞춰줘야 한다. 우리는 문자인 단어를 숫자로 변경한다. 그 과정을 Embedding이라고 한다. Embedding을 통해 우리는 문자인 단어들을 각각 잘 나타낼 수 있는 숫자로 변경한다. 그리고 숫자로 변환된 데이터(벡터 형태이다)를 입력 데이터로 준다. 여기서 Transformer의 단점을 보완해주고자 Positional Encoding이라는 계층을 지나게 된다.

 

Transformer는 RNN의 단점을 해결하고자 나온 모델로, 결론적으로 말하자면 병렬 계산이 가능하다. 따라서 단어들이 순차적으로 들어오지 않고 뭉태기로 들어와도 단어들의 순서를 이해하면서도 병렬적으로 연산이 가능하다. 이것이 가능하게 하는 것을 Positional Encoding 계층이다. 사실 벡터(뭉태기)로 들어오는 단어들에 대한 위치정보는 알 수 없다. 그렇기 때문에 기존에 우리가 RNN을 사용했던 이유는 단어간의 순서와 맥락을 파악하기 위해서였다. 하지만 Transformer는 Positional Encoding 계층을 사용하면서 뭉태기(벡터)의 단어 데이터들에 상대적인 위치 데이터를 제공하며 병렬연산을 가능하게 한다.

 

출처 : https://jalammar.github.io/illustrated-transformer/

 

사실 이 부분에 대해서 수학적인 부분은 명확히 이해를 하지 못했기 때문에(ㅎ) 대충 느낌적으로만 설명하면 결국에 sin, cos인 정현파는 -1~1사이의 값을 갖고 서로 겹치지 않기 때문에, 이것을 홀수 짝수로 나누어 연산을 하고 기존의 Embedding과 단순히 합산을 하면 위의 이미지처럼 서로 겹치지 않는, 상대적인 위치 정보를 가진 최종적인 데이터를 만들 수 있게 되고 이것이 Transformer의 Input으로 주어지게 된다. Positional Embedding에 대해 수식적인 이해를 필요로 한다면 여기를 참고하길 바란다.

 

결론적으로 Input 이전의 과정들은 문자를 숫자로(Embedding) 변경한 뒤, 상대적인 위치 정보를 주입(Positional Encoding)시킨다.

 

 

 


 

 

 

Transformer의 Encoder와 Decoder는 세부 계층으로 Multi-Head Attention과 Feed Forward 구조를 가진 상당히 유사한 모습을 갖고 있다. 따라서 나는 (Masked) Multi-Head Attention에 대해 그리고 그 세부를 구성하는 Scaled Dot-Product Attention에 대해 설명하는 구조로 설명하도록 하겠다.

 

 

 

Scaled Dot-Product Attention (Self-Attention)

 

Scaled Dot-Product Attention의 구조는 위와 같다. Q,K를 행렬곱 연산을 한 후, 1/sqrt(dk)로 Scaling을 하고, 선택적으로 Mask를 한 후, Softmax를 거쳐 그 값을 V와 다시 한번 행렬곱 연산을 한다. 이에 대한 내용은 수식적으로는 아래의 이미지와 같다. 수식을 이해하기에 앞서서 왜 우리는 1/sqrt(dk)로 Scaling을 하며, 선택적으로 Mask를 사용하는걸까?

 

1/sqrt(dk)로 Scaling하는 이유는, QK^T 연산을 하게 되면 행렬 크기가 커지게 되면서 벡터가 커지게 된다. 따라서 벡터를 구성하는 숫자의 개수가 여러개가 되기 때문에 Softmax를 적용하면 거의 대부분의 숫자들이 0에 가깝게 된다.(Softmax는 확률을 나타내는 함수이기 때문에 각 행렬의 위치들이 얼만큼의 확률을 나타내는지를 보이기 때문에 행렬이 클수록 모든 데이터들이 0에 가까워질 수 밖에 없다.) 따라서 각 숫자들의 값들의 차이를 극단적으로 나누기 위해  (대부분의 숫자들이 0에 가까운 것을 막기 위해) 1/sqrt(dk)로 Scaling하게 된다.

 

또 선택적으로 Mask를 하는 이유는, Decoder의 초반 Multi-Head Attention이 Masked Multi-Head Attention을 사용하기 때문인데, 그 이유는 결론적으로 우리는 시계열 데이터를 정확히 예측하고자 하기 때문에 전체 정보를 미리 알려주는 것이 아니라 순차적으로 데이터를 제공하며 유추하기를 원하기 때문에 Mask를 사용하여 순서가 되지 않은 데이터의 정보(Attention)를 숨기는 과정을 거친다. 이렇게 Mask를 사용하는 이유는 Input Data가 벡터로 전체 데이터가 한번에 들어가기 때문이다.

 

아무튼 다시 Scaled Dot-Product Attention의 수식을 보면 다음과 같다.

 

 

여기서 Q, K, V가 뭘까? 풀어 말하자면

Q : 영향을 받을 단어

K : 영향을 주는 단어

V : 영향에 대한 가중치

라고 이해하면 되겠다.

 

이 Scaled Dot-Product Attention에 대해서는 유튜브를 참고하는 것이 훨씬 빠른데 내가 공부할 때 큰 도움이 되었던 유튜브들을 몇 개 링크 걸도록 할테니 꼭 참고하길 바란다. 이건 강요다. Transformer구조를 이해하기 위해서는 이 Scaled Dot-Product Attention에 대한 이해가 필수적이나 글로 풀어쓰는데는 한계가 존재하기 때문에 링크를 꼭 참고하길 바란다. 유튜브 유튜브 블로그

 

아무튼 이 Scaled Dot-Product Attention에 대해 아주 간단히 설명하자면, 각각의 단어가 다른 단어들과 얼마나 밀접한 관련이 있는지에 대한 정보까지 모두 담은 구조라고 이해하면 되겠다. 이에 대한 자세한 내용은 위의 유튜브들로 이해하고 블로그로 다시 한번 이해하면 이해가 잘 되리라 믿는다.

 

그리고 실제 Transformer에서 Q, K, V는 모두 동일하다. Decoder 중간에 위치한 Multi-Head Attention을 제외하고는 모두 Q, K, V가 동일하기 때문에 Self-Attention이라고도 불리고, 이러한 이유 때문에 기재한 영상들이 Q,K,V를 동일한 값으로 계속 설명해주는 것이다. Decoder 중간에 위치한 Multi-Head Attention은 영향을 받을 단어인 Q(구조 이미지에서 Output을 의미, 한글로 말하자면 Decoder에 입력되는 단어 벡터를 의미한다.)를 제외하고 Encoder의 Output이 K와 V로 입력된다.

 

Self-Attention을 사용하는 이유는 논문에 기재되어있는데, 결론적으로 연산량이 적고 속도가 빠르다는 장점이 있기 때문에 Self-Attention을 사용한다는 이야기이다. 여기에 대해 더 자세한 내용은 여기여기를 참고하길 바란다.

 

Self-Attention을 사용하는 이유

 

 

 

Multi-Head Attention

 

Multi-Head Attention에 앞서 Scaled Dot-Product Attention을 설명한 것은 Multi-Head Attention의 핵심 구조가 Scaled Dot-Product Attention이었기 때문이다. Multi-Head Attention은 굉장히 간단하다. 입력으로 들어온 V, K, Q를 Linear 계층으로 보낸다. 이 Linear 계층은 Pytorch 기준이고 Keras로는 Dense 계층을 의미한다. 결론적으로 완전연결계층을 의미한다. 완전연결계층이란 가중치와 편향을 연산하는 계층이다. 위의 이미지를 보면 입력 데이터로 단 한개(2X4 Shape)의 데이터가 들어가지만, 여러개의 가중치(위의 이미지에서는 0~7까지 총 8개이다)로 연산을 하면서 데이터가 8개로 쪼개진다. Q0~7, K0~7, V0~7 이런 식으로 말이다. 또한 2X4 Shape과 가중치의 Shape인 4X3이 행렬곱을 하므로 최종적으로 출력되는 데이터의 Shape은 2X3이다. 이것을 Scaled Dot-Product Attention 에 입력하게 되면 연산 과정에 의해 같은 Shape인 2X3이 나오게 되고 이것이 그림에서 나오는 Z0~7이다.

 

이것들을 Concat한 후(Concat을 하게 되면 2X3 Shape인 데이터들이 가로로 붙으면서 2X24(3*8) Shape이 되고 이를 가중치 W(24X4 Shape)와 연산하면 최종적인 출력 Z(2X4)가 나온다.

 

내가 굳이굳이 Shape을 쓰는 이유는 이게 내 2차 면접의 주요 내용이었기 때문인데, 실제로 Transformer 구조에서 매우 중요하다. Transformer는 결론적으로 Input Shape과 Output Shape이 2X4로 동일하다.

 

따라서 Encoder 및 Decoder를 여러개 쌓아도 되기 때문에 효율적으로 코드를 작성할 수 있고 계산할 수 있다.

 

또 사실 여러개의 Head를 사용하지 않아도 같은 연산 결과가 나오는데, 굳이 Multi-Head를 사용한 이유는 컴퓨터는 병렬 연산 최강자이기 때문에 여러개의 병렬 연산을 동시에 할 수 있어 속도면에서 이득을 취할 수 있기 때문에 같은 결과가 나오면서 속도도 빠르게 계산하고자 Multi-Head를 사용하는 것이다.

 

 

 

Feed-Forward Network

FFN 구조

 

Feed-Forward Network 구조는 별거 없다. 다시 한번 완전 연결 계층을 지난 후, ReLU 계층을 지나고 또 완전 연결 계층을 지나는 구조이다.

 

 

 

Add&Norm

Multi-Head Attention 구조 이후, Feed-Forward 구조 이후 Add&Norm 계층은 ResNet과 같이 이전 데이터를 단순 합산(Add)하며 기존의 데이터에 대한 정보를 잃지 않고 Normalization, 정규화를 하는 계층이다.

 

 

 

모델 구현하기

 

 

구글 리서처들이 대거 투입하여 만든 모델이기 때문에 따뜻하게도 구글의 Tensorflow에 Transformer를 구현하는 코드가 올라와 있다. 모두 여기를 참고하여 이론 뿐만 아니라 코드 또한 이해하길 바란다. 위의 이미지는 실제 Q,K,V의 Shape이 어떻게 되는지를 나타낸 이미지이다. 여기서 attention weights란, Scaled Dot-Product Attention에서 softmax(QK^T/sqrt(dk))를 연산한 Shape이라고 이해하면 되겠다. 즉, V와 행렬곱연산을 하기 직전의 Shape이라고 이해하면 되겠다.

 

 

'인공지능 > 논문 리뷰' 카테고리의 다른 글

2. faster R-CNN  (0) 2020.11.07

 

 

이제부터 Multi Speaker Tacotron에 대해 설명하도록 하겠다. 필자인 나는 공부하는 입장이니까 내가 이해하는 한으로 최대한 자세하게 설명하도록 하겠다. 하지만 공부하는 입장이기 때문에 틀리는 부분도 있을 거라는걸 명심해 주길 바란다... RNN은 정말 너무 어렵다 ㅠ_ㅠ...

 

 

Tacotron 구조

 

위의 이미지가 구글의 Tactoron 구조이다. 이미지의 출처는 논문이기 때문에 참고하길 바란다. 참고로 논문 처음의 참여자들의 이름에 * 표시가 있는 분들은 타코를 좋아하고 † 표시가 있는 분들은 초밥을 더 좋아한다고 한다. 타코를 좋아하는 사람들이 더 많아서 타코트론이 되었다는 멋진 녀석.... 공대생들의 찐광기를 느낄 수 있는 부분

 

Tactron 구조 세부적으로 보기

 

 

 


 

 

 

Encoder

Tacotron Encoder

 

위의 이미지가 타코트론의 Encoder의 세부적인 내용이다. 우선 첫번째로 Character embeddings를 보도록 하겠다.

 

Character embeddings

사실 Character embeddings에 대해 아주 완벽하게 이해를 하지는 못했다. 내가 책으로 공부하기로는 단어의 one-hot encodding과 가중치의 matmul 연산의 불필요함을 줄이기 위해 한번에 단어 ID로 단어의 분산표현을 만들어내는 것이 Embedding이라고 이해했는데 Tacotron의 논문에서는 입력 인코더는 각 문자가 원-핫 벡터로 표현되고 연속 벡터에 포함되는 문자 시퀀스라고 설명되어 있어서 나의 지식과 혼동되고 있다.(ㅠㅠ) 뭐 아무튼 이래나 저래나 Character embeddings의 핵심은 단어의 분산표현을 나타낸다는 것이고, 결론적으로 이것을 쉽게 말하자면 단어를 숫자 데이터로 변환해준다는 뜻이다.

 

 

Pre-net

pre-net 세부 구조

 

Pre-net은 별거 없어 보인다. Fully Connected layer - ReLU - Dropout을 2번 반복하는 구조이다. 사실 처음 타코트론을 공부할 때 이 Pre-net은 단순히 오버피팅을 억제하는 정도로만 이해했었다. 근데 논문을 자세히 살펴보니 이 pre-net의 Dropout이 상당히 중요한 역할을 한다.

 

Pre-net의 Dropout은 크게 2가지 역할을 하는데 우선 첫번째로 일반화를 해준다는 점에서 매우 중요하다. 일반화란, 학습 데이터와 Input data가 달라져도 출력에 대한 성능 차이가 나지 않도록 하는 것을 의미한다. 즉, training data로 나오는 학습 결과만큼 새로운 입력 데이터에 대해서도 좋은 결과가 나올 수 있도록 돕는 역할이라는 것이다. 뭐, 한마디로 그냥 오버피팅을 억제한다고 생각해도 되겠다.

 

Pre-net의 Dropout은 bottleneck layer, 즉 병목 layer라는 점에서 중요하다. 병목 layer라고 하면 마치 이 계층이 병목현상을 유발한다는 것처럼 읽히지만 사실 이 계층은 병목 현상을 방지한다고 보면 되겠다. Dropout의 구조는 여기의 이미지를 참고하면 되는데, 쉽게 말하자면 모든 신경망을 사용하지 않고 일부만을 사용하여 학습을 진행하고 이 과정을 여러번 반복해 평균을 내 모든 신경망을 사용한것과 비슷한 효과를 내면서 overfitting, 즉 과적합을 방지한다. 이런 과정을 거치면, 여기서 설명하는 것과 같이 학습에 필요한 계산 비용이 크게 줄어들게 된다.

 

 

CBHG

크게 보면 CNN과 RNN으로 구성된 신경망이다.
CBHG 세부 구조

 

CBHG란 convolutional 1-D filters, bank, highway networks, gated recurrent unit bidirectional의 첫글자를 따서 지어진 이름이다. CBHG는 크게 보자면 CNN과 RNN으로 구성된 신경망으로, 층이 깊어질수록 복잡하고 추상화된 특징을 추출할 수 있는 CNN의 장점과 시계열 데이터의 전체적인 특징을 파악할 수 있는 RNN의 장점을 모두 합친 모델이다.

 

CNN 모델을 자세히 살펴보자면 Convolution, Max pooling, Convolution 계층을 지나면서 데이터 특징을 잡을 준비를 한다. (혹은 이미 데이터의 특징을 거의 잡아놨다.) 이 과정에서 바로 Highway Layers로 넘어가지 않고 Residual Connection을 하는데, 이는 ResNet을 사용하는 이유와 같은 맥락이라고 보면 된다. 기존의 데이터에 대한 정보를 잃지 않기 위해 우리는 단순 합산을 통해 학습된 데이터와 기존의 데이터의 모든 정보를 갖고 Highway Layers를 통해 특징만을 추출해 낸다.

 

그 후, Bidirectional RNN으로 데이터를 보내 전체에 대한 흐름의 특징을 파악한다. 여기서 Bidirectional은 양방향이라는 뜻으로, Bidrectional RNN을 사용하는 이유는 시계열 데이터는 순방향 못지 않게 역방향으로도 맥락의 흐름을 유추할 수 있기 때문이다. 따라서 Bidrectional RNN을 사용하여 우리는 과거 시점에서도 미래 시점에 대한 데이터를 받고, 미래 시점에서 과거 시점에 대한 데이터를 받아 맥락의 전체적인 흐름에 대해 파악한다.

 

 

 

 

Attention 

어텐션에 대한 자세한 내용은 링크동영상, PPT p.121 부터를 참고하길 바란다. 여기서 간단히 핵심만 다시 언급하자면 Attention이란 시계열 데이터에서 어느 부분에 집중할 것인가에 대해 학습하는 것이며, Attention을 사용하면 '일반화'가 가능하다. 즉, 새로운 데이터가 입력되어도 충분히 좋은 결과를 나타낼 수 있도록 도와준다.

 

 

 

 

Decoder

Tacotron Decoder

 

Decoder의 아래에 입력 데이터인 <GO> frame은 Decoder, 즉 시계열 데이터의 시작을 알리는 데이터로 큰 의미는 없다. (하지만 반드시 필요) 우리는 이 <GO> frame의 데이터와 Encoder에서 학습된, 문장의 특징을 잘 갖고 있는 단어 임베딩들을 (Encoder CBHG의 맨위쪽, 초록색 Embeddings) Attention 계층에서 학습시키고 (특징을 또한번 잡아내고) 일반 RNN을 사용하여 n개의 스펙토그램으로 출력한다. 이 Spectrogram은 음성 신호로 변환되기 직전의 숫자 데이터로, 발음, 음성에 대한 정보를 담고 있다. 즉, 결론적으로 Encoder에 들어온 단어 데이터들을 Decoder의 Attention과 RNN을 통해 음성 신호로 변환될 수 있는 숫자 데이터로 바꿔준다고 이해하면 되겠다. 이에 대한 자세한 설명은 PPT p.103부터 참고하길 바란다.

 

이렇게 스펙트로그램 데이터를 만들면 CBHG를 통해 또한번 특징을 잡은 후 하나의 시계열 데이터로 출력한다. 이 데이터를 스펙트로그램을 음성 데이터로 변환해주는 Griffin-Lim을 통해 음성 데이터로 출력한다.

 

 

 

 

 

 

 

위의 구조가 Tacotron의 구조이다. 정말... 정말 복잡하다... 사실 이해하고 보면 그렇게 어렵지는 않은데 다양한 개념들이 섞여서 헷갈린다. 하지만 그냥 엄청엄청 쉽게 이해를 하자면 악착같이 시계열 데이터들에 대해 특징을 잡아내고 일반화를 하기 위해 노력하는 짓을 n번 반복하여 결과물을 만들어내는 악착같은 모델이라고 이해하면 되겠다.

 

 

 

 


 

 

 

 

Multi Spekaer Tacotron - Speaker Embedding

여기서 끝이 아니다. 우리는 Multi Speaker Tacotron을 사용하기 때문에 Multi Speaker에 대해서도 이해해야한다. 사실 이 부분에 대해서는 완벽하게 이해를 아직 하지 못했기 때문에 대략적으로 설명하고 넘어가도록 하겠다. (큐ㅠ)

 

Multi Speaker Tacotron은 Baidu에서 발표한 Deep Voice2에 기재된 내용으로, 쉽게 말하자면 여러명의 발화자에 대해 적은 메모리 사용량으로도 효과적으로 학습할 수 있다는 내용이다. 이에 대한 자세한 설명은 PPT의 p.159부터 참고하길 바란다.

 

간략하게 설명하자면 N명의 발화자(Speaker) 정보를 가진 Speaker Embedding을 만들어 Encoder CBHG의 CNN부분(정확히는 residual connection)과 RNN부분에 삽입한다. 그리고 Decoder Pre-net과 RNN에 삽입하여 적은 메모리 사용량으로 효과적으로 여러명의 음성 특징을 학습할 수 있게 한다.

 

Multi Speaker Tacotron을 사용하면 결론적으로 잘 학습된 Attention이 잘 학습되지 않은 Attention의 학습에 도움을 주어 적은 양의 데이터로도 충분히 좋은 효과를 볼 수 있다. 필자가 이해하기로는 전이학습과는 다르지만, 결론적으로 학습이 잘된 Attention이 학습이 안된 Attention의 학습에 도움을 준다는 것이 전이학습과 비슷한 '결'이지 않을까 싶다. 이 부분에 대해서는 아직 정확하게 알지 못하기 때문에 추가적으로 기재하도록 하겠다.

 

아무튼 Speaker Embedding을 사용하여 여러 화자에 대한 Attention을 학습하면 내가 원하는 특징(예를 들자면 발화 속도, 억양과 같은)만을 추출하여 다른 화자에게 대입할 수 있다. 이 부분에 대해서도 PPT p.185부터 참고하길 바란다.

 

 

 

 

 


 

 

 

 

설명이 부족하거나 이해가 가지 않는 부분에 대해서는 우리가 참고한 github의 주인인 carpedm20님의 PPT동영상을 참고하길 바란다. (이미 너무 남발하긴 했지만ㅋㅋㅋㅋ) 큰 틀에서 이해하기엔 동영상이 최고다... 흑흑 이제 드디어 끝났다.. 타코트론아 많은 깨달음을 줘서 고맙지만,,, 참,, 힘들었다,,,,★

 

 

 

 

 

 

내가 딥러닝을 제대로 이해하기 시작한게 사실상 올해부터였다. 인공지능을 공부했던건 작년부터였지만 그때는 머신러닝을 이해하는 것도 벅찼고 CNN은 더 벅찼으면 RNN은 사실상 포기였다. 하지만 취업이 바로 안되고(ㅠㅠ) 할 것도 없기에 애매하게 아는 것보단 완벽하게 이해하는게 낫겠다 싶어서 국비 지원으로 인공지능을 다시 배웠다. 6개월 과정에서 나는 SQL, LINUX, HADOOP, R 등 엄청 다양한걸 많이 배웠는데 다 이게 피가되고 살이 되지 않겠나 싶다.

 

암튼 이렇게 구구절절하게 글을 쓰는 이유는 최종 팀프로젝트가 RNN 기반이기 때문이다. 이번에는 책까지 구매해가며 먼저 책을 읽고 수업을 듣고 스터디까지 해서 CNN은 잘 이해했는데 RNN은 그래도 너무 어려운기라! 근데 2번이나 각잡고 배웠는데ㅠㅠ; 이걸 또 포기하기엔 내 자존심이 용납이 안되서 그냥 팀원들한테 욕심으로 RNN과 관련된 프로젝트를 하자고 했고, 다들 OK 해준 덕분에 이 프로젝트를 진행할 수 있었다.

 

나는 일단 일을 벌려야 한다. 욕심이 있으니까 벌려놓으면 그걸 잘하려고 열심히 하기 때문이다. 결과적으로 RNN과 관련된 프로젝트로 일을 벌린건 잘한 일이었다. 사실 지금도 정확히 RNN을 이해했다고 볼 수는 없겠지만 이 프로젝트를 하겠다고 RNN을 다시 공부하고 또 블로그에 글을 정리해가고 팀원들에게 설명을 해주면서 대충 그 흐름은 파악한 것 같다. 그리고 무엇보다 팀프로젝트 결과가 좋다. 넘 행복하다!!!!

 

 

 

 


 

 

 

 

사실 아이디어의 시작은 아주 간단했었다. 거창한 이유로 TTS를 하고 싶었던건 아니고, 매일 9시부터 6시까지 학원에 나가 공부를 했었는데 코로나가 심각해지면서 비대면 수업으로 전환되면서 ZOOM으로 수업을 하게 됬는데 선생님 목소리 데이터가 너무 깨끗한거다! 정말 음질이 너무너무 깨끗했다. 그리고 개인적으로 선생님 목소리도 좋으셔서 음~ 이거 뭔가 데이터가 쓸만할 것 같은걸...? 이라는 생각이 들었었다.

 

그러다 팀 아이디어 회의에서 RNN과 관련된 프로젝트를 하고 싶다는 내 말에 다들 하나 둘씩 아이디어를 냈는데, 선생님의 목소리로 TTS를 만들어보자는 의견이 나왔다. 처음엔 다들 간단하다고 생각했지만 이걸 구현할 수 있는가는 다른 얘기인건 수많은 공대생들은 다 뼈저린 경험으로 알고 있을 것이다. 나는 그 공대생 중에 하나였고, 이걸 과연 우리 수준에서 구현할 수 있는지에 대해 찾아보기 시작했다.

 

그러다 이 동영상을 보게 되었다.

딥러닝을 이용한 아이유 음성 TTS PoC

 

그리고 더보기에 올라온 블로그를 참고하기 시작했다. 이 분은 심지어 라디오 데이터를 사용했는데도 이렇게 잘 나왔는데, 나라고 안될건 없었다. 심지어 데이터 양도 그렇게 많지 않았음에도 충분히 좋은 결과가 나왔었다.

이건.. 이건 할만하다...!!!

 

그렇게 이 프로젝트에서 가장 소중하고 감사한 carpedm20님깃허브를 참고할 수 있게 되었다. 사실 나는 그 전까지만 해도 깃허브를 알기만 했지 도대체 어떻게 쓸 수 있는지를 이해하지 못했는데 이 프로젝트 덕에 깃허브까지 이해를 했다. ㅠㅠ 정말 소중한 프로젝트인걸...?

 

그래서 열심히 전처리하고 데이터 수집하고,,, 했다. 데이터는 준비 됐다. 양질의 4+시간의 데이터를 수집했고 그 과정에서 아주 간단한 파이썬 코드도 구현했다. 엄청 간단하지만 나름 코드 짠 내가 자랑스러웠다ㅋㅋㅋㅋㅋㅋㅋ 그래서 이제 깃허브를 참고해서 학습하기만 하면 됐다! 그랬다!!!!!! 근데 이게 진~짜 오류가 엄청 났다... 엄청난 양의... 모듈들을 다운 받아야했지만... 그게 왜이렇게 오류들이 나는지.. 솔직히 나는 그 빨간 글자들을 보면서 하기 싫었는데 다행히 팀원분 중에 한 분이 엄청엄청 열심히 오류 수정하면서 환경 구성을 해주셔서 아주 잘~! GPU 환경에서 잘 돌아갈 수 있게 되었다.

 

우리가 사용한 CUDA version은 8.0이고 cudnn은 6.0을 사용하였다.

 

암튼 이 주저리 Preview 글에서는 내가 활용했던.. 너무 간단해서 창피하기까지한 파이썬 코드를 같이 첨부하도록 하겠다.

 

전처리과정.ipynb
0.01MB

 

이 코드는 정말 간단하게 총 데이터양이 몇시간인지를 판단해주는 함수 하나랑 csv 파일을 json으로 바꿔주기 위한 전처리 코드들이랑 무음 기준으로 알아서 효과적으로 긴 시간의 음성 데이터를 라벨링하기 쉽게 짤라주는 코드 하나가 있다.

 

손석희 데이터처럼 구글 API를 사용하고 싶었는데, 선생님은 대본 없이 그냥 말하시다보니 구글 API의 불안정함을 잡아줄 수 있는 부분이 없어서 이건 안타깝게도 그냥 다 사람이 했다... 원래 사람이 최고다... 사람은... 갈린만큼 좋은 결과물을 내놓지...

 

그리고 프로젝트 이름이 DJ You인 이유는, 음성 합성에 사용했던 선생님의 성이 유씨인것도 있지만 사람의 음성만 있으면 그 사람의 특징을 살려내면서 음성합성이 가능한 모델이기 때문에 선생님(Yu)은 물론, 당신(You)도 DJ가 될 수 있다는 의미에서 DJ You로 만들었다.

 

암튼! 그렇다는 이야기다. 지금까지의 얘기가 이 프로젝트를 하게 된 이유, 전처리에 대한 주저리 정도라면 앞으로는 실제 사용한 모델인 Multi Speaker Tacotron에 대해 설명하도록 하겠다.

 

 

 

 

 

 

어텐션(Attention)은 seq2seq의 문제점을 개선하기 위해 나온 해결책이다.

 

 

seq2seq의 문제점

seq2seq는 Encoder가 시계열 데이터를 인코딩하고, Encoder의 출력은 h(은닉 벡터)이며 h는 고정 길이의 벡터였다. 하지만 데이터가 모두 항상 동일한 길이일수도 없는 노릇이고 이것을 매번 고정 길이의 벡터로 출력하는 것은 데이터의 손실 및 공간 낭비의 문제가 발생하게 된다.

 

문장이 길어도 고정 길이 벡터로 출력된다.

 

 

 

 

Encoder 개선

이전에 설명한 seq2seq에서 우리는 RNN(LSTM)의 마지막 은닉 상태(h)만을 Decoder에 전달했다. 하지만 위의 문제점을 해결하기 위해서는 Encoder의 출력은 고정 길이 벡터가 아닌, 문장 길이에 따라 바꿔주는 것이 좋다. 따라서 우리는 이 문제점을 해결하고자 시각별 RNN(LSTM) 계층의 은닉 상태 벡터를 모두 이용한다.

 

모든 시각의 은닉 상태 벡터를 hs라고 한다.

 

위의 이미지처럼 각 시각(단어)의 은닉 상태 벡터를 모두 이용하면 입력된 단어와 같은 수의 벡터를 얻을 수 있다. 이는 코드로는 RNN 계층의 초기화 인수로 return_sequences=True로 설정하면 모든 시각의 은닉 상태 벡터(hs)를 반환하게 된다. 단순히 모든 시각의 은닉 상태 벡터를 꺼내는 것만으로, 우리는 입력 문장 길이에 비례한 정보를 인코딩 할 수 있게 되었다.

 

 

 

 

Decoder 개선 - Attention 계층 사용

개선된 Encoder에서 보내는 hs를 활용하기 위해서는 Decoder 또한 개선해야 한다. 기존의 Decoder는 기존의 Encoder가 마지막 은닉 상태 벡터만을 Decoder로 넘겼기 때문에, hs 전체를 활용할 수 있도록 개선해야 한다. 그렇다면 Decoder는 어떻게 hs 전체를 활용할 수 있을까?

 

우리는 기존에 한개만 받던 h를 뭉태기(hs)로 받게되었다. 이 말은 즉슨, 문장 전체에 대한 정보를 입력받을 수 있다는 소리다. 이 덕에, 우리는 입력과 출력의 여러 단어 중 어떤 단어끼리 서로 관련되어 있는가에 대한 대응 관계를 학습할 수 있게 되었다. 이러한 구조를 어텐션(Attention)이라고 하며, 어텐션은 필요한 정보에만 주목하여 그 정보로부터 시계열 변환을 수행하도록 한다.

 

 

위의 그림은 어텐션이 사용된 개선된 Decoder이다. 여기서 어텐션 계층의 입력 데이터는 Encoder로부터 받는 hs와 시각별 LSTM 계층의 은닉상태 벡터(h)이다. 어텐션 계층에서의 계산을 통해 필요한(중요한) 정보만이 Affine 계층으로 출력된다.

 

어텐션의 기본 아이디어는 Decoder에서 출력 단어를 예측하는 매 시각마다, Encoder에서의 전체 입력 문장을 다시 한 번 참고한다는 것이다. 여기서 어텐션은 전체 입력 문장을 전부 다 동일한 비율로 참고하는 것이 아니라, 해당 시점에서 예측해야할 단어와 연관이 있는 입력 단어 부분을 좀 더 집중(attention)해서 보게 된다.

 

어텐션 계층의 대략적인 개념을 설명했으니, 그래서 어텐션 계층이 어떻게 동작하는지 살펴보도록 하자. 우리는 어텐션 계층이 필요한 정보만을 추출해낸다고 이해했다. 하지만 어텐션 계층도 결국에는 학습을 통해 갱신되는 계층이다. 학습을 통해 갱신됨은 역전파를 활용하여 매개변수값을 조정해 나가는 것이고 이것은 미분을 의미한다. 미분에는 '선택'이라는 개념은 없다. 그렇다면 우리는 어떤 계산을 해야하는걸까?

 

 

 

 


 

 

 

 

 

Attention 계층의 세부 연산을 보여주는 이미지

 

위의 이미지를 보면 Attention 계층은 크게 2가지의 중요 연산으로 나눠 볼 수 있다. 여기서 입력 데이터인 hs는 Enocoder에서 입력되는 모든 은닉 상태의 데이터이며, h는 hs를 활용하여(정확히는 hs 벡터의 마지막 줄) LSTM 계층 연산을 통해 출력된 은닉 상태 벡터(h)이다. Attention Weight은 Encoder가 출력하는 각 단어의 벡터 hs에 주목하여 해당 단어의 가중치 a를 구하고, Weight Sum은 a와 hs의 가중합을 구해 맥락 벡터 c를 출력한다.

 

 

 

Attention Weight

단어의 가중치(기여도)를 나타내는 벡터인 a는 어떻게 구하는걸까?

 

Decoder의 LSTM 계층의 은닉 상태 벡터는 h이며, 우리는 이 h가 Encoder의 입력 데이터인 hs와 얼마나 비슷한가를 수치로 나타내고자 한다. 이를 위해서 우리는 벡터의 내적을 이용한다. 벡터의 내적은 두 벡터가 얼마나 같은 방향을 향하고 있는가를 의미하며, 이는 벡터간의 유사도를 표현하는 척도로 사용될 수 있다.

 

 

위의 이미지처럼 h와 hs의 내적으로 각 단어 벡터의 유사도를 구한 결과가 s이다. 이 s는 정규화 하기 이전의 값으로, 점수라고도 한다. 이 s를 정규화하기 위해 softmax함수를 적용시켜 나온 결과가 바로 우리가 원하는 가중치 a이다.

 

 

 

 

Weight Sum

Weight Sum 계층은 (Attention 계층 안에서도 크게 2가지로 나뉘기 때문에 계층이라고 부르겠다) 모든 은닉 상태 벡터(hs)와 가중치를 나타내는 행렬(a)이 연산(행렬곱)하여 그 결과를 합해 맥락 벡터(c)를 얻어낸다.

 

 

이렇게 어텐션은 두 시계열 데이터 사이의 대응 관계(얼라인먼트:Alignment)를 학습하게 되며, 중요한 정보를 집중적으로 파악할 수 있다. 어텐션에 대해 더 자세히 이해하고 싶다면 이 블로그를 참고하길 바란다.

 

 

 

+ Recent posts