[DL Basic] 8강 Transformer

2022. 2. 8. 14:23Naver BoostCamp AI Tech 3기

 Transformer : RNN처럼 재귀적인 구조 없이, 오직 Attention을 이용하여 만들어진 구조이다. 여기서는 Self-Attention이라는 것이 Encoder와 Decoder에 이용이 되고, 핵심이다. Sequential한 데이터를 처리하고 인코딩 하는 것으로, NLP 분야에서 주목을 하였고, 이후에는 Image Detection, Classification 등등 Vision분야 등에도 사용되기 시작했다.

Transformer 중 Self-Attention 부분에 대해 단계적으로 알아보자.

처음에는 단어들에 대해서 임베딩(word embedding)을 해야한다. NLP에서 아주 기초적인 단계이다.

이 word vector들이 Encoder 내의 Self-Attention layer를 거친 후에, Feed Forward Neural Network(Dense layer, 즉 일반적인 신경망 부분)를 거치게 된다. 이렇게 RNN과는 다르게 모든 단어들에 대해 한번에 Encoding을 하고 feature를 얻게 되므로, 문장의 문맥에 따라 각 단어들이 문장에서 가지는 관계를 학습할 수 있게 된다. 아래의 그림은 문장 "The animal didn't cross the street because it was too tired"에서 it이 어떤 단어와 관련이 있는지를 학습하여 보여주는 그림이다. (The animal과 관련이 깊다고 나온다.)

그렇다면, 여기서 계속 언급되는 Attention은 어떤 식으로 진행되는 것일까? 

이와 같이 Queries(Q), Keys(K), Values(V) 벡터들을 계산하여 layer를 진행한다. 여기서 Q, K, V는 Attention에서 나오는 추상적인 개념으로, 다음과 같이 말할 수 있다.

"어텐션 함수는 주어진 쿼리(Query)에 대해서 모든 키(Key)와의 유사도를 각각 구하고, 이 유사도를 가중치로 사용하여서 키와 매핑되어 있는 각각의 값(Value)에 반영해준다. 그리고 유사도가 반영된 값(Value)을 모두 가중합하여 리턴한다." 출처 : https://wikidocs.net/31379

 

1) 트랜스포머(Transformer)

* 이번 챕터는 앞서 설명한 어텐션 메커니즘 챕터에 대한 사전 이해가 필요합니다. 트랜스포머(Transformer)는 2017년 구글이 발표한 논문인

wikidocs.net

입력값 x에 대해서 가중치 행렬 WQ, WK, WV를 행렬곱하여 Q, K, V 벡터를 얻어낸다.

그렇게 벡터들을 얻어내면, Q벡터와 K벡터를 위 그림과 같이 내적하여 각 단어에 대한 Score를 계산한다. 중요한 건, 현재 단어에 대한 Score를 얻을 때, 그 단어의 Q벡터를 사용하고 K벡터는 문장 내의 모든 단어들에 대한 K벡터를 각각 내적하는 것이다.

그 다음에는 차원 수의 루트값으로 Score를 나누어서 Scaling을 해주고(훈련이 용이해진다고 함) Softmax를 취해서 각 단어에 대해 확률을 구한다.

마지막으로, 이렇게 구해진 확률값들을 각각 해당 단어의 V벡터에 곱하고, 곱해진 문장 내의 V벡터들을 전부 합하여(weighted sum) Sum인 z벡터를 구하면 attention 과정이 끝난다.

여기서는 개념 설명을 위해 벡터를 기준으로 진행했지만, 실제 모델에서는 빠른 속도를 위해 이들을 행렬로 처리하게 된다. 위에서 언급한 과정들에 대한 행렬식은 다음과 같다.

설명에 비해 행렬 연산식은 생각보다 깔끔하게 나왔다. 그래서 실제 attention 구현 시에도 그리 복잡하지는 않다. 이 행렬 연산식이 정말 올바른지 체크하기 위해 개인적으로 검증을 해보았다. 그 결과 올바른 연산식이라는 것을 확인하였다.

일반적인 attention은 이러하지만, Multi-headed Attention이라는 것이 있다. 위와 달리 head가 여러 개 있다는 것으로, Q, K, V 벡터가 head 개수만큼 존재한다.

위와 같이 Head를 여러 개 만들고, Feed Forward Neural Network에 통과시킬 때는, z벡터들을 concatenate시켜서 통과시키는 것이다. 그런데 실제 구현에서는 이보다는, 그냥 Q, K, V의 가중치 행렬의 차원을 커다랗게 만든다. 그리고 그 안에서 head 개수만큼 차원 수를 나눠서, 그 각각의 차원이 head에 해당하는 것으로 보고 모델을 만든다. 이렇게 하여도 그림의 결과와는 차이가 없으므로 문제없다.