2020. 2. 11. 16:49ㆍnlp
출처
1) Dissecting BERT Part 1: Understanding the Transformer
2) Dissecting BERT Part2: BERT Specifics
Part 1
1. Encoder
Level 1 : Problem
- Transformer의 과제는 번역하기
- Encoder : 입력 문장(출발어) 안의 단어끼리 관계 포착하기
- Decoder : [입력 문장의 정보] + [번역된 단어, 출력문장(도착어)]
Level 2 : Flow of Information
1) 각 토큰을 embedding 벡터로 바꾼다. 따라서 전체 input 문장은 (input_length) * (embedding_dim) 크기의 행렬이 된다
2) 이 embedding에 단어의 위치 정보(positional encoding)를 더한다. 여전히 input 문장은 (input_length) * (embedding_dim) 크기의 행렬
3) 이 행렬이 N개의 Encoder를 거쳐간다. 그 결과도 여전히 (input_length) * (embedding_dim) 크기의 행렬
4) target 문장은 가려진채로 Decoder에 전해진다. target 문장도 1),2)와 똑같이 전처리됨. [embedding] + [positional encoding]. target 문장도 (target_length) * (embedding_dim) 크기의 행렬이 된다.
* target_length = target 문장 길이 +1 ∵ 문장 시작 태그 <SS> 맨 앞에 삽입해야 함
5) 이 행렬이 N개의 Decoder를 거쳐간다. Decoder는 Encoder의 3)에서의 output을 이용한다. 그 결과는 여전히 (target_length) * (embedding_dim) 크기의 행렬
6) 마지막으로 FC와 Softmax를 거친다. 최종 결과는 (target_length) * (vocab_size)
Level 3-a : Inputs
1) input 문장을 숫자로 바꾼다
[“Hello”, “, “, “how”, “are”, “you”, “?”] → [34, 90, 15, 684, 55, 193]
cf. target 문장의 경우
[“Hola”, “, “, “como”, “estás”, “?”]→[“<SS>”, “Hola”, “, “, “como”, “estás”, “?”]
2) 이 숫자에 embedding vector를 대응시킨다
3) Positional Encoding
4) embedding vector + positional encoding vector
Level 3-b : Layers
1) Multi-Head Attention
- Attention을 여러 번, 다른 weight 행렬로 구하고, 이들을 모두 합친다는 의미
< 한 번의 Dot-Product Attention >
< 여러 번의 Dot-Product Attention 후 합치기>
2) Dropout, Add & Norm
- MultiHead Attention 또는 Feed Forward 레이어 이후에 dropout
- dropout 전 레이어의 input : x
- dropout은 확률 0-1 사시에서 지정되어 Dropout(Sublayer(x))
- 이 둘이 더해져서 : x + Dropout(Sublayer(x))
- 그 다음에 정규화
3) Position-wise Feed-Forward Network
- 각 token에 대해 x : embedding_dim
- xW1 + b1 : hidden_dim
- max(0, xW1 + b1) : hidden_dim
- max(0, xW1 + b1)W2 + b2 : embedding_dim
- 각 token들이 독립적으로 다뤄져서 계산됨
- 따라서 모든 토큰을 계산한 최종 결과 행렬의 사이즈는 (input_length) * (embedding_dim)
- Encoder의 input과 output 사이즈는 같음. 따라서 Encoder의 output을 Decoder의 input으로 사용 가능
2. Decoder
Test 시 Decoder
1) input sequence(문장)의 embedding을 계산
2) <SS> 등 문장의 시작을 알리는 토큰을 첫 target sequence 로 사용
3) 모델이 그 다음에 예측한 target sequence를 계속 더해가며 새로운 sequence를 만들어감
: [<SS>, Prediction_1,…,Prediction_n]
4) <EOS> 등 문장의 끝을 알리는 토큰이 나올 때까지 3)번을 계속 반복
Train 시 Decoder
- ground truth (정답 output)가 있기 때문에 모델에게 이 정답을 한 번에 주고 예측하게 만듦
- 그런데 모델이 정답을 훔쳐보면 안됨
- 정답으로 주어진 것이 [‘<SS>’,’Hola’, ‘,’, ‘ como’, ‘estas’, ‘?’] 라면
- 이들의 embedding + positional encoding 으로 만든 행렬 : (target_length) * (emb_dim)
- 여기서 <SS> 줄의 값은 'Hola'를 예측하는데 사용되고 'Hola' 줄의 값은 그 다음 토큰인 ','를 예측하는데 사용됨
- 따라서 'estas'를 예측해야할 상황이라면 아래 그림에서 초록 부분만 봐도 되고 빨간 부분은 보면 안 됨
- 레이어가 하나만 있다면 이는 문제가 되지 않음. Multi-Head Attention의 경우 마스크(mask)가 필요함
Masked Multi-Head Attention
- 마스크는 각 Decoder의 맨 처음에만 필요함
- Decoder 중간은 [Encoder에서 보낸 정보(인코딩된 input)] + [이전 레이어의 output] 을 더하는 일을 하기 때문
- Softmax까지 적용하면 우리가 보지 말아야할 토큰에 대한 attention이 0으로 수렴함
- 이 행렬을 Value vector와 곱하면, 테스트 시에도 모델에게 제공되는 정보만 제공됨
- 이렇게 수정된 Multi-Head Attention 레이어의 output은 (target_length) * (emb_dim) 크기의 행렬
Multi-Head Attention
- 이 레이어는 [Encoder의 최종 output, E] + [Decoder 내 직전 레이어의 output, D] 모두를 입력받음
* E : (input_length) * (emb_dim)
* D : Masked Multi-Head Attention이 Add&Norm 레이어를 지나간 이후의 결과, (target_length) * (emb_dim)
Part 2
BERT
- BERT = Bidirectional Encoder Representations from Transformers
- Transformer Encoder들을 쌓아놓은 것
OpenAI GPT vs. BERT
- OpenAI GPT : 일방향
- BERT : 양방향
(ex) "I love to work on NLP" 라는 문장의 "love'는 OpenAI GPT에서는 "I" 토큰과 자기 자신("love" 토큰)과만 self-attention 관계를 갖는다. BERT에서는 문장 안의 모든 토큰들과 self-attention 관계를 갖는다
그렇다면 OpenAI GPT는 왜 양방향으로 학습을 시키지 않았는가?
- OpenAI GPT는 Language Model 과제로 모델을 학습시켰다.
- 다음 단어를 예측하는 걸 학습시키는데 다음 단어를 알려주면 안되니까 일방향 self-attention만 가능
- 그래서 Masked Multi Self Attention 을 사용함
BERT는 왜 양방향 학습이 가능했는가?
- BERT는 OpenAI GPT와 다른 과제를 풀었다. (영어를 독일어로 번역하는 과제)
- Transformer Encoder 내에서는 영어 문장만 돌아다님. 과제는 독일어 번역문을 예측하는 것
- 따라서 Encoder 내에서는 양방향 학습을 해도 전혀 예측해야 할 정답이 누출되는 것이 아님
- Encoder 내에서는 마스크 필요 없음!
OpenAI GPT는 모델 pre-training을 Language Model로 진행함
BERT는 모델 pre-training을 Masked Language Model과 Next Sentence Prediction으로 진행함
BERT의 Input Embeddings
- input sequence를 약간씩 수정해서 모델이 다양한 과제를 수행할 수 있도록 함
- pretrained token embeddings 사용
- learned positional embeddings 사용
- [SEP] 토큰 : Next Sentence Prediction 과제 중 두 문장의 경계 알려주기
- [CLS] 토큰 : 분류 과제 여부를 알려주기
Pre-training
Task 1 : Masked Language Model
- 주어진 sequence의 다음 단어를 예측하는 것이 아니라, 문장 안의 단어들 중 랜덤한 곳을 가려놓고(masked) 그 안에 들어갈 단어를 예측하도록 함
- 한 input sequence 토큰의 15%를 가림(masked)
- 토큰이 존재하는 방식 3가지 (ex) "My dog is hairy"
1) 80% : <MASK> 토큰을 사용해 가려지기 (ex) "My dog is <MASK>"
2) 10% : 랜덤한 토큰으로 대체되기 (ex) "My dog is apple"
3) 10% : 그대로 놓기 (ex) "My dog is hairy"
- 그냥 <MASK> 토큰만 사용하면 모델은 아무것도 예상할 필요 없다고 생각함. 그리고 <MASK> 토큰의 문맥을 학습할 것
- 가리지 않고 원 문장 그대로 두기도 하면서 모델이 meaningful representation을 배울 수 있도록 함
Task 2 : Next Sentence Prediction
- 두 문장을 입력으로 주고 두 번째 문장이 첫 문장 다음에 오는 문장인지 아닌지 모델이 예측하게 함
- 두 문장의 관계를 학습할 수 있도록 만든 과제
- Q&A, 자연어 추론 성능에 큰 도움을 줌
- 50%는 두번째 문장이 첫 문장 다음에 오는 문장, 나머지 50%는 그냥 랜덤하게 뽑힌 두 문장
Pre-training procedure
- pre-training에서 input 문장의 예시
Input = [CLS] the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]
- 여기서 두 문장은 연이은 문장이므로 [CLS] = <IsNext>
Input = <IsNext> the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]
- pre-training에서 [CLS] 토큰은 1개의 output만 내놓을 수 있음 (multi-label classification 불가능)
- 오차 = [Masked Language Model 확률의 평균] + [Next Sentence Prediction 확률의 평균]
Fine-tuning
- [CLS] 토큰의 1개 output을 분류하고 싶은 class 개수만큼의 차원으로 늘려야 함
- 첫 토큰인 [CLS]의 마지막 은닉상태에 Linear Layer, Softmax 를 더해서 차원을 늘림
- C : [CLS] 토큰의 마지막 은닉 상태 벡터, 사이즈 (h)
- W : 가중치 행렬weight matrix, 사이즈 (k,h)
* k = 분류하고 싶은 class/label의 개수
- CW = k 차원의 벡터
'nlp' 카테고리의 다른 글
넷플릭스/네이버 시놉시스 word2vec 시각화하기 (0) | 2020.02.22 |
---|---|
BERT Word Embeddings 튜토리얼 번역 및 정리 (3) | 2020.02.14 |
그림으로 보는 BERT 번역 및 정리 (0) | 2020.02.11 |
Seq2seq pay Attention to Self Attention Part 1-2 번역 및 정리 (0) | 2020.02.10 |
그림으로 보는 Transformer 번역 및 정리 (0) | 2020.02.10 |