Introduction

BERT는 2019년에 구글에서 발표한 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 논문에서 제안된 모델로, GPT와 양대산맥을 이루고 있는 representation model이다. 논문 제목에도 나와 있듯이 GPT와는 다르게 양방향학습을 통해 이전 모델보다 더 좋은 성능을 기록했다고 한다. 또한 GPT가 트랜스포머의 디코더를 통한 아키텍처를 구성했다면, BERT는 트랜스포머의 인코더만을 이용한 언어모델이다. BERT라는 이름은 Sesame Street라는 미국 애니메이션의 캐릭터에서 따왔는데, 지금은 해당 언어모델에게 이름을 뺏긴거 같다.

Background

BERT가 나오기 전 Language Representation Model의 대표적인 것으로 ELMo와 GPT가 있었습니다.

ELMo의 경우 양방향 LSTM을 통해 양방향 문맥을 모두 고려해 임베딩을 생성합니다. 하지만 BERT 논문의 저자는 해당 방식이 완전한 양방향 문맥을 고려하지 않는다고 설명한다. 이는 두 LSTM을 독립적으로 학습시킨 후 출력을 연결시키는 형식이고, self attention이 적용되지 않아 문맥정보를 완벽하게 이해할 수 없다는 문제가 있습니다.

GPT는 트랜스포머의 디코드를 사용하여 Autoregressive한 방식으로 순차적으로 표현을 학습합니다. GPT는 단방향(Unidirectional)으로 표현을 학습하게 됩니다. 이러한 방식은 다음 단어를 생성하는데에는 유리할 수 있으나 긴 Context를 이해하는데 한계가 있을 수 있습니다.

그래서 BERT에서는 Masked Language Model을 통해 양방향의 context를 융합하여 representation을 생성하는 방법을 제안합니다. 또한 Next Sentence Prediction을 통해 text-pair representation 또한 학습 할 수 있었습니다.

위 figure를 보면 3가지 representation model을 비교해볼 수 있습니다. GPT는 트랜스포머를 활용하긴 하지만 단방향이고, ELMo는 양방향으로 학습을 진행하지만 독립적으로 학습이 진행하여 결합하는 방식이기에 양방향 문맥을 완벽하게 파악하지 못합니다. 하지만 BERT는 양방향 학습으로 학습하는 것을 볼 수 있습니다.

BERT

다음 figure는 BERT의 Overall을 보여줍니다. BERT는 GPT와 마찬가지로 pre-train과 fine-tuning으로 2개의 스탭으로 학습이 진행된다는 것을 알 수 있습니다.

BERT는 총 2개의 종류로 나눠집니다. 전체적인 구조는 똑같지만 안의 레이어 수와 같은 파라미터에 따른 차이가 존재합니다.

  • $BERT_{BASE}$ : BERT의 기본 모델로 110M의 파라미터를 가져, GPT-1과 동일한 파라미터를 가집니다. (L=12, H=768, A=12)
  • $BERT_{LARGE}$ : BASE 모델 보다 더 크기가 큰 모델로 총 파라미터는 340M개입니다. (L = 24, H = 1024, A = 16)
  • 이때 위의 기호는 다음을 의미합니다.
    • L : 트랜스포머 인코더 레이어의 수
    • H : Hidden vactor크기
    • A : self attention head의 개수

또한 BERT에서 정의하는 Sentence와 Sequence에 대해 알아야 합니다. BERT에서는 Sentence를 우리가 원래 문장(주어+동사+ ~)의 개념이 아닌 연속적인 단어들의 나열으로정의합니다. 이는 원래 문장보다 짧을 수도 한문장보다 더 길게 잡을 수도 있습니다. Sequence는 1개 혹은 2개의 Sentence로 정의합니다.

이제 위 figure를 보며 BERT의 구조를 더 자세히 확인해보겠습니다. 우선 BERT의 pre-train 부분을 보면 입력으로 2개의 masked sentence가 들어갑니다. Masking의 개념은 아래에서 알아보기로 하고, 입력 부분을 보면 N개의 토큰을 가진 문장 A와 M개의 토큰을 가진 문장 B 2개가 입력되는 것을 볼 수 있습니다. 또한 출력부를 보면 final hidden state vactor가 출력이 되는데 이때 $T_N$은 입력에서의 토큰 N에 해당하는 hidden vactor가 됩니다.

그리고 여기서 특별한 토큰 2개가 사용됩니다. 첫번째는 [CLS] 두번째는 [SEP] 토큰입니다. [CLS]는 모든 시퀀스의 첫번째 토큰으로 들어가게 됩니다. [SEP]은 separating 토큰으로 2개의 문장을 구분해주는 토큰이라고보면 됩니다. 그리고 출력으로 나오는 final hidden state vector를 보면 첫번째 토큰 C는 [CLS]에 대한 토큰이 됩니다. C 토큰은 NSP문제의 분류에 사용되거나, 차후에 간단한 분류 문제로 쓸때 해당 토큰만을 보고 판단할 수도 있습니다.

그리고 윗부분을 보면 NSP와 Mask LM 이라고 적힌 부분을 볼 수 있는데 이는 Pretrain 단계에서 수행하는 2가지 task라 보면 됩니다.

Input Representation

다음은 BERT모델에 입력으로 들어가는 input representation입니다. token embedding과 position embedding의 경우 트랜스포머에서와 비슷합니다. 다만 token embedding의 경우 30000개의 vocabulary를 갖는 WordPiece를 통해 임베딩이 진행됩니다. (WordPiece의 경우 위 예시에서 playing이라는 단어가 있을때 play + ##ing와 같은 방법으로 처리하는 임베딩 방식입니다)

Segment Embadding의 경우 2개의 문장이 들어갔을 때 첫번째 문장은 CLS 토큰부터 SEP토큰까지, 두번째 문장은 나머지 부분으로 하여 이를 구분해주는 역할을 합 니다.

그리고 위 3개의 임베딩의 경우 같은 차원을 갖고 있으므로 3개를 더해서 최종 input representation을 만듭니다.

Pre-training BERT

BERT Pre-train 단계에서는 총 2가지의 Task를 수행합니다. 바로 Mask LM과 NSP인데요, 차근차근 살펴봅시다.

1. Mask LM(Language Model)

첫번째 task는 Mask LM입니다. Mask LM에서는 시퀀스에서 15%의 단어를 [MASK] 토큰으로 변경합니다. 이때 마스킹 된 단어를 주변 단어를 통해서 해당 마스킹 된 단어를 올바른 단어로 추론할 수 있도록 학습이 진행되게 됩니다.

이때 해당 방법은 Masking은 Pre-train단계에서만 적용되고 fine-tuning단계에서는 발생하지 않는 문제가 있습니다. 그래서 이러한 miss match 문제를 해결하기 위한 방법은 다음과 같습니다. 만약 특정토큰이 마스킹되는 토큰으로 선택되었을 때 80%는 마스킹을 하고, 10%는 랜덤한 토큰으로 치환을하고, 10%는 마스킹하지 않고 원래 토큰으로 유지합니다. 해당 수치는 위 표와 같이 여러 수치로 실험을 했을때 휴리스틱한 방법으로 찾아낸 수치임을 알 수 있습니다.

2. NSP(Next Sentence Prediction)

Pre-train의 두번째 sentence는 NSP입니다. 저자는 QA(Question & Answer)과 NLI(Natural Language Inference)에서 두 문장간의 관계를 이해해야만 잘 할 수있다고 주장합니다. 그래서 BERT에서는 여러 문장의 관계를 파악하기 위해 Binarized next sentence Prediction을 통해 다음을 진행하게 됩니다.

Binarized next sentence Prediction은 굉장히 간단합니다. 2개의 문장이 하나의 시퀀스로 들어가게 되는데 A 다음에 B가 들어가는 경우, 즉 일반적인 시퀀스인 경우 IsNext라 하며 이로 50%의 데이터셋을 구성합니다. 다음은 A 문장 다음에 랜덤한 문장을 가져오는 경우, 즉 corpus에서 A 다음 문장이 연속된 문장이 아니었던 경우를 NotNext라 하며 해당 시퀀스로 50%를 구성하게 됩니다. 그리고 토큰 C를 통해 해당 문장이 연속된 문장이었는지를 분류하게 됩니다.

해당 방법은 단순함에도 불구하고 QA과 NLI에서 굉장히 유의미한 차이를 보여줬다고 합니다.

Fine-Tuning BERT

논문에서는 총 4가지 task에 대한 fine-tuning을 언급하고 있다.

  1. Sentence pair classification : 두개의 문장이 주어졌을때 이들간의 관계를 예측하는 task
  2. single sentence classification : 하나의 문장을 입력받아(SST-2) 또는 문법적 적절성(CoLA)을 예측하는 task
  3. Question Answering : 주어진 paragraph에서 question에 대한 정답을 찾는 task, paragraph의 시작 토큰과 끝 토큰을 예측함
  4. Named Entity Recognition : 문장에서 특정 entity를 인식하는 task, 문장에서 해당 단어가 어떤 것인지(ex 사람이름, 장소) 태깅 작업을 수행

여기서 BERT 위에 하나의 레이어를 쌓는 것만으로도 구현 가능하다. 즉 다시한번 말하면 task별 아키텍처를 따로 설계하지 않고 BERT 출력 위에 추가적인 레이어만으로 fine-tuning이 가능하다는 것이다.