논문 : https://arxiv.org/abs/1706.03762
Attention Is All You Need
The dominant sequence transduction models are based on complex recurrent or convolutional neural networks in an encoder-decoder configuration. The best performing models also connect the encoder and decoder through an attention mechanism. We propose a new
arxiv.org
안녕하세요. 오늘은
Transformer에 대한 논문 리뷰를 진행하겠습니다!
Seq2Seq 매커니즘의 문제점으로 인해
Attention 이라는 매커니즘이 세상에 나왔으며
이 Attention만을 이용해 구현한 모델이 바로
Transformer 모델입니다.
Seq2Seq 매커니즘과 Attention 매커니즘은
각각 포스팅으로 작성했으니 참고 부탁드립니다.
https://aigaeddo.tistory.com/51
Seq2Seq 매커니즘
위키독스 내용을 참고했습니다.https://wikidocs.net/24996 14-01 시퀀스-투-시퀀스(Sequence-to-Sequence, seq2seq)이번 실습은 케라스 함수형 API에 대한 이해가 필요합니다. 함수형 API(functional API, https://wikidocs.n
aigaeddo.tistory.com
https://aigaeddo.tistory.com/52
Attention 매커니즘
이번 포스팅에서는 Attention 매커니즘에 대해서학습하는 시간을 가져보겠습니다! 위키독스와 해당 포스팅을 참고할게요!https://wikidocs.net/22893 15-01 어텐션 메커니즘 (Attention Mechanism)앞서 배운 seq2
aigaeddo.tistory.com
위키독스를 참조했습니다.
https://wikidocs.net/31379
16-01 트랜스포머(Transformer)
* 이번 챕터는 앞서 설명한 어텐션 메커니즘 챕터에 대한 사전 이해가 필요합니다. 트랜스포머(Transformer)는 2017년 구글이 발표한 논문인 Attention i…
wikidocs.net
1. 트랜스포머(Transformer)의 주요 하이퍼파라미터
트랜스포머의 주요 하이퍼파라미터를 먼저 정의하겠습니다.

트랜스포머의 인코더와 디코더에서 정해진 입력과 출력의 크기
임베딩 벡터의 차원도 되며,
각 인코더와 디코더가 다음 층의 인코더, 디코더로 값을 보낼때 해당 차원을 유지합니다.
논문에서 정의한 값은 512입니다.

인코더와 디코더의 층을 나타내는 파라미터입니다.
논문에서는 각 6개의 층을 쌓았습니다.

어텐션을 사용할 때 한번에 하는 것보다
여러개의 병렬처리로 어텐션을 수행하고
다시 결과값을 하나로 합치는 방식을 선택했는데 해당 병렬 작업의 개수입니다.
논문에서는 8로 정의했습니다.

트랜스포머 내부의 피드포워드 신경망(MLP같은 단방향 전달 구조의 신경망)의
은닉층 크기입니다.
논문에서는 2048로 정의했습니다.
2. 트랜스포머의 구조

언뜻보면 인코더들과 디코더들로 이루어져 Seq2Seq와 동일한 구조로 보입니다.

하지만 트랜스포머 모델은 Seq2Seq 매커니즘과 다르게
RNN을 사용하지 않고 N개의 인코더,디코더로 구성되는 구조입니다.
아래는 인코더와 디코더가 6개로 구성된 구조의 트랜스포머 모델을 나타냅니다.

Seq2Seq과 동일하게 인코더 정보를 전달받아 디코더에서 출력 결과를 만들어 줍니다.
디코더는 시작심볼<sos>를 입력받아 종료심볼<eos>가 나올때 까지 연산합니다.
3. 포지셔널 인코딩(Positional Encoding)
트랜스포머의 입력 부분을 먼저 보자면,
자연어 처리시 RNN이 유리했던 이유는
단어의 위치에 따라 순차적으로 입력받아 처리할 수 있어서였습니다.
즉, 각 단어의 위치정보(position information)을 가질 수 있다는 점에서 였습니다.
하지만 트랜스포머는 단어 입력을 순차적으로 받는 방식이 아닙니다.
그래서 단어의 위치 정보를 얻기 위해 각 단어의 임베딩 벡터에 위치 정보들을
더해서 모델의 입력으로 사용합니다.
이를 포지셔널 인코딩(positional encoding)이라고 합니다.


입력으로 사용되는 임베딩 벡터들이 트랜스포머의 입력으로 사용되기 전에
포지셔널 인코딩의 값과 더해지게 됩니다.

인코딩 부분을 더 자세하게 알아보겠습니다.
포지셔널 인코딩은 아래의 함수를 사용합니다.
Positinal Encoding이 만족해야하는 필요 조건들은
조건 1. 각 위치값은 시퀀스의 길이나 입력 값에 관계없이 동일한 위치값을 가져야함.
조건 2. 모든 위치값이 입력값에 비해 너무 크면 안됨.
조건 3. Positional Encoding의 값이 빠르게 증가되면 안됨(gradient vanishing 예방)
조건 4. 위치 차이에 의한 Positional Encoding값의 차이를 거리로 이용할 수 있어야 함.
조건 5. positional Encoding 값은 위치에 따라 서로 다른 값을 가져야 함.
라고 합니다. 이 필요 조건을 모두 충족시키는 함수가 아래의 함수입니다.


pos : 입력문장의 임베딩 벡터에서 위치
i : 임베딩의 차원내 인덱스
dmodel : 출력 차원(여기서는 임베팅 벡터의 차원)
가 되며
PE(pos,2i) : 포지셔널 인코딩 중 짝수 인덱스
PE(pos, 2i + 1) : 포지셔널 인코딩 중 홀수 인덱스
입니다.
홀수는 sin함수를 씌워줬고,
짝수는 cos함수를 씌워줬습니다.
이유는 주기성을 가지므로 조건 1을 만족하며,
-1 ~ 1 사이의 값을 가지므로 조건 2, 3을 만족합니다.
홀수는 sin, 짝수는 cos함수를 사용하므로서
조건 4번을 충족하며, 최대한의 거리차를 둘 수 있도록 했습니다.

먼저 sin함수를 들여보면 A는 진폭, N은 진동수와 관련이 있고
A는 진폭을 -1~1사이로 유지할 것이기 때문에 무시합니다.
N이 작아지면 진동수가 작아지고 주기가 길어지게 됩니다.
해당 주기를 길어지게 하면 조건 5번을 충족할 수 있게되며
Transformer 저자는 N을 1/10000으로 정의해서 반복을 피하도록 했습니다.
이렇게 해서 해당 함수를 이용해서 조건 1~5번을 모두 만족하게 만든 것입니다.
(대단하네요....)

포지셔널 인코딩의 값은 embedding vector와 summition(단순 덧셈) 해서
인코더의 입력값으로 들어가게 됩니다.
여기서 concat이 아닌 sum을 해주는 이유는
Transformer구조가 GPU를 많이 필요로 하는 만큼 메모리 낭비를 줄이고자라고 합니다.
sum이 가능하게 하기 위해서 embedding 된 차원에 맞춰 positional encoding 차원을 맞춰줍니다.

4. 어텐션(Attention)
트랜스포머에서는 3가지 어텐션을 사용합니다.

1. Encoder Self-Attention
2. Masked Decoder Self-Attention
3. Encoder-Decoder Attention
이름대로 1번 어텐션은 Encoder에서,
2,3번 어텐션은 Decoder에서 이뤄집니다.
Self-Attention은 Query, Key, Value가 동일한 경우입니다.
3번째는 Query자체가 Decoder의 벡터이고 Key와 Value는 인코더의 벡터이므로
Self-Attention이 아니게 됩니다.

Transfomer의 아키텍처에서 봤을때
각 종류의 Attention은 해당 위치에 사용되게 됩니다.
Multi-head라는 이름이 붙은 이유는 트랜스포머가
어텐션을 병렬적으로 수행하기 위한 방법이 사용된 구조라서 입니다.
5. 인코더(Encoder)
먼저 인코더 구조를 보겠습니다.
(좌우 동일한 구조의 그림입니다.)


인코더는 2개의 서브층(sublayer)로 나뉘어집니다.
각 Self Attention과 FeedFoward 신경망입니다.
위의 그림에서는 멀티 헤드 어텐션이라고 써진건 위에서 말했듯
병렬 처리를 하는 셀프 어텐션이라는 말이고,
포지션 와이드 피드 포워드 신경망이라는 말은
깊게 층을 쌓는게 아닌
얇고 넓게 노드를 늘려준 포워드 신경망의 모양이라서 붙은 이름 같습니다.
6. 인코더의 셀프 어텐션
6-1. 셀프 어텐션의 의미와 이점
어텐션 함수는 Query 에 대해서 모든 Key와의 유사도를 구한다고 했습니다.
그리고 이 유사도를 가중치로 키와 매핑된 값에 반영을 해줍니다.
그리고 유사도가 반영된 값을 모두 곱해 더해주는 가중합을 해서
Attention Value로 리턴해줍니다.

사실상 Seq2Seq에서 어텐션에서의 Q,K,V의 개념은
Query : t 시점의 디코더 셀에서의 은닉 상태
Keys : 모든 시점의 인코더 셀의 은닉 상태들
Values : 모든 시점의 인코더 셀의 은닉 상태들
이고, 사실상 t시점을 반복하게 되면서
Querys : 모든 시점의 디코더 셀에서의 은닉 상태들
Keys : 모든 시점의 인코더 셀의 은닉 상태들
Values : 모든 시점의 인코더 셀의 은닉 상태들
으로 일반화가 가능합니다. 이 개념을 트랜스포머에 적용한다면
Q : 입력 문장의 모든 단어 벡터들
K : 입력 문장의 모든 단어 벡터들
V : 입력 문장의 모든 단어 벡터들
이 됩니다.
6-2. Q,K,V 벡터 얻기
셀프 어텐션은 인코더의 초기 입력인 dmodel의 차원을 가지는
단어 벡터들로 어텐션을 수행하는게 아닌
각 단어 벡터들로 부터 Q벡터, K벡터, V벡터를 얻는 작업을 먼저 하게 됩니다.
논문에서 정의한 하이퍼파라미터중 num_heads로 결정이 되는데
이는 앞서 병렬처리를 하기 위한 개수라고 설명했습니다.
논문에서는 dmodel 입력 차원인 512를 num_heads 인 8로 나눠줘 64차원을
가지는 Q벡터, K벡터, V벡터로 변환합니다.

student라는 단어의 Q,K,V 벡터를 얻는 그림입니다.
각 가중치 행렬은

의 크기를 가지게 됩니다. 이유는 dmodel을 가중치와 곱하게 되면 dmodel/ num_heads의 차원이
결과로 나와야 하기 때문입니다.
각 가중치는 처음에 랜덤값으로 구성되며 훈련 과정에서 학습됩니다.
결과적으로 논문에서의 내용으로 보면
512의 dmodel벡터를 512 x 64의 가중치 행렬로 곱하고
64 크기를 가지는 Q,K,V 벡터를 얻어냅니다.
이 과정을 모든 단어에서 반복합니다.
6-3. 스케일드 닷-프로덕트 어텐션(Scaled dot-product Attention)
앞선 어텐션 포스팅에서는
Q벡터와 K벡터를 비교해서 Attention Score을 뽑아내는데
dot 방식을 사용한 닷-프로덕트 어텐션을 설명했었는데요,
이번에는 스케일드가 붙습니다.
즉, Attention Score을 뽑아내는데 스케일링이 한 번 들어가는 의미로 보시면 됩니다.

n = dk 은 k벡터의 차원을 나타내는 값입니다. 위의 그림에서는 2가 됩니다.
논문에서는 K는 64차원이니 dk는 64가 됩니다.
루트를 씌워준 이유는 표준정규분포를 따르면서 추후 소프트맥스 함수에 적용했을때
이상적인 특정을 보일 수 있도록 하기 위해서라고 합니다.
결론적으로 Attention Score를 구하기 위해서는
Q와 K를 내적한 값에 루트를 씌운 dk를 나눠줍니다.
논문의 값으로 구해보면 8로 나눠주게 되는 것입니다.

Attention Score를 소프트맥스 함수를 통과시켜
Attention Distribution 값으로 만들어줍니다.
이후 해당 값을 Value값과 곱해 Attention Value로 출력합니다.
6.4 행렬 연산으로 일괄 처리하기
위에서는 벡터연산으로 표현했던 것을
행렬 연산으로 처리하면 일괄계산이 가능합니다.
실제로는 I/ am/ a / student 로 잘린 벡터 형태가 아닌
I + am + a +student의 임베딩 후 포지셔널 인코더와
더해진 행렬로 Q, K, V 행렬을 구하게 되는 것이죠.

아래의 그림에서 보면 Q와 K의 행렬 자체를 내적해서 Attention Score을 뽑아냅니다.
I의 행, student의 열을 가지는 자리는 Q에서 I에 대한 값과, K의 student에 대한 값에
대한 Attention Score가 됩니다.

결과적으로 스케일드 닷 프로덕트 어텐션의 최종 Attention Value 는 행렬로 나오게 됩니다.

위의 그림은 아래의 스케일드 닷-프로덕트 어텐션의 수식을 만족합니다.

AttentionValue 행렬의 크기를 구해보자면
1. 입력 문장의 길이가 seq_len 라면 문장 행렬의 크기는

이 됩니다.
2. Q행렬, K 행렬 크기는

,V 행렬의 크기는

가 됩니다.
3. Wq 와 Wk는 각각


의 크기를 갖게 되며
4. 결과적으로 AttentionValue 행렬의 크기는

가 됩니다.
여기서 dv값은 dmodel/num_heads의 값이니
논문에서의 값으로 행렬의 크기를 구해보면
(단어의 개수 , 64) 가 됩니다.
6-4. 멀티 헤드 어텐션
dmodel을 num_heads로서 나눈 차원을 가지는 Q,K,V의 행렬로
변경하고 어텐션을 수행한 건 병렬처리, 즉 멀티 헤드 어텐션의 개념이었습니다
그럼 왜, 어떻게 단어 벡터를 가지고 어텐션을 하지 않고
차원을 축소시킨 행렬로서 어텐션을 수행하는 걸까요?

앞서 (seq_len, dv)의 크기로 나온 각각의 병렬 어텐션의
가중치 행렬은 각각 다 다른 값을 가지고 있습니다.
즉, 연관도의 시각이 다양하다는 뜻이죠.
병렬처리를 하므로서 이런 다양한 시각의 연관도를 수집할 수 있게 됩니다.

각각의 병렬처리된 AttentionValue는 Concatenate되어 연결됩니다.
이 연결된 행렬의 크기는 다시

가 되며, 또 다른 가중치 행렬인 W0와 곱해지게 됩니다.

이 과정이 끝나야만 멀티헤드 어텐션의 최종 결과물인
Multi-head attention matrix를 구할 수 있습니다.
전체적인 구조를 다시 표현하면 아래의 그림과 같이
표현할 수 있습니다.

6-5. 패딩마스크
사실 스케일드 닷 프로덕트 어텐션 함수 내부를 보면 mask라는 옵션이 있습니다.
해당 연산에 대해서 알아보겠습니다.

mask라는 것은 입력 문장중에서 PAD 부분이 있다면 해당 부분을
처리해주는 마스킹 개념입니다.

예를들어 I / am /sam /<pad> 값이 들어온다면
이 pad에 대한 단어를 굉장히 큰 음수값인 -1e9(-1000000000)로 채워주게 됩니다.

이런 큰 음수값이 소프트맥스 함수를 거치게 되면
0이 되며 단어 간 유사도를 구하는 일에 <pad> 토큰이 반영되지 않습니다.
(0이 아닌 -1e9를 넣는 이유는 0을 넣으면 연산 시 컴퓨터의 Error가 발생할 경우가 생길 수 있기 때문이라고 합니다.)

7. 포지션-와이드 피드 포워드 신경망(Position-wise FFNN)
다시 한 번 인코더의 구조를 살펴보겠습니다.
멀티헤드 셀프어텐션에서 나온 Attention Value Metrics 값은
Feed Forward라는 곳으로 들어가게 되는데 이 부분을 설명하겠습니다.

인코더 부분에서 설명하고 있지만 어텐션 부분과 마찬가지로 디코더에서도
공통적으로 가지고 있는 서브층입니다.
Fully-connected FFNN이라고 해석할 수 있습니다.
깊지 않고 1개의 히든레이어에 많은 수의(논문에서는 2048)의 노드를 가지는
구조여서 포지션 와이드라는 이름이 붙지 않았나 생각됩니다.
피드 포워드라는 뜻은 단일 신경망, 즉 MLP형태라고 보면 될 것 같습니다
FFNN(x) = MAX(0, x{W_{1}} + b_{1}){W_2} + b_2

FFNN은 위의 수식과 구조를 갖습니다.
해당 가중치인 W1, b1, W2,b2는 하나의 인코더 층에서는 공유가 되지만
다른 인코더 층에는 공유되지 않습니다.
구조에서 보이듯 하나의 Relu 함수를 activation함수로 가지는 히든레이어로 구성되며
논문에서는 하이퍼파라미터 dff의 값 2048의 크기를 넣어주었으므로
해당 히든 레이어의 노드수는 2048개가 됩니다.
9. 잔차연결(Residual connection) , 층 정규화(Layer Normalization)

Add & Norm 부분의 Add에 해당되는 개념입니다.
9-1. 잔차연결(Residual connection)
위 그림의 어텐션 구조를 보면 Multi-Head Attention을 거치기 전 값과
Multi-Head Attention의 출력 값이 더해지는 것을 보실 수 있습니다.
이 개념이 잔차 연결입니다.

H(x)의 서브레이어를 F(x)라고 한다면
H(x)함수의 입력값과 서브레이어 F(x)의 출력 값을 더하는 수식을
H(x) = x + F(x)로 나타낼 수 있습니다.
혹은 x+Sublayer(x) 로 나타낼 수 있습니다.
서브층이 멀티헤드 어텐션이라면 잔차연산을 아래와 같이 표현할 수 있습니다.
H(x) = x+Multi-head\ Attention(x)

9-2. 층 정규화(Layer Normalization)
Add & Norm 부분의 Norm에 해당되는 개념입니다.
잔차 연결을 거친 결과는 층 정규화 과정을 거칩니다.
보통 딥러닝에서의 정규화 방식은 2가지인데
Batch Nomalization, Layer Normalization이 있습니다.
간단하게 말하면 이전 레이어의 출력 값을 정규화해서 다음 레이어의 훈련에 안정성을 주고Overfitting을 막는 기법입니다.(이부분은 따로 포스팅 하겠습니다.)보통 Batch Nomalization은 Sequence data를 다루는 RNN모델 형태에서는적용시키기 힘들다고 합니다. 그래서 Layer Normalizaion을 사용하지 않았나 합니다.Batch Normalization은 데이터의 feature 별 batch에 대해서 정규화를 하는 기법이라면Layer Normalization은 layer의 모든 뉴런에 대한 인풋을 정규화를 하는 기법입니다.

트랜스포머에서는 잔차연결을 거친 결과를
층 정규화를 통해 텐서의 마지막 차원에서 평균과 분산을 구하고
정규화하게 됩니다.
LN = LayerNorm(x+Sublayer(x))

10. 인코더에서 디코더로
인코더는 num_layers 만큼 층 연산을 순차적으로 한 후
마지막 층의 인코더 출력을 디코더에 전달합니다.

11. 디코더
11-1.디코더의 첫번째 서브층, 셀프 어텐션과 룩-어헤드 마스크(look-ahead mask)
아래의 그림과 같이 디코더도 인코더와 동일하게 임베딩 층에서 포지셔널 인코딩을 거친 후의
문자 행렬이 입력됩니다.
Seq2Seq와 동일하게 교사강요(Teacher Forcing) 로 훈련이 진행되며,
그러므로 디코더에서는 번역할 문장에 해당되는 <sos> je suis étudiant의 문장 행렬을 한 번에 입력받습니다.
<sos>는 문장의 시작을 뜻하는 값입니다.
교사강요란 n-1번째의 실제값으로 n번째의 단어를 예측한다고 생각하시면 됩니다.
그래서 문장 행렬을 한 번에 입력받는게 필요합니다.

문장 행렬을 한번에 입력받으므로 트랜스포머에서는 입력 문장의 행렬로부터 미래 시점의 단어까지
참고할 수 있는 현상이 발생하였고 이를 막기 위해
룩-어헤드 마스크(look-ahead mask)라는 개념을 도입했습니다.

룩-어헤드 마스크는 위의 디코더 구조에서 첫번째 서브층에서 이루어집니다.
디코더의 첫번째 서브층은 인코더의 첫번째 서브층인 Multi head self-attention과 동일한 연산을 수행합니다.
다만 디코더에서는 이 룩-어헤드 마스크를 적용합니다.

인코더의 첫번째 서브층과 동일하게 연산을 해서
Attention Score Matrix를 뽑아낸 후

마스킹 방식은 위의 인코더에서 설명한 패딩마스크와 동일하며,
Softmax를 거치기 전에 해당 마스킹 할 score에 -1e9를 더해줍니다.
11-2 . 디코더의 두번째 서브층, 인코더- 디코더 어텐션
인코더- 디코더 어텐션은
멀티 헤드 어텐션을 수행하지만, 셀프 어텐션이 아닙니다.
Query는 디코더 행렬,
Key와 Value는 인코더 행렬에서 가져오게 됩니다.

왼쪽의 2개 화살표는 인코더의 마지막층의 행렬이며, 우측의 1개 화살표는 첫번째 서브층의 결과 행렬입니다.

입력의 종류가 다를뿐 Q,K,V 을 이용해 어텐션 스코어 행렬을 구하는 과정은 셀프 어텐션과 동일합니다.
3개의 연달은 포스팅으로 Seq2Seq의 개념,어텐션의 개념,
항상 궁금해왔던
Transformer에 대해서 조금 알아보았습니다.
틀린점이 있다면 지적부탁드립니다.
'인공지능 개발하기 > 기술 & 논문 리뷰' 카테고리의 다른 글
| [논문 리뷰] Fast R-CNN (2) | 2024.05.11 |
|---|---|
| [논문 리뷰] R-CNN(Rich feature hierarchies for accurate object detection and semanti (0) | 2024.05.09 |
| Attention 매커니즘 (0) | 2024.04.27 |
| Seq2Seq 매커니즘 (0) | 2024.04.27 |
| [논문 리뷰] YOLOv1(You Only Look Once: Unified, Real-Time Object Detection) (1) | 2024.03.06 |