[딥러닝 모델] 트랜스포머 (Transformer)

박나연·2022년 5월 14일
2

https://wikidocs.net/31379

트랜스포머

트랜스포머는 RNN을 사용하지 않지만, 기존 seq2seq 처럼 인코더에서 입력시퀀스를 입력받고, 디코더에서 출력시퀀스를 출력하는 인코더-디코더구조를 가진다. 이전에는 하나의 RNN인 t개의 시점을 가지는 구조였는데, 이번에는 인코더와 디코더 단위가 N개로 구성되는 구조이다.

위 그림은 인코더와 디코더가 6개씩 존재하는 트랜스포머의 구조이다. 동일한 인코더 레이어와 디코너 레이어가 N번 반복되어 stack 되는 것이다.

디코더는 기존 seq2seq 구조처럼 시작 심볼 < sos > 을 입력으로 받아서 종료 심볼 < eos >가 나올 때 까지 연산을 진행한다. 그리고 그 마지막 인코더레이어의 출력을 디코더에 보내게 된다. 단어들이 순차적으로 처리되는 것이 아닌 하나의 레이어에 병렬로 들어간다.

포지셔널 인코딩(Positional Encoding)

트랜스포머에서는 단어입력을 순차적으로 받는 방식이 아니기 때문에 위치정보를 다른 방식으로 알려줄 필요가 있다. 이때 각 단어의 임베딩 벡터에 위치정보들을 더해 모델의 입력으로 사용하게 되고, 이를 포지셔널 인코딩이라고 한다.

위 그림에서 알수 있듯, 입력으로 사용되는 임베딩 벡터들이 트랜스포머의 입력으로 사용되기 전에 포지셔널 인코딩값이 더해진다.

위 그림처럼 각 단어들의 위치가 반영된 포지셔널 인코딩값이 더해지는 것이다.

트랜스 포머는 위치정보를 가진 값을 만들기 위해서 위 함수를 사용하고, 임베딩 벡터와 포지셔널 인코딩의 덧셈은 임베딩 벡터가 모여서 만들어진 문장 벡터행렬포지셔널 인코딩 행렬덧셈연산을 통해 이루어진다.

pos는 입력문장에서 임베딩 벡터 위치를 나타내고, i는 임베딩 벡터내 차원의 인덱스를 의미한다. 임베딩 벡터내 각 차원의 인덱스가 짝수인 경우 (pos,2i)사인 함수 값을, 홀수인 경우 (pos,2i+1) 코사인 함수 값을 사용한다.

어텐션(Attention)

트랜스포머에서 사용되는 세가지의 어텐션이다.

첫번째 그림은 셀프어텐션으로, 인코더에서 이루어지고, 두번째 그림의 셀프어텐션과 세번째 그림의 인코더-디코더 어텐션은 디코더에서 이루어진다.

인코더 (Encoder)

트랜스포머는 하이퍼파라미터인 num_layers개수의 인코더 층을 쌓는다. 인코더를 하나의 층이라는 개념으로 생각하면 하나의 인코더 층은 크게 두개의 서브층으로 나뉘고, 이것이 셀프어텐션과 피드 포워드 신경망이다.

인코더의 셀프 어텐션

이전에 정리했던 어텐션은 주어진 Query에 대해 모든 Key와의 유사도를 구하고 유사도의 가중치를 각각의 Value에 반영, 이것을 가중합하는 방식이었다. 셀프 어텐션은 이 어텐션을 자기 자신에게 수행한다는 의미인데,

Q: 입력 문장의 모든 단어 벡터들
K: 입력 문장의 모든 단어 벡터들
V: 입력 문장의 모든 단어 벡터들

셀프 어텐션은 Q,K,V가 모두 동일하다.

셀프어텐션은, 앞에 문장에서 표현한 단어를 뒤에 문장에서 단순히 대명사인 This로 표현했다면, 이를 입력 문장내의 단어들끼리 유사도를 구해주기 때문에 연관성을 찾기 쉬워진다는 장점이 있다.

셀프어텐션은 각 단어 벡터들로부터 Q,K,V벡터를 얻는 작업을 거친다. 이때 Q, K, V 벡터들은 초기 입력인 d model의 차원을 가지는 단어 벡터들보다 더 작은 차원을 가지게 되고, 이 작은 차원은 하이퍼파라미터인 num_heads로 인해 결정되는데, d model을 num_heads로 나눈 값을 각 Q,K,V의 차원으로 결정한다.

위 그림은 student라는 단어 벡터를 Q,K,V벡터로 변환하는 과정이다.

스케일드 닷-프로덕트 어텐션(Scaled dot-product Attention)

Q, K, V벡터를 얻은 이후에는 기존 어텐션 메커니즘과 동일하다. 각 Q벡터는 모든 K벡터에 대해 어텐션 스코어를 구하고 어텐션 분포를 구한뒤에 이를 V벡터에 가중합하여 어텐션 값을 구하게 된다. 그리고 이 과정을 모든 Q벡터에 대해 반복한다.

어텐션 함수의 종류는 다양하고, 이 중 내적만 사용하는 어텐션 함수가 아닌, 여기에 특정값으로 나눠준 어텐션 함수인
을 사용하는 스케일드 닷-프로덕트 어텐션을 정리해보고자 한다.

위 그림은 단어 I에 대한 Q벡터가 모든 K벡터에 대해 어텐션 스코어를 구하는 것을 보여준다. I, am, a, student 각 단어와 얼마나 연관되어 있는지를 어텐션 스코어가 나타내고 있고, 두 벡터의 내적값을 스케일링하는 값으로 K벡터의 차원을 나타내는 dk에 루트를 씌운 값을 사용한다.

이제 어텐션 스코어에 소프트맥스 함수를 사용해서 어텐션 분포(Attention Distridution)를 구하고, 각 V벡터와 가중합하여 어텐션 값을 구하게 된다. 이것을 단어 I에 대한 어텐션값(context vector)이라고 한다.


0518 추가

멀티 헤드 어텐션 (Multi-head Attention)

한번의 어텐션을 하는 것보다 여러번의 어텐션을 병렬로 사용하는 것이 더 효과적이라고 판단하여, num_heads의 차원을 가지는 Q, K, V에 대해 num_heads개의 병렬 어텐션을 수행한다. 각 어텐션값 행렬을 어텐션 헤드라고 부르고, 이때 가중치 행렬들의 값은 8개의 어텐션 헤드마다 전부 다르다.

병렬 어텐션을 다 수행했다면 모든 어텐션 헤드를 연결해준다.

어텐션 헤드를 모두 연결한 행렬은 또 다른 가중치 행렬 W0을 곱하게 되는데, 이 후 최종결과가 멀티-헤드 어텐션의 최종 결과물이 된다.

포지션-와이즈 피드 포워드 신경망(Position-wise FFNN)

포지션-와이즈 FFNN은 인코더와 디코더에서 공통적으로 가지는 서브층이다. 포지션-와이즈 FFNN은 Fully - connected FFNN이라고 해석할 수 있다.

잔차 연결(Residual connection)과 층 정규화(Layer Normalization)

트랜스포머에서는 이러한 두개의 서브층을 가진 인코더에 추가적으로 Add&Norm 기법을 사용한다.

잔차연결

잔차연결은 서브층의 입력과 출력을 더하는 것으로, 모델의 학습을 돕기 위한 기법이다.

층 정규화 (Layer Normalization)

층 정규화는 텐서의 마지막 차원에 대해 평균과 분산을 구하고, 이를 가지고 특정수식을 통해 값을 정규화하여 학습을 돕는다.

인코더에서 디코더로

지금까지는 인코더를 살펴보았고, 이제 디코더 연산이 시작되어 디코더 또한 총 num_layers 만큼의 연산을 하게 된다. 이때 마다 인코더가 보낸 출력을 각 디코더 층 연산에 사용한다.

디코더의 첫번째 서브층 : 셀프 어텐션과 룩-어헤드 어텐션

RNN 계열의 신경망은 입력단어를 매 시점마다 순차적으로 받으므로 다음 단어 예측에 현재 시점 이전에 입력된 단어들만 참고할 수 있다. 그러나 트랜스포머는 문장단위로 입력을 한번에 받기 때문에 현재 시점보다 미래에 있는 단어들을 참고하지 못하도록 룩-어헤드 마스크를 도입했다.

룩-어헤드 마스크는 디코더의 첫번째 서브층에서 이루어진다.

위 그림처럼 우선 셀프어텐션을 통해 어텐션 스코어 행렬을 얻는다.

그리고 자기 자신보다 미래의 단어들을 제외하여 마스킹한다.

디코더의 두번째 서브층 : 인코더-디코더 어텐션

디코더의 두번째 서브층을 살펴보면, 멀티헤드 어텐션을 수행한다는 점에서 이전의 어텐션들과 같지만 셀프 어텐션은 아니다.

인코더의 첫번째 서브층 : Query = Key = Value
디코더의 첫번째 서브층 : Query = Key = Value
디코더의 두번째 서브층 : Query : 디코더 행렬 / Key = Value : 인코더 행렬

profile
Data Science / Computer Vision

0개의 댓글