좋은 기회로 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

+ Recent posts