본문 바로가기
인공신경망(DL)/NLP

Transformer / BERT, GPT

by kiimy 2021. 8. 22.
728x90
  • Transformer의 장점과 주요 프로세스인 Self-Attention에 대해 이해하고 설명할 수 있다.
    • 트랜스포머를 발표한 논문 제목은 왜 "Attention is All You Need"인지 설명할 수 있다.
    • Positional Encoding을 적용하는 이유에 대해서 설명할 수 있다.
    • Masked Self-Attention가 트랜스포머 구조 중 어디에 적용되며 어떤 역할을 하는지 설명할 수 있다.
    • 기존 RNN과 비교하여 Transformer가 가지는 장점에 대해서 설명할 수 있다.
  • GPT, BERT 그리고 다른 모델에 대해서 개략적으로 설명할 수 있다.
    • GPT(Generative Pre-Training)
      • 사전 학습된 언어 모델(Pre-trained LM)의 Pre-training과 Fine-tuning은 무엇이고 각각 어떤 종류의 데이터셋을 사용하는 지 설명할 수 있다.
      • GPT는 Transformer를 어떻게 변형하였는지 설명할 수 있다.
    • BERT(Bidirectional Encoder Representation by Transformer)
      • BERT는 Transformer를 어떻게 변형하였으며 GPT와의 차이 무엇인지 알 수 있다.
      • MLM(Masked Language Model)은 무엇인지 이해할 수 있다.
      • NSP(Next Sentence Prediction)은 무엇인지 이해할 수 있다.
  • 최근 언어 모델의 발전은 어떻게 진행되고 있는지 알 수 있다.
  • 주의 : 이후에도 새로운 모델을 공부하게 되면 아래와 같은 순서로 학습하게 될 겁니다.
    1. 논문을 통해 해당 모델의 컨셉과 대략적인 구조를 파악한다.
    2. 기존에 구현되어 있는 라이브러리를 통해 해당 모델을 사용해본다. (추론 혹은 파인튜닝)
    3. 해당 모델에 대한 좀 더 깊은 이해가 필요할 경우 코드로 구현해본다.

 

정리: https://github.com/codestates/AIB04_Discussion/discussions/22

Transformer

-어텐션을 RNN의 보정을 위한 용도가 아니라 아예 어텐션으로 인코더와 디코더를 만들어보면 어떨까

 라는 아이디어로 시작

= 결과적으로 좋은 성능을 보임

 

Transformer parameter

* dmodel = 512

트랜스포머의 인코더와 디코더에서의 정해진 입력과 출력의 크기를 의미

각 인코더와 디코더가 다음 층의 인코더와 디코더로 값을 보낼 때에도 이 차원을 유지

 

* num_layers= 6

트랜스포머에서 하나의 인코더와 디코더를 층으로 생각하였을 때,

트랜스포머 모델에서 인코더와 디코더가 총 몇 층으로 구성되었는지를 의미

 

* num_heads = 6

트랜스포머에서는 어텐션을 사용할 때, 1번 하는 것 보다 여러 개로 분할해서 병렬로 어텐션을 수

행하고 결과값을 다시 하나로 합치는 방식, 이 병렬의 개수를 의미(= multi head )

트랜스포머가 어텐션을 병렬적으로 수행하는 방법( 앙상블 효과 )

 

* dff= 피드포워드

트랜스포머 내부에는 피드 포워드 신경망이 존재, 이때 은닉층의 크기를 의미

피드 포워드 신경망의 입력층과 출력층의 크기는 dmodel

 seq2seq 구조에서는 인코더와 디코더에서 각각 하나의 RNN이 t개의 시점(time-step)
가지는 구조였다면 이번에는 인코더와 디코더라는 단위가 N개로 구성되는 구조

인코더 블록과 디코더 블록이 6개씩 모여있는 구조
내부 구조

* 인코더 블록은 크게 2개의

sub-layer [Multi-Head (Self) Attention, Feed Forward]


* 디코더 블록은 3개의

sub-layer [Masked Multi-Head (Self) Attention, Multi-Head (Encoder-Decoder) Attention, Feed Forward] 

https://wikidocs.net/31379

1. Positinoal Encoding

pos는 입력 문장에서의 임베딩 벡터의 위치를 나타내며, i는 임베딩 벡터 내의 차원의 인덱스를 의미

위의 식에 따르면 임베딩 벡터 내의 각 차원의 인덱스짝수인 경우에는 사인 함수의 값을 사용하고

홀수인 경우에는 코사인 함수의 값을 사용

 

각 임베딩 벡터에 포지셔널 인코딩값을 더하면 같은 단어라고 하더라도 문장 내의 위치에 따라서

트랜스포머의 입력으로 들어가는 임베딩 벡터의 값이 달라진다.

== 트랜스포머의 입력은 순서 정보가 고려된 임베딩 벡터

RNN의 경우에는 단어의 위치에 따라 단어를 순차적으로 입력받아서 처리 하기에
각 단어의 위치 정보(position information)를 가질 수 있었다.
 
Transformer는 모든 단어 벡터를 동시에 입력받기 때문에 위치를 알 수가 없다.
=  단순히 각 단어의 임베딩 벡터들을 입력받는 것이 아니라 임베딩 벡터에서 조정된 값을 입력 받음

단어의 위치 정보를 제공하기 위한 벡터를 따로 제공해줘야 하는데
이를 위해서 Positional Encoding 과정을 거치게 된다. == 주기함수를 사용

2. Self- Attention , Encoder

= 각각의 단어가 서로에게 어떤 연관이 있는지 파악

( 문맥의 정보를 잘 학습시키는 것)

+ 추가적으로 Residual learning 잔여 학습을 통해서 성능 향상시킬 수 있다.

 

Attention Value

- '쿼리(Query)'에 대해서 모든 '키(Key)'와의 유사도를 각각 구한다.

그리고 구해낸 이 유사도를 가중치로 하여 키와 맵핑되어있는 각각의 '값(Value)'에 반영

그리고 유사도가 반영된 '값(Value)'을 모두 가중합하여 리턴

  • 쿼리(q)는 분석하고자 하는 단어에 대한 가중치 벡터
  • 키(k)는 각 단어가 쿼리에 해당하는 단어와 얼마나 연관있는 지를 비교하기 위한 가중치 벡터
  • 밸류(v)는 각 단어의 의미를 살려주기 위한 가중치 벡터

입력 문장 내의 단어들끼리 유사도를 구하므로서

그것(it)이 동물(animal)과 연관되었을 확률이 높다는 것을 찾을 수 있다.

==> 셀프 어텐션은 입력 문장의 단어 벡터들을 가지고 수행

 

  1. 먼저, 특정 단어의 쿼리(q) 벡터와 모든 단어의 키(k) 벡터를 내적합니다. 내적을 통해 나오는 값이 Attention 스코어(Score)가 됩니다.
  2. 트랜스포머에서는 이 가중치를 q,k,v 벡터 차원  의 제곱근인  로 나누어줍니다.
    계산값을 안정적으로 만들어주기 위한 계산 보정으로 생각해주시면 됩니다.
  3. 다음으로 Softmax를 취해줍니다.
    이를 통해 쿼리에 해당하는 단어와 문장 내 다른 단어가 가지는 관계의 비율을 구할 수 있습니다.
  4. 마지막으로 밸류(v) 각 단어의 벡터를 곱해준 후 모두 더하면 Self-Attention 과정이 마무리됩니다.

1. 인코더의 초기 입력인 dmodel의 차원을 가지는 단어 벡터들을 사용하여 셀프 어텐션을 수행하는 것이

아니라 우선 각 단어 벡터들로부터 Q벡터, K벡터, V벡터를 얻는 작업을 거친다.

가중치 행렬  Wq, Wk, Wv로부터 각 단어의 쿼리, 키, 밸류(q, k, v) 벡터를 만든다.

* 해당 단어 벡터들의 차원은 dmodel / num_heads 

초기 입력인 dmodel의 차원을 그대로 쓰지 않는 이유
한 번의 Attention을 하는 것보다 여러번의 Attention을 병렬로 사용하는 것이 더 효과적이라고 판단
so, 차원을 축소시킨 벡터로 Attention을 수행

 

 

2. 분석하고자 하는 단어의 쿼리 벡터(q)와 문장 내 모든 단어(자신 포함)의 키 벡터(k)를 내적하여

각 단어와 얼마나 관련 정도를 구한다. root dk == 기울기 소실 방지하기 위한 scale

* [16, 4, 4, 16] == Attention score

dk = dmodel / num_heads

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

 

3. softmax를 사용하여 어텐션 분포(Attention Distribution)을 구하고,

   각 V 벡터와 가중합하여 어텐션 값(Attention Value)을 구할 수 있다.

 

 

4. 하나의 벡터에 대해서만 살펴보았지만 실제 Attention 계산은 행렬 단위로 병렬 계산된다.

문장 행렬의 가중치 행렬을 곱하여 Q 행렬, K 행렬, V행렬 구한다
Attention Score 행렬

  1. 먼저 쿼리 행렬(Q)과 키 행렬(K)을 내적합니다. 
  2. 결과로 나오는 행렬의 요소를   나누어 줍니다. = 각 행과 열의 Attention Score
  3. 행렬의 각 요소에 Softmax를 취해줍니다. = Attention Distributed
  4. 마지막으로 밸류 행렬(V)과 내적하면 최종 결과 행렬(Z)이 반환됩니다. = Attention Value

Multi-head Attention ( Encoder에선 Self-Attention )

- Self-Attention 을 동시에 여러 개로 실행하는 것

==> 각 Head 마다 다른 Attention 결과를 내어주기 때문에 앙상블과 유사한 효과

 Attention이 8개로 병렬로 이루어지게 되는데, 이때 각각의 Attention Value 행렬을 Attention head라고 한다

==> 다른 시각으로 정보들을 수집

WO 행렬

  1. WQ, WK, WV에 해당하는 d_model 크기의 밀집층(Dense layer)을 지나게한다.
  2. 지정된 헤드 수(num_heads)만큼 나눈다(split).
  3. 스케일드 닷 프로덕트 어텐션.
  4. 나눠졌던 헤드들을 연결(concatenatetion)한다.
  5. WO에 해당하는 밀집층을 지나게 한다. == 행렬WO 요소는 학습을 통해 갱신됨

최종적으로 생성된 행렬 Z토큰 벡터로 이루어진 행렬 X 동일한 크기(Shape)가 된다.

3. Layer Normalization & Skip Connection

- 트랜스포머의 모든 sub-layer에서 출력된 벡터는 Layer normalization Skip connection을 거치게된다.

Layer normalization의 효과는 Batch normalization과 유사

Skip connection(혹은 Residual connection)은 역전파 과정에서 정보가 소실되지 않도록 한다.

(= 학습이 훨씬 빠르고 잘 되도록)

4. Feed Forward

은닉층의 차원이 늘어났다가 다시 원래 차원으로 줄어드는 단순한 2층 신경망
활성화 함수(Activation function)으로 ReLU를 사용

outputs = tf.keras.layers.Dense(units=dff, activation='relu')(attention) Encoder

outputs = tf.keras.layers.Dense(units=d_model)(outputs) Decoder


1. Masked Self-Attention Decoder

- 미리보기에 대한 마스크

디코더는 일반적으로 숨겨진 상태에서 출력을 생성하는 부분이다.

Auto Regressive는 디코더가 이전 상태의 예측을 사용하여 다음 단계를 생성하는 반복 구조라는 것을 의미

예를 들어, 이전 예측 출력 단어를 사용하여 번역 중에 다음 출력 단어를 생성

 seq2seq의 디코더에 사용되는 RNN 계열의 신경망은 입력 단어를 매 시점마다
순차적으로 받으므로 다음 단어 예측에 현재 시점 이전 이전에 입력된 단어들만 참고할 수 있었다.

반면, 트랜스포머는 문장 행렬로 입력을 한 번에 받으므로 현재 시점의 단어를 예측하고자 할 때,
입력 문장 행렬로부터 미래 시점의 단어까지도 참고할 수 있는 현상이 발생

==> 디코더는 Auto Regressive 하게 단어를 생성하기 때문에 타깃 단어 이후 단어를 보지 않고 단어를 예측

타깃 단어 뒤에 위치한 단어는 Self-Attention에 영향을 주지 않도록 마스킹(masking)해야 한다.

 

Masked Self-Attention 에서는 Softmax를 취해주기 전, 가려주고자 하는 요소에만 -1e9 

해당하는 매우 작은 수를 더해준다.

"""

mask가 있을 경우 masking된 자리(mask=1)에는 (-inf)에 해당하는 절댓값이 큰 음수 -1e9(=-10억)을 더해줍니다.

그 값에 softmax를 취해주면 거의 0에 가까운 값이 나옵니다. 그 다음 value 계산시에 반영되지 않습니다.

"""

# add the mask to the scaled tensor.

if mask is not None:

     scaled_attention_logits += (mask * -1e9)

2. Encoder-Decoder Attention 

- 좋은 번역을 위해서는 번역할 문장번역된 문장 간의 관계 역시 중요

 

디코더 블록 Masked Self-Attention으로부터 출력된 벡터를 쿼리(Q) 벡터로 사용합니다.
키(K)와 밸류(V) 벡터는 최상위(=6번째) 인코더 블록에서 사용했던 값을 그대로 가져와서 사용

== 계산은 Self-Attention과 동일

3. Linear & Softmax Layer

- 디코더의 최상층을 통과한 벡터들은 Linear 층을 지난 후 Softmax를 통해 예측할 단어의 확률을 구한다.


GPT, BERT

임베딩 층(Embedding layer)를 랜덤 초기화하여 처음부터 학습하는 방법과 방대한 데이터로

Word2Vec 등과 같은 임베딩 알고리즘으로 이미 학습된 임베딩 벡터들을 가져와 사용하는 방법이 있다.

태스크에 사용하기 위한 데이터가 적다면, 사전 훈련된 임베딩을 사용하면 성능을 높일 수 있었고,

자연어 처리에서 광범위하게 사용되었다.

 

하지만

하나의 단어가 하나의 벡터값으로 맵핑되므로 문맥을 고려하지 못한다는 점

다의어나 동음이의어를 구분하지 못하는 문제점

==> 임베딩 벡터는 '사과'라는 벡터에 하나의 벡터값을 맵핑하므로 '용서'의 '사과' 

       두 가지 의미를 구분할 수 없다.

 

이러한 한계는 사전 학습된 언어 모델(Pre-trained Language Model)로 해결된다.

= 사전 학습이란 대량의 데이터를 사용하여 미리 학습하는 과정

여기에 필요한 데이터를 추가 학습시켜 모델의 성능을 최적화 == 전이 학습(Transfer Learning)

책을 많이 읽는 것처럼 레이블링 되지 않은 데이터를 모델이 학습하도록 하는 과정을 사전 학습 이라고 합니다.

 

사전 학습이 끝난 모델에 우리가 하고자하는 태스크에 특화된(Task specific) 데이터를 학습합니다.
이를 Fine-tuning 이라고 합니다.
Fine-tuning에서는 학습시 레이블링 된 데이터

[Ex) 감성 분석, 자연어 추론(NLI), 질의 응답(QA)] 를 사용합니다

GPT, Generative Pre-trained Transformer 

GPT에서는 인코더를 사용하지 않기 때문에 디코더 블록내에 2개의 Sub-layer

[Masked Self-Attention,  Feed-Forward]

= GPT는 인코더를 사용하지 않기 때문에 Encoder-Decoder Attention 층이 빠지게된다.

12개의 인코더를 사용한다.

 

  • 사전 학습(Pre-training)

지난 노트에서 배웠던 언어 모델처럼 다음에 올 단어를 계속해서 맞추는 방식으로 학습합니다.

  • Fine-tuning

기존 모델에서는 태스크에 맞춰 모델 구조를 변경해주고 학습을 진행시켰습니다.

하지만 GPT와 같은 사전 학습 언어 모델은 Fine-tuning 과정에서 데이터의 입력 방식만을

변형시키고 모델 구조는 일정하도록 설계되었습니다. ??


BERT, Bidirectional Encoder Representation by Transformer

- 수많은 NLP 태스크에서 최고 성능을 보여주면서 명실공히 NLP의 한 획을 그은 모델로 평가

- 트랜스포머의 인코더만을 사용하여 문맥을 양방향(Bidirectional)으로 읽어낸다.

인코더 블럭을 12개 사용

( Base 버전에서는 총 12개를 쌓았으며, Large 버전에서는 총 24개를 쌓았다 )

 

성능이 좋은 이유

레이블이 없는 방대한 데이터로 사전 훈련된 모델을 가지고, 레이블이 있는 다른 작업(Task)에서

추가 훈련과 함께 하이퍼파라미터를 재조정하여 이 모델을 사용하면 성능이 높게 나오는

기존의 사례들을 참고하였기 때문

 

Special Token : [CLS], [SEP]

BERT에는 [CLS] [SEP]이라는 두 가지 Special Token이 있습니다.


[CLS] 토큰은 입력의 맨 앞에 위치하는 토큰입니다.
아래에서 등장할 NSP(Next Sentence Prediction)이라는 학습을 위해 존재합니다.

 

[SEP] : Separation

[CLS] : Classification

[SEP] 토큰은 첫 번째 부분의 끝자리와 두 번째 부분의 끝자리에 위치합니다.

Input Vector : Token Embeddings, Segment Embeddings, Position Embeddings

 

BERT는 3종류의 임베딩 벡터를 모두 더하여 모델에 입력합니다.

  • Token Embeddings : 단어를 나타내는 임베딩입니다.

Word2Vec, GloVe, FastText 등으로 사전 학습된 임베딩 벡터를 사용합니다.

  • Segment Embeddings : 첫 번째 부분과 두 번째 부분을 구분하기 위한 임베딩입니다.

[CLS] 부터 첫 번째 [SEP] 까지 동일한 벡터를 적용하고, 다음 토큰부터 두 번째 [SEP] 까지 동일한 벡터를 적용합니다.

  • Positional Embeddings : 단어의 위치를 나타내기 위한 임베딩입니다.

BERT 역시 Pre-trained Language Model이기 때문에 사전 학습 이후에 Fine-tuning을 진행


BERT는 GPT와 다른 방식의 사전 학습이 적용

- GPT는 앞으로 올 단어를 예측해가며 학습 하지만

- BERT는 2가지 방법이 있다. (MLM, NSP)

* 사전학습 Pre-training

MLM(Masked Language Model)

사전 학습 과정에서 레이블링 되지 않은 말뭉치 중에서 랜덤으로 15%가량의 단어를 마스킹
그리고 마스킹된 위치에 원래 있던 단어를 예측하는 방식으로 학습을 진행

빈칸 채우기를 하면서 단어를 학습

NSP(Next Sentence Prediction)

모델이 문맥에 맞는 이야기를 하는지 아니면 동문서답을 하는지를 판단하며 학습하는 방식

[SEP] 토큰 왼쪽의 문장과 오른쪽의 문장이 바로 이어지는 문장일 경우 [CLS] 토큰의 출력이 IsNext 로 되도록 학습

두 문장이 이어지지 않는 쌍일 경우에는 출력 벡터가 NotNext 로 나오도록 학습

fine-tunning

(a)는 “Sentence” 쌍을 분류하는 태스크입니다. [SEP]으로 나눠진 “Sentence” 쌍을 입력받아

 [CLS]가 출력하는 클래스를 반환합니다.

 

(b)는 감성분석 등 하나의 문장을 입력하여 [CLS]로 해당 문장을 분류하는 태스크입니다.

 

(c)는 질의 응답 태스크입니다. 질문과 본문에 해당하는 단락을 [SEP] 토큰으로 나누어 입력하면 질문에 대한

답을 출력하도록 합니다.

 

(d)는 품사 태깅(POS tagging)이나 개체명 인식(Named Entity Recognition, NER) 등의 태스크입니다.

입력받은 각 토큰마다 답을 출력합니다.

 

결론적으로는 지금은 보다 더 좋은 모델이 만들어져 있고 이러한 기반으로 만들어졌다는 것이다.

 

트랜스포머의 디코더 블록만을 사용한 GPT는 상대적으로 자연어 생성과 관련된 태스크에,
인코더 블록만을 사용한 BERT는 자연어 이해와 관련된 태스크에 특화되어 있습니다.
GPT와 같이 순차적으로 자연어를 생성하는 모델에는 AR(Auto-Regressive)한 방법이 적용되었다고 하고,
BERT와 같이 노이즈를 맞추어가는 방식으로 자연어를 이해하는 모델에는 AE(Auto-Encoder)한 방법이

적용되었다고 합니다.

728x90

댓글