본문 바로가기
Deep Learning/자연어처리

BERT(Bidirectional Encoder Representations form Transformers)

by 대소기 2022. 2. 20.

Intro

* BERT는 transformer를 이용해 구현되었으며, wikipedia(25억 단어)와 bookscorpus(8억 단어)와 같은 레이블이 없는 텍스트 데이터로 사전 훈련된 언어 모델이다.

* trasnformer로 구현된 모델이기 때문에 transformer에 대한 사전 지식이 필요하다. 이전에 transformer에 대해 정리해 둔 글이 있으니 참고하길 바란다.

https://soki.tistory.com/97

 

Transformer

Intro * Transformer는 seq2seq의 encoder, decoder를 차용하되, RNN을 제거하고 attention을 사용한 모델이다. * 처음에 transformer에 대한 개괄적인 설명을 보고 여기서 RNN을 제거하고 attention을 사용한 이..

soki.tistory.com

 

* BERT를 통해 사전훈련된 embedding을 사용하면 약간의 tuning만으로 우리가 원하는 task를 성공적으로 수행할 수 있다.

BERT의 크기

* 위에서 볼 수 있다시피 BERT는 trasnformer의 encoder를 쌓아 올린 구조이다.

* transformer의 encoder 층 수를 L, $d_{model}$의 크기(단어 vector의 차원 수)를 D, self-attention head의 수를 A라고 하였을 때 각각의 크기는 다음과 같다.

  • BERT-Base : L=12, D=768, A=12 : 110Million개의 파라미터
  • BERT-Large : L=24, D=1024, A=16 : 340Million개의 파라미터

BERT의 문맥을 반영한 Embedding

* BERT의 embedding은 문맥을 반영햔 embedding이다. 무슨 뜻이냐면 문장 내에서의 다른 단어들과의 관계를 반영한 embedding을 출력한다는 뜻이다. 이는 transformer의 encoder를 사용하기 때문이다.

* BERT-Base 모델의 경우 D=768이므로, 각 단어 vector는 768 차원의 vector이고, BERT-Base를 통과해 최종 출력된 단어 vector역시 768차원의 vector가 될 것이다(transformer의 encoder는 입력 vector와 출력 vector의 차원이 같다).

BERT의 subword tokenizer : WordPiece

* BERT는 subword tokenizer를 사용한다. subword tokenizer는 기본적으로 자주 등장하는 단어는 그대로 단어 집합에 추가하고, 자주 등장하지 않는 단어의 경우에는 더 작은 단위인 subword로 분리되어 subword들이 단어 집합에 추가된다는 아이디어를 사용한다.

토큰화 수행 방식

* 먼저 훈련 데이터로부터 만들어진 단어 집합을 준비한다.

1) 해당 토큰이 단어 집합에 존재할 경우 : 해당 토큰을 분리하지 않는다.

2) 토큰이 단어 집합에 존재하지 않을 경우 : 해당 토큰을 서브워드로 분리한다. 해당 토큰의 첫번째 서브워드를 제외한 나머지 서브워드들은 앞에 '##'(단어의 중간부터 등장하는 subword라는 표시)를 붙인 것을 토큰으로 한다.

예시

  • 만약 embeddings라는 단어가 입력으로 들어왔는데, 사전 훈련된 단어 집합에 embeddings라는 단어가 없다고 가정해보자.
  • subword tokenizer가 아닌 tokenizer의 경우 OOV(Out of Vocabulary) 문제가 발생하지만, subword tokenizer는 해당 단어를 subword들로 쪼개서 어떻게든 토큰을 생성한다.
    • 단어 집합에 em, bed, ding, s와 같은 단어들이 존재한다면 입력 'embeddings'은 em, ##bed, ##ding, ##s로 분리된다.

* 실제로 어떻게 tokenizing하는지 확인해보자.

import pandas as pd
from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-uncased") # Bert-base의 토크나이저
result = tokenizer.tokenize('Here is the sentence I want embeddings for.')
print(result)

# ['here', 'is', 'the', 'sentence', 'i', 'want', 'em', '##bed', '##ding', '##s', 'for', '.']

Position Embedding

* transformer에서는 encoder, decoder의 입력시 sin, cosine함수를 사용한 position embedding을 통해 문장 내의 단어들의 위치정보를 표현하였다.

* BERT에서는 position embedding vector를 학습 가능한 벡터로서 취급한다. 때문에 BERT의 문장 최대 길이인 512개의 position embedding vector가 학습될 수 있다.

BERT의 사전 훈련

1) MLM(Masked Language Model)

* BERT는 사전 훈련을 위해 입력 텍스트의 15%의 단어들을 마스킹 하고, 모델에게 이를 예측하도록 한다.

* 단, 15%의 단어들은 모두 일괄적으로 마스킹되지 않고 다음과 같이 3가지 방법으로 변환된다.

  • 80%의 단어들은 [MASK]로 변경한다.
  • ex) The man went to the store → The man went to the [MASK]
  • 10%의 단어들은 랜덤으로 단어가 변경된다.
  • ex) The man went to the store → The man went to the dog
  • 10%의 단어들은 동일하게 둔다.
  • ex) The man went to the store → The man went to the store

* 그냥 모두 [MASK]로 변환하지 않는 이유는 [MASK] 토큰이 파인튜닝 단계에서는 나타나지 않기 때문에 사전 학습 단계와 파인 튜닝 단계에서의 불일치가 발생할 수 있기 때문이다.

예시)

* 'My dog is cute. he likes playing.' 이라는 예문이 있다고 해보자.

* 문장은 tokenizer에 의해 ['my', 'dog', 'is' 'cute', 'he', 'likes', 'play', '##ing'] 와 같이 토큰화 된다.

* 만약 'dog' 단어가 마스킹 되었다면, MLM classifier는 마스킹된 단어가 무엇인지를 예측한다. 이 때 Dense layer와 softmax layer를 거쳐 가장 확률이 높은 단어를 하나 뽑게 된다.

* BERT의 훈련 과정에서 손실함수에는 이 마스킹된 단어 예측에 대해서만 반영되고, 마스킹되지 않은 나머지 단어들에 대한 예측은 반영되지 않는다.

* 마스킹되지 않고 단어가 변경되었거나, 단어가 그대로이지만, 변경 대상 15%안에 들었던 단어들에 있어서도 예측을 시행하고, 손실함수에 이를 반영한다.

* playing의 경우 단어가 변경되지는 않았지만, BERT는 이 단어가 변경되었는지 여부를 모르기 때문에 원래 단어가 무엇인지 예측하게 된다.

2) 다음 문장 예측(Next Sentence Prediction, NSP)

* BERT는 마스킹되거나 변경된, 혹은 변경되지 않은 단어의 원래 단어가 무엇인지를 예측하기도 하지만, 입력된 두 문장이 이어지는지 여부도 예측해야 한다.

* 입력은 두 개의 문장으로 구성되어 있고, 5:5 비율로 실제로 이어지는 문장, 관련없는 문장이 제공된다.

* 문장 종료시 [SEP] 토큰이 등장하며 두 개의 문장을 구분해준다(두 번째 문장 종료 이후에도 [SEP]토큰이 나온다)

* [CLS] 토큰은 두 문장이 이어지는지 여부를 binary classification 하는 위치에 삽입되는 특별 토큰이다.

* 하나 주의할 점은 이 두 개의 문장이라는 예시는 문제를 간단히 하기 위한 예시일 뿐이고, 실제로는 두 종류의 text data가 될 수도 있다는 점이다. 두 종류의 text data가 입력될 경우 문장의 개수는 두개가 아니라 매우 많을 것이다.

* MLM classification과 NSP classification에 대한 예측 둘다 동일하게 손실함수에 적용된다.

Segment Embedding

* BERT의 훈련에는 두 개의 문서가 주어진다고 했었다. 각 단어가 몇 번째 문서에 속해있는지를 구분하기 위해 segment embedding layer가 존재한다. 이 segment embedding은 position embedding을 거친 vector에 scalar 값으로서 더해주게 된다.

* 만약 감성분류 task와 같이 두 개의 문서를 입력받을 필요 없는 문제의 경우 segment layer에서 0 embedding만 더해주게 된다.

BERT를 Fine tuning하기

* 실질적으로 사전훈련된 BERT를 활용하는 방법으로 우리가 원하는 task의 데이터를 추가 학습시켜서 Fine-tuning하는 법을 알아보겠다.

1) Single Text Classification

* 감성분류 등에 사용된다. [CLS] 토큰 자리에서 해당 문서의 sentiment를 분류한다. binary classification이기 때문에 dense layer를 추가할 수 있다.

2) 하나의 텍스트에 대한 태깅 작업

* 품사 tagging혹은 개체명 인식 등에 사용될 수 있다.

3) 텍스트 쌍에 대한 분류 또는 회귀 문제

* Text pair를 입력받아 두 text들이 contradiction, entailment, neutral 중 어떤 것인지에 대해 분류하는 task를 수행할 수도 있다.

4) Question Answering

* SQuAD(Stanford Question Answering Dataset)를 사용하여 질문과 본문이 주어졌을 때 본문에서 질문에대한 답을 찾는 등의 QA task를 훈련시킬 수 있다.

* 질문 : "강우가 떨어지도록 영향을 주는 것은?"

* 본문 : "기상학에서 강우는 대기 수증기가 응결되어 중력의 영향을 받고 떨어지는 것을 의미합니다. 강우의 주요 형태는 이슬비, 비, 진눈깨비, 눈, 싸락눈 및 우박이 있습니다."

* 답 : 중력

 

 

 

그 외 기타

* 훈련 데이터는 위키피디아(25억 단어)와 BooksCorpus(8억 단어) ≈ 33억 단어

* WordPiece 토크나이저로 토큰화를 수행 후 15% 비율에 대해서 마스크드 언어 모델 학습

* 두 문장 Sentence A와 B의 합한 길이. 즉, 최대 입력의 길이는 512로 제한

* 100만 step 훈련 ≈ (총 합 33억 단어 코퍼스에 대해 40 에포크 학습)

* 옵티마이저 : 아담(Adam)

* 학습률(learning rate) : 10−4

* 가중치 감소(Weight Decay) : L2 정규화로 0.01 적용

* 드롭 아웃 : 모든 레이어에 대해서 0.1 적용

* 활성화 함수 : relu 함수가 아닌 gelu 함수

* 배치 크기(Batch size) : 256

Attention Mask

* Attention mask는 pad token에 대해 attention을 하지 않도록 마스킹해주는 역할을 한다.

 

 

 

https://wikidocs.net/108730

 

01) NLP에서의 사전 훈련(Pre-training)

2018년 딥 러닝 연구원 세바스찬 루더는 사전 훈련된 언어 모델의 약진을 보며 다음과 같은 말을 했습니다. ```

wikidocs.net

 

'Deep Learning > 자연어처리' 카테고리의 다른 글

Transformer  (0) 2022.02.20
다양한 단어의 표현방법  (0) 2022.01.27
Sparse Representation, Dense Representation  (0) 2021.12.27
RNN을 이용한 디코더-인코더 - Seq2Seq  (0) 2021.12.23
글자 단위 RNN(Char RNN)  (0) 2021.12.18