본문 바로가기
AI/딥러닝 기초(Deep learning)

[NLP] Transformer(트랜스포머)_② Deep dive

by Hyen4110 2021. 5. 24.

이전 글에서 Transformer(트랜스포머)가 왜 등장하였는지 그리고 어떤 특징을 가지고있는지 얕게 살펴보았습니다. 

2021.05.17 - [자연어처리(NLP)] - [NLP] Transformer(트랜스포머)_1) Warm up

 

[NLP] Transformer(트랜스포머)_1) Warm up

이 글은 아래 유튜브 영상 2개과 사이트 페이지의 내용을 정리한 글입니다. 저는 특정 딥러닝 모델이 등장한 배경, 당시 제기된 필요성에 대해서 알아가면서 배우는것을 좋아하는데요. 그런 블

hyen4110.tistory.com

이번 글에서는 Transformer(트랜스포머)의 원리에 대해서 깊게 살펴보고자 합니다.

이번 글을 작성하기위해서 참고한 글 리스트는 아래와 같으며, 특히 유튜브채널 KoreaUniv DSBA 의 '08-2 Transformer'강의와 '김동화-Transformer & BERT'를 보고 너무너무 많은 도움을 얻었습니다. 강필성 교수님의 깔끔하고 군더더기 없는 설명 강력추천 드리고, 코드 단까지 섬세하게 파헤쳐서 리뷰해주신 김동화 박사님의 영상도 추천합니다. 

 

1) KoreaUniv DSBA 08-2: Transformer : https://www.youtube.com/watch?v=Yk1tV_cXMMU

2) https://jalammar.github.io/illustrated-transformer/

3) https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

4) https://www.youtube.com/watch?v=xhY7m8QVKjo

1. Transformer

1.1 Encoder(인코더)와 Decoder(디코더)

 

- Encoding 부분은 여러개의 인코더들을 쌓아 놓은 구조(stack)이며  원논문에서는 6개의 인코더를 쌓았습니다(6개가 최

적이라는 논리적인 근거는 없다고 합니다).

 

- 기존의 seq2seq과 다른점은, 여러개의 인코더와 디코더를 쌓았다는 것(같은 수만큼)이 특징입니다. 

 

 

 

 

 

- 인코더 블록과 디코더 블록의 차이점(masked vs Unmasked)

: 인코더한 번에 모든 시퀀스 데이터를 사용한다는 것(Unmasked 방법)이고, 디코더시퀀스를 생성할때 즉 문장을 생성해나갈때 차례대로 생성하기 위해서 순서에 따라서 마스킹이 되어있다는 것(Masked 방법)입니다. 

: 인코더와 디코더를 구성하고 있는 블록도 2개의 Layer과 3개의 Layer로 조금 다른걸 볼 수 있습니다. 

https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

  Encoder Decoder
Masked vs Unmasked 인코더에서는 'robot', 'must', 'obey', 'orders' 네 토큰이 모두 한꺼번에 인코딩 과정을 지남 디코더에서는 5번째 토큰(시작토큰 포함해서 5번째)인 'orders'에 대한 번역을 생성하기 위해서는 그 전 단어(토큰)인 'obey'까지만 사용하고 'orders'는 마스킹하여 사용하지 않음
2단 vs 3단 1) Self- Attention
2) Feed Forward Neurla Nework
1) Masked Self-Attention
2) Encoder Decoder Self Attention
3) Feed Forward Neurla Nework

 

Encoder와 Decoder의 특징

*Encoder

- 인코더 블록들은 모두 같은(identical) 구조입니다.

 : 구조만 같을 뿐, 가중치를 공유하지 않습니다. 즉 학습에 의해서 얼마든지 다른 값을 가질 수있습니다. 

- 인코더 블록은 2개의 하위층(sub-layer)으로 구성되어 있습니다. 

Self Attention
Layer
- 입력 시퀀스에서 특정 단어(토큰)을 인코딩할때 다른 단어(토큰)이 얼마나 볼 것인가를 계산
- 토큰들 간의 의존(dependency) 존재함
Feed Forward
Neural Layer
- Self Attention Layer의 출력값을 입력값으로 받음
- 같은 FFN이 각 단어(토큰)마다 독립적으로 작용
  (=토큰들간의 의존(dependency) 존재하지 않음

*Decoder

- 디코더 블록은 인코더블록의 2 Layer에 'Encoder-Decoder Attention Layer'을 추가하여 3개의 하위층(sub-layer)으로 구성되어 있습니다. 

Encoder-Decoder Attention  - 최종적으로 단어를 생성할 때, 인코더에서 주어지는 정보를 어떻게 반영할 것인가를 결정

 

1.2 Step by Step

1.2.1 Encoder

1. Input Word Embedding

 

- 입력 시퀀스에 대한 벡터로, 가장 첫번째 인코더의 입력으로서만 사용이 되며 그 다음 인코더들은 앞의 인코더의 출력값을 입력값으로 받습니다. 

- 각 임베딩 벡터는 512 차원이며,  일반적으로 Word Embedding, Glove, Fastext등을 사용해서 입력단어에 대한 Embedding을 사용합니다. (512라는 숫자는 한 문장의 최대길이로 하이퍼파라미터로 지정하여 변경할 수 있습니다)

- 토큰 임베딩은 임베딩사이즈의 제곱근만큼 나누어지는 스케일링 과정을 거칩니다. 

https://www.youtube.com/watch?v=xhY7m8QVKjo

 

2. Positional Encoding 

 

- [의미] RNN 계열과 다르게 전체 시퀀스를 동시에 입력하기 때문에 순서에 대한 정보가 손실되는것에 대한 보완 기능으로, 각 단어의 위치 정보를 반영하기 위하여 만들어짐

- [과정] Positional Encoding은 input Embedding과 더해져서(sum이지 concat이 아님!) 새로운 512차원의 벡터를 만듭니다.  (*sum : (1x512) + (1x512) = (1x512) /  *concat : (1x512)+(1x512) = (1x1024))

https://jalammar.github.io/illustrated-transformer/

- Positional Encoding의 특징

  : 위치가 멀어질수록 길이가 멀어지며, 같은 단어라고 하더라도 문장 내의 위치에 따라서 트랜스포머의 입력으로 들어가는 임베딩 벡터의 값이 달라집니다. 


- Positional Encoding의 종류

Xavier initializer
Sinusiod initializer

[출처] https://www.youtube.com/watch?v=xhY7m8QVKjo

 

- Positional Encoding의 식

https://wikidocs.net/31379
https://jalammar.github.io/illustrated-transformer/f

 

https://www.youtube.com/watch?v=xhY7m8QVKjo

 

3. Self-Attention

- 입력 시퀀스의 특정 단어(토큰)을 처리할 때 다른 단어(토큰)들이 각각 얼마나 영향을 주는지 계산해서 특정 단어의 의미를 정확하게 파악하기 위함

 

https://jalammar.github.io/illustrated-transformer/

 

*Self Attention의 진행 과정

[Step1] 각 인코더의 input vector(각 단어의 embedding)로부터 3개의 벡터 생성

   - Query vector: 현재 처리중인 단어(토큰)에 대한 표현으로, 다른 단어의 영향도를 계산하기 위한 기준이 되는 값 

   - Key vector: 레이블과 같은 역할로, 쿼리가 주어졌을 때 관련된 유의미한 단어를 찾을 때 =

   - Value vector: Key가 레이블이라면 Value는 실제 값

https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

 

*Query, Key, Value 벡터를 만드는 과정

- Query, Key, Value 벡터 모두 input imbedding (1xn)에 다가 weight인 W(nxn)을 곱함으로써, 최종적으로 Key, Val, Query(1xm) 벡터를 만들어 냅니다. 

 

- 여기서 weight에 해당하는 W값은 학습 해야하는 파라미터입니다. 

 

- 일반적으로 input embedding에 대한 차원(512-dim)보다는 Query, Key, Value 벡터의 차원을 더 낮게(64-dim) 가집니다(이미지 참고). 그 이유는 Multihead Attention을 통과한 벡터를 모두 concat해서 해당 인코더/디코더의 출력값으로 사용하기 때문에, Query, Key, Value의 차원을 낮게 한다음 concat을 하여 다시 원래 차원으로 만들기 위함입니다. (64*8 = 512/ '8': Multihead Attention의 숫자)

 

 

[Step2] 스코어 계산하기

- 현재 처리하고자 하는 단어(Query)에 대하여 해당 input sentence의 단어들(Key, Value)의 영향도 스코어를 계산하고자 합니다. 

현재 보고있는 단어(q, Query)와 나머지 단어들(k, Key)를 곱하면 스칼라값이 112, 96으로 각각 나오는것을 볼 수 있습니다. 

 

위에서 구한 스칼라값(112, 96)을 차원(d(k))의 루트만큼 나눠줍니다. 여기서 Query, Key, Value의 차원수가 64였으므로, 루트를 씌운 값이 8로 나눠줍니다. (이를 나눠주는 이유는, 'gradient가 안정적이어지는데 도움'이 되기 때문)

 

소프트맥스 함수를 거쳐 0~1사이의 값을 얻는다.

: 현재 토큰에 대한 중요도를 확률로 나타냄

 

소프트맥스 값(스칼라)에 Value를 곱하여 weighted value vector를 만듭니다. 즉 초점을 두고 싶은 단어의 값은 건드리지 않고, 관련이 없는 단어는 0에 가까운 값을 곰함으로써 작은 값을 갖게 합니다.

 

 weighted value vector를 모두 더한 값을 구하며(z1 = v1 + v2), 그 값은 첫번째 Self-Attention Layer의 출력값이 된다.

->이것이 특정 한 토큰에 대하여 스코어를 계산하는 과정이며, 각 단어마다 이 과정을 진행하여 각각 z1, z2, ... zn 을 만들게 됩니다.  

https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

 

*attention 개념 잠깐!

'쿼리(Query)와 키(Key)를 곱하는게 무슨 의미인거야? 
--> 쿼리(Query)와 키(Key)를 곱한다는 의미는, '쿼리(Query)'에 대해서 모든 '키(Key)'와의 유사도를 구한다는 말입니다. 따라서 그리고 구해낸 이 유사도를 가중치로 하여 키와 맵핑되어있는 각각의 '값(Value)'에 반영해줍니다. 그리고 유사도가 반영된 '값(Value)'을 모두 가중합하여 리턴합니다.

 

*Matrix로 본 Self-Attention Score구하는 과정

https://jalammar.github.io/illustrated-transformer/

 

<Self Attention>

 

https://www.youtube.com/watch?v=xhY7m8QVKjo

 

3*. Multi-Head Attention

- attention을 다르게 줌으로써 여러개의 경우의 수를 허용하는 방법이 Multi-Attention의 핵심입니다.

- 아래와 같이 Self-Attention을 n개 만큼 수행해서 Z matrix를 n개를 얻은 후, 그것을 concat하고, 학습가능한 파라미터 weightd을 곱하여, 원래 input embedding과 같은 차원의 출력값을 만듭니다. 

https://jalammar.github.io/illustrated-transformer/
[Multi-Head Attention 요약] https://jalammar.github.io/illustrated-transformer/

 

4. Residual connection & Layer normalization

1) Residual connection

https://jalammar.github.io/illustrated-transformer/

- Residual의 개념은 ResNet에서처럼 특정 입력값에 대한 layer의 출력값에 원래 입력값을 더하는 것입니다.

- 즉, layer의 출력값 function_layer(x)에다가 원래 x를 더해주었을 때

y = function_layer(x) + x

-> 미분하면, y' = function_layer'(x) + 1가 되어서 function_layer'(x) 값이 아주 작더라도, gradient가 최소 1만큼 전달이 되게 됩니다. 

- Residual 과 Normalization은 각 모든 인코더, 디코더 블록의 Self-Attention, FFN 뒤에 하나씩 붙어있습니다. 

 

 

2) Layer normalization 

- 텐서의 마지막 차원에 대해서 평균과 분산을 구하고, 이를 가지고 어떤 수식을 통해 값을 정규화하여 학습을 돕는 과정입니다. (https://wikidocs.net/31379)

 

 

5. Point-wide FeedForward Networks

 

- Fully Connected Layer이며, 각각의 position에 대하여 독립적으로 적용되지만, 동일합니다.(같은 블록 내에서는 동일하지만(같은 파라미터), 블록이 다를 경우, 완전히 다릅니다)

 

- 각각의 Layer마다 서로 다른 파라미터를 학습합니다. 

 

https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

- z1 입력할때와, z2를 입력할 때 파라미터(W1, W2, b1, b2)는 모두 같습니다. 

 

1.2.2 Decoder

1. Masked Multi-Head Attention

- Decoder에서의 Self-Attention Layer는 반드시 현재 처리중인 단어보다 앞쪽에 해당하는 단어에 대하여만 attention 점수를 참고할 수 있도록 하기 위하여 마스킹 처리를 하는 방법입니다. 

- 마스킹 처리는 Self-Attention에서 소프트맥스 함수를 취할 때, -∞값을 주어서, softmax(-∞) =0이 되도록 하여 attention score가 주어지지 않도록 합니다. 

https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

 

 

https://github.com/pilsung-kang/Text-Analytics/blob/master/08%20Seq2Seq%20Learning%20and%20Pre-trained%20Models/08-2_Transformer.pdf

 

 

2. Multi-Head Attention with Encoder Outputs

 

 

1) 가장 마지막 Encoder의 출력값(파란색)은 Key와 Value의 attention vector로 변환됩니다.

 

2) 이 Key와 Value들은 “encoder-decoder attention"에서 디코더가 입력 시퀀스의 적합한 위치에 focus하도록 돕습니다.

 

 

 

 3) 디코더는 인코더에서 Key, Value 벡터를 받아 차례대로 단어를 생성하며, 이는 출력값이 종료예약어가 나올 때까지 반복합니다.

 

4) decoder의 출력값은 다음 time step의 처음 decoder의 입력값으로 들어갑니다.  

 

 

https://www.youtube.com/watch?v=xhY7m8QVKjo

 

*Encoder와 Decoder에서 Self-Attention의 차이점

① 마스킹 처리

- 디코더에서의 Self-attention layer는 output 시퀀스에서 더 앞선 위치의 단어들에 대하여만 허용합니다. 

- 이는 특정 단어의 뒤에 나오는 단어들을 (self-attention 계산 과정 중) 소프트맥스 함수 이전에 마스킹 처리(음의 무한대 설정)하여 진행합니다.

 

② Encoder-Decoder Attention layer

"Encoder-Decoder Attention layer"는 Multi-head Self Attention과 거의 동일하지만, 인코더 블록(stack)의 최종 출력에서 Key, Values matrix를 받고 자기자신(Encoder-Decoder Attention layer) 아래로부터 Query matrix를 생성한다는것이 다른 점입니다.  

 

https://www.youtube.com/watch?v=xhY7m8QVKjo

3. Final Linear and Softmax Layer

- Final Linear and Softmax 층에서는 실수 벡터로 이루어진 디코더의 최종 출력값을 단어로 바꾸어주는 역할을 합니다.

- Linear layer은 단순한 fully connected NN이며, 디코더의 최종 출력벡터를 logit vector라고 불리는 훨씬 더 큰 vector로 투영(projects)합니다.

- 예를들어 모델이 1만개의 영어 단어를 훈련데이터 학습을 통해서 안다고 했을 때, 1만개 셀(cell) 너비의 logit vector를 생성합니다. 여기서 셀(cell)은 각 고유 단어의 스코어와 일치합니다.

- softmax layer는 해당 스코어를 0과 1사이의 확률로 변환하며, 그 중 가장 높은 확률을 가진 cell이 선택되어 해당 단어가 출력됩니다. 

 

 

 

이상으로 트랜스포머의 원리에 대해서 step by step 살펴보았습니다. 

[

 

댓글