Transformer
는 자연어 처리에서 주로 사용하는 딥러닝 아키텍처 중 하나다.
기존 RNN 기반 모델들은 long-term dependency
가 있기 때문에, 입력 문장이 길어지면 앞의 과거 정보가 마지막 시점까지 전달되지 못하는 현상이 발생한다.Transformer
는 self-attention
이라는 특수한 형태의 attention을 사용해 효과적으로 RNN의 한계점을 극복하였다.
Transforemr의 구조
트랜스포머의 전체 구조는 위와 같다. 차근차근 알아 보도록 하자.
우선 트랜스포머는 인코더-디코더
로 구성된 모델이다.
그림에서 input이 들어가는 박스가 인코더이고 인코더 오른쪽에 있는 박스가 디코더 이다. 인코더와 디코더가 어떻게 작동하는지 이해해보자 !
트랜스포머의 인코더 이해하기
트랜스포머는 N개의 인코더가 쌓인 형태이다. 인코더1의 결과값은 그 다음 인코더의 입력값으로 들어가게 된다.
가장 마지막에 있는 인코더의 결과값이 입력값의 최종 출력 값으로 해당 값은 디코더에서 활용 된다.
Attention is all you need
논문에서는 N = 6으로 되어 있다. 이는 인코더를 6개 누적해서 쌓아 올린 형태를 표현한 것이다.
인코더의 구성요소
인코더의 구조를 살펴보면 두 가지 요소로 구성되어 있다.
- multi head attention
- feedforward network
- Add & norm
1. multi head attention
multi head attention
의 역할을 간단히 요약하면 입력 값들이 서로에게 얼마나 영향을 끼치는지 계산하게 된다. 그렇다면 계산은 어떻게 진행 될까?
transforemr구조에서는 self-attention
을 통해 입력 값들이 서로에게 얼마나 영향을 끼치는지 계산하게 된다.
multi head attention 과정
- self-attention
- h개(head의 개수) self-attention 결과를 결합(concat)
- concat된 결과와 가중치 행렬($W_0$)을 곱하여 출력값 생성
그렇다면 self-attention은 무엇인가?
Self attention 과정
- 입력 데이터를 이용해
query
,key
,value
벡터를 만든다. 이 때 각 vector는 서로 다른 신경망을 통해 구할 수 있다. - query벡터와 key벡터를 행렬곱 해줌
- 2의 결과 값을 $\sqrt{d_k}$ 값으로 나눠준다.(정규화, 여기서 $d_k$는 key 벡터의 dimension)
- 정규화 된 벡터를 softmax 함수에 넣어줌.
- 최종적으로 사용할 값은 4를 통해 구한 값과 value 벡터를 곱한 값을 사용한다.
아래 사진은 self-attention 과정을 요약 한 것이다.
self attention은 입력 문장들의 단어가 각각 얼마나 연관이 있는지 계산하기 위해 사용 된다. 단어들이 얼마나 연관이 있는지 계산한 후 decoder를 거치며 output을 출력할 때 참고하기 위함이다 !
정규화를 하는 이유
$z_i$를 구하는 과정에서 score값을 $\sqrt{d_k}$ 값으로 나눠 주었는데 그 이유는 다음과 같다.
softmax에 들어가는 벡터에서 한 entry가 유별나게 클 수 있다. 이렇게 되면 softmax의 결과값이 그 큰 값에 쏠리는 (very peaked) 문제가 발생한다.
이에 따라 gradient가 vanishing되어 학습이 안될 가능성이 생긴다. 따라서 내적의 결과에 표준편차로 기대되는 값 $\sqrt{d_k}$ 를 나눠주어 normalize를 해준 후 softmax를 통과시킨다.
2. Feedforward network
피드포워드 네트워크는 2개의 전 결합층 dense layer과 ReLU활성화 함수로 구성된다. 크게 어렵거나 중요한 부분이 아니라고 생각 된다. 부연 설명도 따악히 . .
3. add와 norm 요소
인코더에서 중요한 요소중 하나는 바로 add와 norm 부분이다. 이 부분은 서브레이어의 입력과 출력 부분에 연결되어 있다. 아래 그림에서 파란색으로 표시된 부분.
해당 부분을 자세히 보면 다음과 같이 구성된것을 알 수 있다.
- 서브 레이어에서 멀티 헤드 어텐션의 입력값과 출력값을 서로 연결
2. 서브레이어에서 피드포워드의 입력값과 출력값을 서로 연결.
add와 norm 요소는 기본적으로 레이어 정규화와 residual connection이다. 레이어 정규화는 각 레이어 값이 크게 변화하는 것을 방지해 모델을 더 빠르게 학습할 수 있게 합니다.
전체 인코딩 구성 요소
1. 입력값은 입력 임베딩으로 변환한 다음 *positional encoding을 추가하고, 가장 아래에 있는 온키더(인코더 1)에 입력값으로 넣어준다. 2. 인코더 2은 입력값을 받아 multi head attention의 서브레이어에 값을 보내고, 어텐션 행렬을 결괏값으로 출력 3. 어텐션 행렬의 값을 다음 서브레이어인 feedforward 네트워크에 입력한다. 4. 그다음 인코더 1의 출력값을 그 위에 있는 인코더(인코더 2)에 입력값으로 제공 5. 인코더 2에서는 1~4번 내용을 반복. 위 과정을 N번(인코더의 갯수) 만큼 반복하고, 최상위 인코더의 출력값은 디코더에서 사용된다. |
*positional encoding
트랜스포머 네트워크에서는 RNN을 사용하지 않기 때문에 모든 단어들이 병렬적으로 입력 된다. 병렬로 단어를 입력하는 것은 학습 시간을 줄이고 RNN의 long-term dependency를 해결해준다.
하지만 트래스포머에서 단어를 병렬로 입력하면 한 가지 문제가 발생하는데, 바로 단어의 순서 정보가 유지되지 않는다는 것이다. 이것을 해결하기위해 각 단어의 위치 정보를 encoding 해주는 역할을 positional encoding에서 수행하게 된다.
디코더의 구성요소
decoder의 구성요소는 encoder와 상당히 유사 하다. 한 가지 다른점은 Masked Multi-Head Atention
가 추가 된 것이다.
그 외에 작동 방법은 encoder와 똑같으므로 Masked Multi-Head Atention
에 대해서만 알아보자.
Masked Multi-Head Atention
디코더에서는 문장을 입력할 때 처음에는 <sos> 토큰을 입력하고 <eos> 토큰이 생성될 때까지 이전 단게에서 예측한 단어를 추가하는 형태로 입력을 반복한다.
따라서 타깃 문장의 시작 부분에 <sos> 토큰을 추가한 다음 디코더에 입력한다.
위에서 self-attention
은 각 단어의 의미를 이해하기 위해 각 단어와 문장 내 전체 단어를 연결했다.
그런데 디코더에서 문장을 생성할 때 이전 단게에서 생성한 단어만 입력 문장으로 넣는다는 점이 중요하다. (이후 단어에 대해서는 모른다고 가정을 해야한다.)
그래서 이 Masked Multi-Head Atention
을 이용해 이후 단어들을 가려 준다.(masked)
아래 표를 보면 조금 이해하는데 도움이 될 것이다.
Masked Multi-Head Atention
과정은 아래와 같다.
- query 벡터와 key 벡터를 내적
- key 벡터의 차원인 $\sqrt{d_k}$로 나눈다.
- 2번 값에 마스킹을 진행하여 소프트맥스 함수를 적용
- value 벡터와 내적
여기서 마스킹을 진행하게 되면 행렬의 값은 아래와 같이 바뀐다.
전체 디코더 구성요소
1. 먼저 디코더에 대한 입력 문장을 임베딩 행렬로 변환한 다음 positional encoding 정보를 추가하고 디코더( 디코더 1)에 입력한다. 2. 디코더는 입력을 가져와서 마스크된 멀티 헤드 어텐션 레이어에 보내고, 출력으로 어텐션 행렬 M을 반환한다. 3. 어텐션 행렬M, 인코더의 출력값 R을 입력받아 멀티 헤드 어텐션 레이어에 값을 입력하고, 출력으로 새로운 어텐션 행렬 생성. 4. 인코더-디코더 어텐션 레이어에서 출력한 어텐션 행렬을 다음 서브레이어인 피드포워드 네트워크에 입력. 피드포워드 네트워크는 이 입력값을 받아서 디코더의 표현으로 값을 출력 5. 다음으로 디코더 1의 출력값을 다음 디코더(디코더 2)의 입력값으로 사용. 6. 디코더 (디코더 2)는 1~5번 과정을 반복. 디코더의 경우 N개의 디코더를 쌓을 수 있다. 이때 최종 디코더에서 얻은 출력값은 타깃 문장의 표현이 된다.다음으로 타깃 문장의 디코더 표현을 선형 및 softmax 레이어에 입력하고 최종으로 예측된 단어를 얻는다. |
정리
트랜스포머의 인코더 부분을 살펴보면서 multihead attention과 feedforward 네트워크 같은 인코더에서 사용하는 다양한 서브레이어를 살펴보았다.
트랜스포머는 RNN을 사용하지 않고 모든 입력 데이터를 병렬적으로 처리하였다.(시간단축) 또한 positional encoding을 통해 각 단어의 위치정보를 보존하였다.
셀프 어텐션은 단어를 좀 더 잘 이해하기 위해 주어진 문장의 모든 단어와 해당 단어를 연결하는 형태다. 셀프 어텐션을 계산하기 위해 query, key, value 총 3개의 벡터를 사용했다.
디코더는 masked multi-head attention를 통해 현재 step 이후의 정보는 mask 하여 모델 학습시 사용하였다.