---
# System prepended metadata

title: 'Transformer: Attention Is ALL You Need'

---

# Transformer: Attention Is ALL You Need
* 2021년 기준으로 최신 고성능 모델들은 transforemr 아키텍처를 기반으로 하고 있습니다.
    * GPT  : Transforemr의 디코더(Decoder)아키텍처를 활용
    * BERT : Transformer의 인코더(Encoder)아키텍처를 활용
    ![](https://i.imgur.com/SdB2Mig.png)

* Seq2Seq 모델들의 한계점
    * Context vector v에 소스문장의 정보를 압축합니다. 
    * 병목(bottleneck)이 발생하여 성능 하락의 원인이 됩니다. 
    * 히든state에 입력되는 값을 차례대로 히든state값을 갱신합니다.
    
[문제상황]
    * 하나의 문맥 벡터가 소스 문장의 모든 정보를 가지고 있어야 하므로 성능이 저하됩니다.

[해결방안]
    * 그렇다면 매번 소스 문장에서의 출력 전부를 입력으로 받으면 어떨까요?
    * 최신 GPU는 많은 메모리와 빠른 병렬 처리를 지원합니다.
    
* Seq2Seq with Attention
    * Seq2Seq 모델에 Attention 메커니즘을 사용합니다.
    * 디코더는 인코더의 모든 출력(Outputs)을 참고합니다.
    * Attention 가중치를 사용해 각 출력이 어떤 입력 정보를 참고했는지 알 수 있습니다.
----
* Transforemr는 RNN이나 CNN을 전혀 사용하지 않습니다.
* 대신 Positional Encoding을 사용합니다.
* Bert와 같은 향상된 네트워크에서도 채택되고 있습니다.
* 인코더(Encoder)와 디코더(Decoder)로 구성됩니다. 
* Attention만 사용합니다.
* ![](https://i.imgur.com/0tmVr94.png)

----

동작원리 : ![](https://i.imgur.com/oxatXe7.png)

1. 먼저 입력된 값을 임베딩을 통해 매트릭스를 생성합니다. 
    * 전통적인 Embedding_dim = 512 설정합니다.(상황에따라 수정이 가능합니다.)
    ![](https://i.imgur.com/AiGo6Xs.png)
2. 이어서 입력된 값의 위치정보를 포함하기 위해 Positional Encoding을 넣습니다. 
    ![](https://i.imgur.com/l1nk3Rw.png)
    
3. 임베딩이 끝난 이후에 Attention을 진행합니다. 
    * 각 단어들이 어떠한 연관성을 가지고 있는지 확인합니다. 즉, 서로 이어져있는 문장들에 대한 연관성을 조사합니다.
    * 성능 향상을 위해 잔여 학습(Residual Learning)을 사용합니다. 
        * 레이어를 거쳐서 단순히 반복적으로 갱신하는 것이 아니라, 특정 레이어를 건너 띄어서 복사가 된 값을 그대로 넣어준다. 그러므로 전체 네트워크는 기존 정보를 입력 받으면서 추가적으로 잔여된 부분만 학습하도록 만드릭 대문에 전박적으로 학습 난이도가 낮고, 그렇게 때문에 초기 모델 속도가 높게되고, 그로 인해 글로벌 옵티마를 찾을 확률이 높아지기 대문에 다양한 네트워크에서 이것을 사용했을때 성능이 좋아지는걸 목격할 수 있다. 

4. Attention과 Normalization과정을 반복합니다. 
    * 입력값이 들어온 이후, Attention을 걸치고 나서 Residual Learning을 거치고나서 Normalization. 그다음에, Feedforwrd Layer을 걸치고 나서, 마찬가지로 Residual Learning 그리고 Normalization 추가해서 결과적으로 하나의 인코더 Layer에서 그 결과값을 뽑아낼 수 있습니다. == 레이어를 중첩해서 사용할 수 있다.
    * 각 레이어는 서로 다른 파라미터를 가집니다.
![](https://i.imgur.com/4l4EROj.png)
 
5. 인코더의 가장 마지막 Layer N에서 나온 값을 디코더에 들어가게 됩니다.
    * 우리가 앞서 Seq2Seq2모델 Attention 메커니즘을 활용했을때와 마찬가지로 디코더 파트에서는 매번 출력할 때 마다, 입력 소스 문장중에서 어떤 단어에게 가장 많은 초점을 두어야 하는지를 알려주기 위함입니다. 
    * 디코더 파트에서도 마찬가지로 여러개의 Layer로 이루어져 있고 마지막 Layer에 나오게된 출력 된 값이 바로 실제로 번역을 수행하는 결과가 됩니다. 
    * Transformer의 기본적인 방식은 인코더에서 마지막 Layer에 출력된 값을 매번 디코더의 Layer에 넣어주는 방식

6. 디코더에서도 마찬가지로, 각각 단어 정보를 받아서 이어서 각 단어의 상대적인 위치를 알려주는 인코딩 값을 추가한 이후에 하나의 디코더 Layer에서는 두개의 Attention을 사용하게 되는데 
    * 첫번째 Attention은 Self-Attention으로, 인코더 파트와 마찬가지로 각 단어들이 어떠한 가중치를 가지고 있는지 구하도록 만들어서 이 출력되는 문장에 대한 전반적인 표현을 학습하도록 만들어주고 
    * 두번재 Attention(인코더 디코더 Attention)은 인코더에대한 정보를 Attention을 할 수 있도록 만듭니다.

7. Transformer에서는 마지막 인코더 레이어의 출력이 모든 디코더 레이어에 입력됩니다. 
    * 인코더 레이어의 갯수와 디코더 레이어의 갯수는 같습니다.
        * n_layer = 6일때 의 예시
    ![](https://i.imgur.com/jzZV0p8.png)

----
* Transformer에서도 인코더와 디코더의 구조를 다릅니다. 
    * 이대 RNN을 사용하지 않으며 인코더와 디코더를 다수 사용한다는 점이 특징입니다.
    * eos가 나올때까지 디코더를 이용합니다.
----
* Multi-Head Attention Layer (인코더와 디코더)
    * 목적 : 물어보는 주체인 쿼리와 Attention을 수행할 단어들이 Key로 들어가 행렬곱(MatMul)을 수행한 뒤 스케일링 하고, 필요에 따라 Masking가지 진행한다. 그 후 SoftMax를 취해 어떠한 단어와 가장 높은 연관성을 가지는지 확률(비율)값을 구한다. 구해진 확률값과 Value값을 곱해 가중치가 적용된 결과적인 Attention Value를 구할 수 있다.
        * Attention을 위한 세 가지 입력 요소
            * Query : 물어보는 주체
            * Key : 물어보는 대상
            * Value 
    ![](https://i.imgur.com/RGLcbdG.png)

    1. Scaled Dot-Product Attention 방법
        * 물어보는 주체(Q)가 들어오고, 각각의 단어들(K)이 들어고 행렬곱(MatMul)을 수행한 뒤에, Scaling을 해주고, 필요하다면 Mask를 씌어주고, SoftMax를 취해서 -> 각각의 Key중에서 어떤 단어와 가장 높은 연관성을 가지는지 구한다. 이렇게 구해진 확률값과 실제로 Value값을 곱해서 -> 가중치가 적용된 결과적인 Attention value를 구한다. 
    
    * Scaled Dot-Product Attention으로 들어온 입력값들은 h개로 구분됩니다. 즉, 입려된 문장에서 서로 다른 Value, Key, Query로 만드는 것입니다. h개 컨셉으로 이루어진 각각의 더욱더 구분된 다양한 특징들을 배운다. 
    * 입력값과 출력값의 dim은 같아야 하므로, 각각의 헤더로 부터 나온 Attention 값들을 concat에서 일자로 붙인뒤에, 마지막에 linear 레이어를 걸쳐서 결과값을 낸다. 
    * 인코더 파트에서 어떤 단어를 참고하면 좋을지 K와 V값을 사용한다.
![](https://i.imgur.com/H0lAgLS.png)

* Multi-Head Attention 수학식 
    * Attention
        * 하나의 Attention은 Query, Key, Value를 받는다.
        * 이 때, Query와 Key를 곱해 각 Query에 대해 각각의 Key에 대한 에너지 값을 구할 수 있다.
        * 해당 에너지 값을 softmax를 통해 확률값으로 나타내어 어떤 Key에 대해 높은 가중치를 가지는지 계산할 수 있다.
        * Scale Factor로 루트dk를 사용한다. 이 때 dk는 각각의 Key dimension이 된다. 이렇게 특정한 스케일로 나눠주는 이유는 softmax 함수가 0 근처에서는 gradient가 높게 형성되지만 값이 들쭉날쭉 조금씩 왼쪽 오른쪽으로 이동하면 기우릭 값이 많이 줄어들기 대문에 gradient vanishing 문제를 피하기 위한 방법으로 이러한 Scale Factor를 이용한다. 
        * 결과적으로 각각의 Query가 각각의 Key에 대해 어떠한 가중치를 가지는 Score값을 구한 뒤에 Value값과 곱해Attention Value를 구한다.
    * head
        * 입력으로 들어오는 각각의 값에 대해 서로 다른 Linear Layer를 거치게 만들어 h개의 서로 다른 Query, Key, Value값을 만들 수 있도록 한다.
        * h개 서로 다른 concept을 네트워크가 구분하여 학습하도록 만들어서 Attention을 수행하기 위한 다양한 Feature들을 학습하도록 만든다.
    * MultiHead
        * 각 head에 대한 출력값을 Concat함수를 통해 일자로 죽 붙이고 마지막으로 Output Matrix와 곱해 결과적인 Multi-Head Attention 값을 구한다.
    * 매번 입력값이 들어왔을 때 Query, Key, value로 각각 들어가게 되고, 나올 때는 입력으로 들어왔던 차원과 동일한 차원을 가지기 때문에 이러한 Multi-Head Attention 레이어가 포함된 하나의 인코더 혹은 디코더 레이어는 중첩되서 사용할 수 있다. 
    ![](https://i.imgur.com/yZsr44l.png)

* 마스크 행렬(Mask matrix)
     - 마스크 행렬을 이용해 특정 단어는 무시할 수 있도록 합니다. 
  - 마스크 값으로 음수 무한의 값을 넣어 softmax 함수의 출력이 0%에 가까워지도록 합니다.
 : Attention Energies값이 있을때, 어텐션 에너지값과 같은 차원의 Mask Matrix를 만들어서 엘레멘트 와이즈?!를 각각의 원소를 곱해서 "특정 단어"의 값을 0으로 만들어서 참고하지 않도록 합니다.

![](https://i.imgur.com/TOKUYf1.png)

* Transformer의 Attention
    * Encoder Self-Attention
        * 각각의 단어가 서로에게 어떠한 연관성을 가지는지를 Attention을 통해 구한다. 전체 문장에 대한 representation을 Learning할 수 있도록 하는것이 특징이다.
    * Masked Decoder Self-Attention
        * 각각의 출력 단어가 다른 모든 출력 단어를 모두 참고하지 않고 앞쪽에 등장했던 단어들만 참고한다.
    * Encoder-Decoder Attention
        * Query가 Decoder에 있고, 각각의 Key와 value는 인코더에 있다.
        * 각각의 출련단어들이 입력단어들 중에서 어떤 정보에 더 많은 가중치를 두는지 구한다.

* Self-attention은 Encoder와 Decoder 모두에서 사용됩니다. (매번 입력 문장에서 각 단어가 다른 어떤 단어와 연관성이 높은지 계산할 수 있습니다.)
![](https://i.imgur.com/WNfjMSd.png)

* Positional Encoding
    * 필요성
        * Transforemr 이전에는 RNN 구조의 LSTM과 같은 모델을 사용하여 순차적으로 입력되는 데이터를 처리 하였습니다. 이 구종에서는 Input에 입력되는 순서대로 RNN 모델 내에서 처리가 되었습니다. 
        * 데이터가 한번에 1개씩 처리 되기 때문에 연산 속도가 매우 느리다는 문제점이 있었습니다. 하지만 Transformer의 경우 입력되는 데이터를 순차적으로 처리하지 않고 한번에 병렬로 처리한다는 특징이 있습니다. 
        * 이와 같은 병렬 처리로 인한 장점이 있는 반면 데이터를 병렬 처리하면서 데이터가 입력된 순서에 대한 정보가 사라지는 무제가 발생하게 됩니다. 
        * 이 문제를 개선하기 위하여 Positional Encoding 이라는 개념을 도입하여 말 그대로 위치 정보를 Encoding 하는 역할을 하게 됩니다. 
: 네트워크가 각각의 입력 문장에 포함되어 있는 각 단어들의 상대적인 위치 정보를 알 수 있도록 이러한 주기성을 학습할 수 있도록 한다면 어떠한 함수도 가능하다. 즉, sin과 cos함수가 아닌 다른 함수를 사용해도 된다. 
    * Positional Encoding은 다음과 같이 주기 함수를 활용한 공식을 사용합니다.
    * 각 단어의 상대적인 위치 정보를 네트워크에게 입력합니다.
    ![](https://i.imgur.com/CyAYp3b.png)
