HOW AI WORKS

BERT는 어떻게 동작하는가
— 빈칸을 맞히며 양쪽을 동시에 읽는 법

BERT의 구조는 새롭지 않습니다. 논문 스스로 "원래 Transformer 구현과 거의 동일하다"고 쓰고, BERTBASE는 비교를 위해 일부러 OpenAI GPT와 같은 크기(12층 · 768 · 12헤드)로 맞췄습니다. 두 모델의 차이는 사실상 어텐션 마스크 한 장 — GPT는 왼쪽만, BERT는 양쪽을 봅니다. 그런데 마스크를 걷어내면 언어 모델을 학습시킬 수가 없습니다. 층을 두 번만 지나도 각 단어가 정답인 자기 자신을 간접적으로 보게 되기 때문입니다. BERT의 진짜 기여는 이 문제를 푸는 학습 과제입니다 — 입력의 15%를 가리고 맞히게 하는 Masked LM, 그리고 두 문장이 이어지는지 맞히는 NSP. 이 자료는 논문을 앞에서부터 따라가며 그 두 과제가 왜 그런 모양이 되었는지, 80/10/10이라는 이상한 비율은 어디서 왔는지, 110M 파라미터가 어디에 있는지, 그리고 출력층 하나만 붙여 11개 과제를 푸는 파인튜닝이 실제로 무엇을 새로 배우는지를 브라우저에서 직접 계산해 봅니다.

how-ai-works 시리즈 · 원전: Devlin, Chang, Lee & Toutanova, BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (NAACL 2019, arXiv:1810.04805)

앞서 읽으면 좋은 자료 · How Transformer Works (블록 하나와 마스크 행렬 — BERT는 그 인코더 쪽입니다) · How Bidirectional RNN Works (양방향의 대가와 라벨 누수) · How word2vec Works (문맥 없는 단어 벡터 — BERT가 넘어서려던 것) · How N-gram Works (데모 3의 셈법)
차례
  1. 사전학습 표현을 쓰는 두 가지 방법 — 그리고 단방향이라는 제약
  2. 왜 그냥 양방향 언어 모델을 만들 수 없는가 — "자기 자신을 본다"
  3. 입력 표현 — 세 임베딩의 합과 [CLS]·[SEP]
  4. 과제 1 · Masked LM — 15%와 80/10/10
  5. 과제 2 · 다음 문장 예측(NSP)
  6. 모델 크기 — 110M과 340M은 어디에 있나
  7. 사전학습 레시피 — 33억 단어, 100만 스텝, 그리고 128/512
  8. 파인튜닝 — 출력층 하나로 11개 과제
  9. 결과 — GLUE · SQuAD · SWAG · 특징 추출
  10. 정리 — 한 장 요약
  11. 이해도 퀴즈

§1 사전학습 표현을 쓰는 두 가지 방법 — 그리고 단방향이라는 제약

2018년에는 "큰 말뭉치로 언어 모델을 먼저 학습시켜 두면 다른 과제에 도움이 된다"는 것이 이미 알려져 있었습니다. 논문 1절은 그 사전학습 표현을 하위 과제(downstream task)에 가져다 쓰는 방법을 두 가지로 나눕니다.

특징 기반 (feature-based)파인튜닝 (fine-tuning)
대표ELMo (Peters et al., 2018a)OpenAI GPT (Radford et al., 2018)
하는 일사전학습 모델은 얼려 두고, 그 출력을 과제별 모델의 추가 특징으로 넣는다과제별 파라미터는 최소한만 추가하고, 사전학습 파라미터 전부를 과제 데이터로 다시 학습한다
과제별 구조필요 (과제마다 설계)거의 불필요
사전학습 목표둘 다 단방향 언어 모델 — 앞 단어들로 다음 단어를 맞힌다

논문의 주장은 이 마지막 행에 있습니다. "표준 언어 모델은 단방향이고, 이것이 사전학습에 쓸 수 있는 구조의 선택을 제한한다." GPT의 Transformer에서는 모든 토큰이 자기 왼쪽만 볼 수 있습니다. 문장 분류에서도 아쉽지만, 질의응답처럼 토큰 하나하나에 답을 내야 하는 과제에서는 치명적일 수 있다고 논문은 말합니다 — "은행에 가서 돈을 찾았다"의 은행이 강둑인지 금융기관인지는 오른쪽에 있는 "돈"이 알려 주니까요.

ELMo는 이미 양방향이지 않냐고 물을 수 있습니다. ELMo는 왼→오 LSTM과 오→왼 LSTM을 따로 학습시킨 뒤 마지막에 두 출력을 이어 붙입니다. 논문은 이것을 얕은 결합(shallow concatenation)이라고 부르고, BERT는 모든 층에서 양쪽 문맥을 함께 조건으로 삼는(jointly conditioning on both left and right context in all layers) 깊은 양방향이라고 구분합니다(부록 그림 3). 이 둘이 실제로 얼마나 다른지 칸을 클릭해 확인해 봅시다.

데모 1 · 논문 그림 3 — 한 칸은 입력의 어디까지 보는가
세 구조를 같은 문장·같은 깊이(3층)로 펼쳤습니다. 아무 칸이나 클릭하면 그 칸의 값을 계산하는 데 쓰인 모든 칸(조상)이 칠해집니다. 색이 진한 칸은 왼쪽과 오른쪽 입력을 둘 다 본 칸입니다.
양쪽 문맥을 함께 본 칸 한쪽만 본 칸 선택한 칸

bank 위의 맨 윗칸을 세 모델에서 차례로 눌러 보세요. GPT의 bank는 withdraw money를 영원히 볼 수 없습니다. ELMo의 bank는 결국 양쪽을 보지만, 그 정보는 맨 마지막 이어 붙이기에서 처음 만납니다 — 중간의 어떤 LSTM 유닛도 양쪽을 함께 본 적이 없으니, "오른쪽에 money가 있으니 왼쪽의 went to the를 이렇게 해석하자" 같은 계산은 어느 층에서도 일어나지 않습니다. BERT에서는 첫 층부터 모든 칸이 양쪽을 보고, 그 칸들이 다시 섞입니다. 논문이 5.1절에서 ELMo식 결합을 따로 두 모델로 만들지 않은 이유로 든 세 가지 — (a) 비용이 두 배, (b) 질의응답에서 오→왼 모델은 질문을 보고 답을 조건화할 수 없음, (c) 모든 층에서 양쪽을 쓰는 깊은 양방향보다 엄밀히 약함 — 가 이 그림 한 장에 들어 있습니다.

§2 왜 그냥 양방향 언어 모델을 만들 수 없는가 — "자기 자신을 본다"

그러면 GPT에서 인과 마스크를 걷어내고 양방향으로 다음 단어… 아니, 각 위치의 단어를 맞히게 학습하면 되지 않을까요? 논문 3.1절은 여기서 딱 한 문장으로 이유를 댑니다.

표준 조건부 언어 모델은 왼→오 또는 오→왼으로만 학습할 수 있다. 양방향 조건화는 각 단어가 간접적으로 "자기 자신을 보게" 해서, 여러 층으로 된 문맥에서는 모델이 목표 단어를 자명하게 예측할 수 있기 때문이다. — 논문 3.1절

"간접적으로"가 핵심입니다. 자기 자리를 가리는 마스크(대각선 마스크)를 씌워도 소용이 없습니다. 1층에서 이웃 칸 j가 xi를 읽어 두면, 2층에서 i가 그 이웃을 읽는 순간 xi가 돌아옵니다. 정답이 예측 위치까지 흘러 들어가는 경로의 수를 직접 세어 봅시다.

데모 2 · 누수 경로 계수기 — 정답이 예측 위치에 도달하는 길은 몇 개인가
층마다 "누가 누구를 볼 수 있는가"를 행렬로 두고, 입력의 정답 토큰에서 출력의 예측 위치까지 가는 경로 수를 셉니다. 경로가 1개라도 있으면 모델은 문맥을 이해하지 않고 정답을 베낄 수 있습니다. 그림의 빨간 선이 그 경로입니다.
학습 목표예측 위치 i가 맞힐 것쓸 수 있는 문맥정답 → 예측 위치 경로 수판정

L=1에서는 대각선 마스크가 통합니다(경로 0). 하지만 L=2가 되는 순간 경로가 n−1개로 튀어나오고, 층을 쌓을수록 폭발합니다 — 정확히는 ((n−1)L + (n−1)(−1)L) / n개입니다. 여기에 Transformer에는 잔차 연결이 있어서, "잔차 연결 포함"을 켜면 대각선 마스크는 L=1에서도 무너집니다 — 자기 자리의 값이 어텐션을 거치지 않고 그대로 위로 올라가니까요.

GPT의 인과 마스크는 이 문제를 맞힐 대상을 한 칸 미루는 것으로 풉니다. i번 위치는 xi+1을 맞히는데, xi+1에서 i번으로 내려오는 선은 행렬의 위쪽 삼각형이라 전부 막혀 있습니다. 대가는 오른쪽 문맥 전부입니다. BERT의 답은 방향을 바꿨습니다 — 정답을 입력에서 지운다. 입력에 xi 대신 [MASK]를 넣으면 어텐션 행렬이 꽉 차 있어도 정답이 출발할 곳이 없으니 경로는 0이고, 예측 위치는 양쪽 문맥 n−1개를 전부 씁니다. 논문은 이것을 1953년 Taylor의 클로즈(Cloze) 과제 — 빈칸 채우기 — 에서 따왔다고 밝힙니다.

How Bidirectional RNN Works에서 본 것과 같은 문제입니다. 양방향 RNN으로 언어 모델을 만들 수 없는 이유 — 역방향 상태에 정답이 들어 있는 라벨 누수 — 가 Transformer에서는 "층을 지나며 간접적으로 자기 자신을 본다"는 모양으로 다시 나타납니다. 인과 마스크(GPT)와 MLM(BERT)은 같은 누수에 대한 두 가지 답입니다: 문맥의 절반을 버리거나, 입력의 일부를 버리거나.

오른쪽 문맥은 얼마나 값어치가 있나

정답을 가리는 대가로 BERT가 얻는 것은 오른쪽 문맥입니다. 그것이 얼마나 정보를 주는지, 가장 단순한 셈법으로 재 볼 수 있습니다. 아래 데모는 신경망이 아니라 단어 개수 세기입니다 — 빈칸 하나를 두고, 같은 두 단어 분량의 문맥을 왼쪽 두 단어(GPT식)로 쓸 때와 왼쪽 하나 + 오른쪽 하나(BERT식)로 쓸 때 맞히는 비율을 말뭉치 전체에서 셉니다.

데모 3 · 빈칸 맞히기 — 문맥 두 단어, 방향만 다르다
말뭉치의 모든 단어를 한 번씩 가리고, 나머지 말뭉치에서 센 횟수로 가장 그럴듯한 단어를 고릅니다(자기 자신은 세지 않는 leave-one-out). 말뭉치는 고쳐 쓸 수 있습니다. 아래 칸에 ___를 넣은 문장을 쓰면 두 방식의 예측을 비교합니다.

품사나 관사처럼 왼쪽만 봐도 되는 단어가 있는가 하면, 주어 명사처럼 오른쪽(동사)을 봐야만 정해지는 단어가 있습니다. "the ___ barks"의 빈칸은 왼쪽 두 단어로는 다섯 동물 중 하나를 찍을 수밖에 없지만, 오른쪽 한 단어를 보면 확정됩니다. 실제 BERT는 개수를 세지 않고 512토큰 전체를 12층에 걸쳐 섞지만, 얻으려는 것은 바로 이 오른쪽에서 오는 정보입니다.

이 말뭉치는 일부러 만든 것입니다. 오른쪽 문맥이 결정적인 문장 틀을 섞어 넣었으니 차이가 과장돼 보일 수 있습니다. 말뭉치를 지우고 평범한 문장을 넣어 보면 차이가 줄어듭니다 — 그래도 뒤집히지는 않는 편인데, 오른쪽 문맥을 "추가로" 쓰는 쪽이 정보를 잃을 이유가 없기 때문입니다(여기서는 문맥 크기를 두 단어로 똑같이 묶어 공정하게 비교했습니다).

§3 입력 표현 — 세 임베딩의 합과 [CLS]·[SEP]

BERT는 사전학습과 파인튜닝에 같은 모델을 씁니다(그림 1). 그러려면 입력 형식 하나로 문장 하나(감정 분류)와 문장 쌍(질문–문단, 전제–가설)을 모두 담을 수 있어야 합니다. 논문 3절의 규칙은 네 줄입니다.

  1. WordPiece 토큰화, 어휘 30,000개. 사전에 없는 단어는 play ##ing처럼 조각으로 쪼갭니다(##은 "앞 조각에 붙는다").
  2. 모든 시퀀스의 첫 토큰은 [CLS]. 이 자리의 마지막 은닉 벡터 C ∈ ℝH를 분류용 요약으로 씁니다.
  3. 두 문장은 [SEP]로 구분하고, 모든 토큰에 문장 A인지 B인지를 나타내는 학습된 임베딩을 더합니다.
  4. 한 토큰의 입력 = 토큰 임베딩 + 세그먼트 임베딩 + 위치 임베딩. 이어 붙이지 않고 더합니다(그림 2).

여기서 "문장(sentence)"은 언어학적 문장이 아니라 연속된 텍스트 구간 아무거나이고, "시퀀스"는 BERT에 들어가는 토큰열 전체입니다. 위치 임베딩은 원래 Transformer의 사인파가 아니라 학습되는 표(512행)라서, BERT는 512토큰보다 긴 입력을 원천적으로 받을 수 없습니다.

데모 4 · 입력 조립기 — 논문 그림 2를 직접 만들기
두 문장을 넣으면 작은 WordPiece(최장 일치 우선, 논문과 같은 규칙 · 어휘는 이 페이지에 넣은 수백 개뿐)로 쪼개고 세 줄의 임베딩 인덱스를 만듭니다. 문장 B를 비우면 단일 문장 입력(text–∅ 쌍)이 됩니다.

playing이 play ##ing으로, flightless가 flight ##less로 쪼개지는 것을 보세요 — 논문 그림 2와 부록 A.1의 모습 그대로입니다. 세 임베딩 표의 크기를 보면 무게가 어디 있는지 보입니다: 토큰 30,522×768(공개 모델 기준) ≈ 23.4M, 위치 512×768 ≈ 0.39M, 세그먼트는 2×768 = 1,536개뿐입니다. 세그먼트 임베딩은 파라미터로는 거의 공짜이면서 "지금 이 토큰이 질문 쪽인지 문단 쪽인지"를 모든 층에 알려 줍니다.

왜 두 문장을 한 시퀀스에 넣나? 논문 3.2절: 문장 쌍 과제의 흔한 방식은 두 문장을 따로 인코딩한 뒤 양방향 교차 어텐션을 거는 것인데, BERT는 이어 붙인 쌍에 셀프 어텐션을 걸어 두 단계를 하나로 합칩니다. 이어 붙인 시퀀스의 셀프 어텐션 행렬 안에는 A→B, B→A 교차 어텐션이 이미 들어 있습니다(행렬의 비대각 블록 두 개).

§4 과제 1 · Masked LM — 15%와 80/10/10

규칙은 이렇습니다(3.1절). 각 시퀀스에서 WordPiece 토큰의 15%를 무작위로 골라 예측 대상으로 삼고, 그 자리의 최종 은닉 벡터 Ti를 어휘 크기 소프트맥스에 넣어 원래 토큰을 교차 엔트로피로 맞히게 합니다. 디노이징 오토인코더와 달리 입력 전체를 복원하지 않고 고른 자리만 맞힙니다.

문제는 [MASK]가 사전학습에만 있고 파인튜닝 때는 한 번도 나오지 않는다는 것입니다(사전학습–파인튜닝 불일치). 그래서 고른 토큰을 항상 [MASK]로 바꾸지 않습니다.

고른 15% 중   80% → [MASK]  ·  10% → 무작위 토큰  ·  10% → 그대로 부록 A.1의 예: my dog is hairy → my dog is [MASK] / my dog is apple / my dog is hairy
데모 5 · 마스킹 발생기 — 모델이 실제로 받는 입력
문장을 넣고 다시 뽑기를 누르세요. 파란 테두리가 예측 대상(손실이 걸리는 자리)입니다. 비율을 바꾸면 아래 통계가 해석적으로 다시 계산되고, 괄호 안 값은 10만 토큰을 실제로 뽑아 잰 값입니다. [CLS]·[SEP]는 고르지 않습니다(공개 코드와 같음).
[MASK]로 바뀜 무작위 토큰으로 바뀜 그대로 두었지만 예측 대상

기본값에서 숫자를 읽어 봅시다. 입력의 12%가 [MASK], 1.5%가 엉뚱한 단어, 1.5%는 멀쩡하지만 정답을 맞혀야 하는 자리입니다. 중요한 것은 모델의 입장입니다 — [MASK]가 아닌 토큰 88% 가운데 3.4%는 예측 대상이고, 1.7%는 거짓말입니다. 어느 것이 거짓말인지 모르니 모델은 모든 토큰에 대해 "문맥상 여기 올 단어가 이게 맞나"를 따지는 표현을 유지해야 합니다. 논문 부록 A.1의 표현으로 "which words it will be asked to predict or which have been replaced by random words"를 모르게 만드는 것이 목적이고, 무작위 교체는 전체 토큰의 1.5%뿐이라 언어 이해를 해치지 않는 것 같다고 적었습니다.

그러면 80/10/10은 얼마나 중요했을까요? 부록 C.2의 표 8이 여섯 가지 비율을 비교합니다.

데모 6 · 논문 표 8 — 마스킹 전략 절제 실험
행을 클릭하면 BERT의 80/10/10 대비 차이가 막대로 나옵니다. MNLI·NER은 파인튜닝, 마지막 열은 BERT를 얼린 채 마지막 4층을 특징으로 뽑은 특징 기반 NER입니다(Dev).
MASKSAMERNDMNLI
파인튜닝
NER
파인튜닝
NER
특징 기반

논문의 결론: 파인튜닝은 마스킹 전략에 놀랄 만큼 둔감합니다(MNLI 83.6~84.4, 폭 0.8). 차이가 드러나는 곳은 특징 기반 NER입니다. [MASK]만 쓰면(100/0/0) 94.9 → 94.0으로 가장 크게 떨어지는데, 파인튜닝이라면 [MASK]가 없는 입력에 표현을 다시 맞출 기회가 있지만 얼린 모델은 그럴 수 없어서 불일치가 그대로 드러나기 때문입니다. 반대로 [MASK]를 아예 쓰지 않고 무작위만 쓰면(0/0/100) MNLI가 83.6으로 가장 나쁩니다. 80/10/10은 두 극단 사이의 타협입니다 — 표를 자세히 보면 MNLI에서는 80/20/0이 84.4로 오히려 조금 높습니다. 차이가 작아서 "정답 비율"이라기보다 무난한 선택에 가깝습니다.

대가 — 배치의 15%에서만 배운다

왼→오 언어 모델은 모든 위치에서 다음 토큰을 맞히니 토큰마다 손실이 걸리지만, MLM은 15%에서만 걸립니다. 같은 배치에서 받는 학습 신호가 약 1/6.7이니 수렴이 느리지 않을까요? 부록 C.1(그림 5)의 답: 조금 느리게 수렴하는 것은 맞지만, 절대 정확도로는 MLM이 거의 처음부터 왼→오 모델을 앞섭니다. 그리고 BERTBASE는 100만 스텝을 학습한 것이 50만 스텝보다 MNLI에서 거의 1.0%p 높았습니다 — "그렇게 오래 학습시켜야 하나?"라는 질문에 논문이 직접 "예"라고 답한 부분입니다.

§5 과제 2 · 다음 문장 예측(NSP)

질의응답(QA)이나 자연어 추론(NLI)은 두 문장의 관계를 이해해야 하는데, 언어 모델링은 그것을 직접 가르치지 않습니다. 그래서 논문은 아무 단일 언어 말뭉치에서나 공짜로 만들 수 있는 이진 분류를 하나 더 붙였습니다.

데모 7 · 사전학습 예제 생성기 — MLM과 NSP를 한 번에
네 개의 짧은 "문서"에서 논문 절차대로 학습 예제를 만듭니다. 누를 때마다 50% 확률로 실제 다음 문장 또는 다른 문서의 문장이 B가 되고, 그 위에 데모 5와 같은 80/10/10 마스킹이 걸립니다. 모델이 받는 입력과 맞혀야 할 정답을 함께 보여 줍니다.

부록 A.1의 두 예시가 바로 이런 모양입니다 — [CLS] the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]는 IsNext, ... [SEP] penguin [MASK] are flight ##less birds [SEP]는 NotNext. 최종 모델은 NSP를 97~98% 맞힙니다(각주 5).

각주 6을 놓치지 마세요. "벡터 C는 NSP로 학습되었으므로 파인튜닝 없이는 의미 있는 문장 표현이 아니다." 사전학습된 BERT의 [CLS] 벡터를 그대로 문장 임베딩으로 쓰면 안 된다는 경고를 논문이 직접 달아 두었습니다.

NSP는 정말 도움이 됐을까요? 5.1절의 표 5는 BERTBASE와 완전히 같은 데이터·파인튜닝·하이퍼파라미터로 사전학습 과제만 바꾼 모델들을 비교합니다. 여기에는 NSP의 효과뿐 아니라, 이 논문의 핵심 주장인 양방향의 효과도 들어 있습니다.

데모 8 · 논문 표 5 — 무엇을 빼면 얼마나 잃는가
비교할 쌍을 고르세요. 막대는 과제별 차이(Dev)입니다. "LTR & No NSP"는 GPT처럼 왼→오 언어 모델로 사전학습한 모델로, 파인튜닝 때도 왼쪽만 봅니다 (풀면 불일치 때문에 오히려 나빠졌다고 논문은 적습니다).
사전학습MNLI-mQNLIMRPCSST-2SQuAD (F1)

표를 읽는 법: NSP를 빼면 QNLI(−3.5)·MNLI(−0.5)·SQuAD(−0.6)가 떨어집니다. 양방향을 빼면(No NSP → LTR) 전 과제가 떨어지고 MRPC −9.0, SQuAD −10.1이 특히 큽니다. SQuAD는 토큰마다 "여기가 답의 시작인가"를 판정하는 과제인데 왼→오 모델의 토큰 표현에는 오른쪽 문맥이 없으니 당연하다고 논문은 말합니다. 공정하게 하려고 LTR 위에 무작위 초기화 BiLSTM을 얹어 보니 SQuAD는 77.8 → 84.9로 회복됐지만 여전히 양방향 사전학습(87.9)에 못 미치고, GLUE 과제들은 오히려 나빠졌습니다. 사전학습 단계에서 얻지 못한 양방향성은 나중에 붙여서 메워지지 않는다는 뜻입니다.

나중 이야기. NSP의 효과는 이후 연구에서 뒤집혔습니다. RoBERTa(Liu et al., 2019)는 NSP를 빼고 한 문서에서 연속된 문장들로 512토큰을 채우는 편이 같거나 더 좋다고 보고했고, ALBERT(Lan et al., 2019)는 NotNext의 B가 다른 문서에서 오기 때문에 NSP가 문장 관계보다 주제가 바뀌었는지를 맞히는 쉬운 과제가 된다고 보고 순서 예측(SOP)으로 바꿨습니다. 데모 7에서 NotNext 예제를 몇 개 만들어 보면 주제가 확 바뀌는 것이 눈에 보입니다 — 97~98%라는 높은 정확도의 한 이유입니다.

§6 모델 크기 — 110M과 340M은 어디에 있나

논문은 층 수를 L, 은닉 크기를 H, 어텐션 헤드 수를 A로 적고 두 크기를 주로 보고합니다. FFN 크기는 항상 4H입니다(각주 3). 활성함수는 ReLU가 아니라 GPT를 따라 GELU이고(부록 A.2), 블록 자체는 원래 Transformer 인코더 그대로입니다.

LHAFFN논문 표기
BERTBASE12768123072110M
BERTLARGE241024164096340M
(참고) Transformer 논문의 가장 큰 모델61024164096인코더 100M (5.2절)
데모 9 · 파라미터 계산기 — 110M · 340M 재현, 그리고 표 6
층 하나 = 어텐션 4H²+4H · FFN 8H²+5H · LayerNorm 2개 4H = 12H² + 13H. 여기에 임베딩(토큰 V·H + 위치 512·H + 세그먼트 2·H + LN 2H)과 [CLS] 풀러(H²+H)를 더합니다. 어휘 V는 공개 영어 uncased 모델의 30,522입니다(논문은 "30,000").

BASE는 109.48M, LARGE는 335.14M이 나옵니다(논문의 110M·340M은 반올림). 여기서 두 가지를 볼 수 있습니다.

5.2절의 표 6은 크기만 바꿔 가며 같은 절차로 학습한 모델 6개를 비교합니다(파인튜닝 5회 평균, Dev). 파라미터 열은 위 계산기로 센 값입니다.

LHA파라미터 (계산)MLM pplMNLI-mMRPCSST-2

커질수록 모든 과제에서 엄격하게 좋아집니다 — 학습 예제가 3,600개뿐이고 사전학습 과제와 전혀 다른 MRPC에서도요. 논문은 이것을 "충분히 사전학습되었다면 극단적인 모델 크기로의 확장이 아주 작은 과제에서도 큰 개선으로 이어진다는 것을 설득력 있게 보인 첫 연구"라고 적습니다. 이전의 특징 기반 연구들(ELMo 2→4층, context2vec 200→600→1000차원)은 크기를 키워도 효과가 섞이거나 멈췄는데, 논문은 그 차이를 파인튜닝에서 찾습니다 — 새로 배우는 파라미터가 아주 적으면 작은 데이터로도 큰 표현을 활용할 수 있다는 가설입니다.

표 6의 숨은 비교 한 쌍. 2행(6, 768, 3)과 3행(6, 768, 12)은 파라미터가 66.96M으로 완전히 같습니다. 헤드 수만 다른데 MLM 퍼플렉시티가 5.24 → 4.68, MNLI가 80.6 → 81.9로 달라집니다. 같은 무게를 여러 개의 작은 헤드로 나누는 것 자체가 이득이라는 증거입니다.

§7 사전학습 레시피 — 33억 단어, 100만 스텝, 그리고 128/512

항목논문 값 (3.1절 · 부록 A.2)
말뭉치BooksCorpus 8억 단어 + 영어 위키백과 25억 단어(본문만 — 목록·표·제목 제외). 긴 연속 구간이 필요하므로 문장을 섞은 말뭉치(Billion Word)가 아니라 문서 단위 말뭉치가 필수
배치256 시퀀스 × 512 토큰 = "128,000 토큰/배치" (정확히는 131,072)
스텝1,000,000 스텝 ≈ 33억 단어 말뭉치의 약 40 에폭
옵티마이저Adam, lr 1e-4, β₁=0.9, β₂=0.999, L2 가중치 감쇠 0.01, 처음 10,000스텝 워밍업 후 선형 감소
정규화모든 층 드롭아웃 0.1 · 활성함수 GELU
하드웨어BASE: Cloud TPU 4개(칩 16개) · LARGE: Cloud TPU 16개(칩 64개) · 각각 4일
길이 스케줄어텐션이 길이의 제곱이라 긴 시퀀스가 불균형하게 비싸므로, 스텝의 90%는 길이 128로, 나머지 10%는 512로 학습해 위치 임베딩을 익힘

마지막 행이 흥미롭습니다. 논문은 "어텐션이 제곱이라서" 길이 128로 줄였다고 설명하는데, 실제로 절약된 계산의 대부분이 제곱 항에서 왔을까요? 토큰 하나를 한 층에 통과시키는 비용을 둘로 나눠 계산해 봅시다 — 선형 변환(Q·K·V·O와 FFN)은 토큰당 24H² FLOPs로 길이와 무관하고, 어텐션 점수와 가중합(QKᵀ, AV)만 토큰당 4nH로 길이 n에 비례합니다.

데모 10 · 사전학습 예산 계산기 — 128/512 스케줄은 무엇을 아꼈나
전 구간 512로 학습했을 때와 비교합니다. 논문은 길이 128 구간의 배치 크기를 명시하지 않았으므로 256 시퀀스를 유지한다고 가정합니다(바꿔 볼 수 있습니다). 워드피스 수와 단어 수는 논문처럼 같다고 봅니다.

기본값에서 스케줄 전체의 계산량은 전 구간 512의 약 31%(약 3.2배 절약)입니다. 그런데 이 중 제곱 항 몫은 작습니다 — H=768에서 어텐션의 제곱 부분은 길이 512에서도 층 계산의 10%, 길이 128에서는 2.7%뿐이라, 토큰 하나당 비용 차이는 1.08배에 불과합니다. 절약의 대부분은 한 스텝에 처리하는 토큰 수 자체가 4분의 1이 된 데서 옵니다.

"40 에폭"은 전 구간 512를 가정한 수입니다. 256 × 512 × 1,000,000 ÷ 33억 ≈ 39.7로 논문의 "approximately 40 epochs"와 맞습니다. 하지만 90%를 길이 128로(배치 256 그대로) 돌렸다면 처리한 토큰은 약 426억 개로 약 13 에폭이 됩니다. 논문의 두 문장을 같이 읽으면 생기는 틈이고, 실제 공개 코드의 길이별 배치 설정에 따라 값이 달라집니다 — 데모의 "128 구간 배치"를 1024로 올리면 다시 40 에폭 근처가 됩니다.

§8 파인튜닝 — 출력층 하나로 11개 과제

사전학습에 비하면 파인튜닝은 싸다고 논문은 말합니다. 논문의 모든 결과는 같은 사전학습 모델에서 출발해 Cloud TPU 한 대로 최대 1시간, GPU로는 몇 시간이면 재현됩니다(SQuAD 모델은 TPU 한 대로 약 30분에 Dev F1 91.0). 과제마다 바뀌는 것은 입력을 채우는 법과 맨 위의 출력층뿐입니다.

데모 11 · 과제별 머리 — 새로 배우는 파라미터는 몇 개인가 (논문 그림 4)
과제를 고르면 입력 배치와 어느 출력 벡터가 쓰이는지, 그리고 무작위로 초기화되어 처음부터 배워야 하는 파라미터 수가 나옵니다. 나머지 109.48M은 사전학습 값에서 출발합니다.

MNLI에서 새로 배우는 것은 W ∈ ℝK×H, 3 × 768 = 2,304개 — 전체의 0.002%입니다. 손실은 log(softmax(CWᵀ)). SQuAD는 시작 벡터 S와 끝 벡터 E 두 개(1,536개)뿐이고, SWAG은 벡터 하나(768개)입니다. 네 개의 (문장, 선택지) 쌍을 각각 BERT에 넣어 C와의 내적으로 점수를 내고 네 점수를 소프트맥스합니다. 논문이 "과제별로 크게 설계한 구조가 필요 없어진다"고 말할 때 가리키는 것이 이 숫자들입니다.

SQuAD — 시작 벡터와 끝 벡터로 답의 구간 찾기

SQuAD v1.1은 질문과 위키백과 문단이 주어지면 문단 안에서 답이 되는 구간을 찾는 과제입니다(4.2절). 질문은 A, 문단은 B 임베딩으로 한 시퀀스에 넣고,

Pistart = eS·Ti / Σj eS·Tj   ·   구간 점수(i, j) = S·Ti + E·Tj,   j ≥ i 학습 목표는 정답 시작·끝 위치의 로그 우도 합. v2.0에서는 답이 없을 때 시작·끝을 [CLS]로 두고, snull = S·C + E·C와 비교
데모 12 · 구간 점수기 — 시작·끝 소프트맥스와 "답 없음" 판정
각 토큰의 S·Ti, E·Tj 값은 설명을 위해 손으로 넣은 가상의 로짓입니다(실제 모델 출력 아님). 계산 규칙은 논문 그대로입니다 — 두 소프트맥스는 독립이고, 구간은 j ≥ i인 것 중 최고 점수를 고릅니다. v2.0을 켜면 [CLS]가 후보에 들어오고 임계값 τ와 비교합니다.
순위구간텍스트S·Ti + E·Tj

"답이 없는 질문"으로 바꾸고 v2.0을 켜 보세요. 문단 안의 최고 구간 점수 ŝi,j가 snull + τ보다 크지 않으면 "답 없음"을 냅니다. τ는 Dev 세트에서 F1이 최대가 되도록 고른 값입니다(4.3절). v2.0 모델에는 TriviaQA를 쓰지 않았고 2 에폭 · lr 5e-5 · 배치 48로 학습했습니다. v1.1 쪽은 TriviaQA로 먼저 파인튜닝한 뒤 SQuAD로 다시 파인튜닝하는 "약간의 데이터 증강"을 썼는데, 빼도 F1이 0.1~0.4만 떨어진다고 적었습니다.

§9 결과 — GLUE · SQuAD · SWAG · 특징 추출

초록의 숫자: 11개 과제에서 최고 기록, GLUE 80.5(+7.7%p), MultiNLI 86.7%(+4.6%p), SQuAD v1.1 Test F1 93.2(+1.5), SQuAD v2.0 Test F1 83.1(+5.1). GLUE는 모든 과제에서 배치 32 · 3 에폭, lr은 {5e-5, 4e-5, 3e-5, 2e-5} 중 Dev 최고. LARGE는 작은 데이터에서 파인튜닝이 가끔 불안정해서 여러 번 무작위 재시작(같은 체크포인트, 다른 셔플·분류층 초기화)해 Dev 최고를 골랐습니다.

데모 13 · 논문 표 1 — GLUE 테스트 결과
위 표는 논문 표 1 그대로(QQP·MRPC는 F1, STS-B는 스피어만, 나머지는 정확도). 아래 막대는 고른 비교의 과제별 차이이고, 과제는 학습 데이터가 큰 순으로 정렬했습니다.

BERTBASE와 GPT는 어텐션 마스크를 빼면 구조가 거의 같습니다(4.1절). 그런데도 평균이 75.1 → 79.6으로 오릅니다. 물론 GPT와의 차이가 마스크 하나만은 아닙니다 — 부록 A.4가 직접 나열하듯 BERT는 말뭉치가 더 크고(위키백과 추가), 배치가 4배(128,000 대 32,000 단어)이며, [CLS]·[SEP]·세그먼트 임베딩을 사전학습 때부터 배우고, 과제별로 lr을 골랐습니다. 그래서 논문은 데모 8의 표 5로 이 차이들을 통제한 LTR 모델과 비교해 "개선의 대부분은 두 사전학습 과제와 그것이 가능하게 한 양방향성에서 온다"고 주장합니다. 그리고 LARGE − BASE 막대를 보면 논문의 또 다른 관찰 — 데이터가 작은 과제일수록(CoLA 8.5k, RTE 2.5k) 큰 모델의 이득이 크다 — 이 보입니다.

SQuAD와 SWAG

SQuAD v1.1 (표 2)Dev F1Test F1
사람–91.2
리더보드 1위 앙상블 (nlnet)–91.7
BERTBASE (단일)88.5–
BERTLARGE (단일)90.9–
BERTLARGE (단일 + TriviaQA)91.191.8
BERTLARGE (앙상블 + TriviaQA)92.293.2
SQuAD v2.0 (표 3) · SWAG (표 4)Test
v2.0 이전 최고 (단일, MIR-MRC)F1 78.0
v2.0 BERTLARGE (단일)F1 83.1
v2.0 사람F1 89.5
SWAG ESIM+ELMo59.2
SWAG OpenAI GPT78.0
SWAG BERTLARGE86.3
SWAG 사람 (전문가 / 5인)85.0 / 88.0

SQuAD v1.1에서 BERT 단일 모델(91.8)이 리더보드 1위 앙상블(91.7)을 넘었고, SWAG에서는 ESIM+ELMo를 +27.1%p, GPT를 +8.3%p 앞섰습니다. BERT 앙상블은 사전학습 체크포인트와 파인튜닝 시드를 달리한 7개 시스템입니다.

얼려 두고 특징만 뽑아도 되나 — 표 7

5.3절은 파인튜닝 대신 ELMo처럼 BERT를 얼리고 층의 활성값만 뽑아 쓰는 방식도 시험합니다. 모든 과제를 Transformer 인코더로 표현할 수는 없고, 비싼 표현을 한 번 계산해 두고 싼 모델로 실험을 여러 번 돌리는 계산상의 이점도 있기 때문입니다. CoNLL-2003 NER에서 뽑은 특징을 무작위 초기화 2층 768차원 BiLSTM에 넣었습니다.

BERTBASE에서 무엇을 뽑았나Dev F1해석
임베딩 층만91.0문맥 없는 벡터 — word2vec과 같은 처지
마지막 은닉층94.9MLM에 특화된 맨 위층은 최선이 아니다
끝에서 두 번째 은닉층95.6마지막 층보다 낫다
12층 전부 가중합95.5
마지막 4층 가중합95.9
마지막 4층 이어 붙이기96.1특징 기반 최고 — 파인튜닝과 0.3 차이
(비교) 파인튜닝 BASE / LARGE96.4 / 96.6Test 92.4 / 92.8

§10 정리 — 한 장 요약

질문답
BERT의 구조는 새로운가아니다. 원래 Transformer 인코더 그대로(Post-LN, GELU, 학습되는 위치 임베딩). BASE는 GPT와 같은 크기로 맞췄다
GPT와의 구조 차이어텐션 마스크 한 장 — GPT는 왼쪽만, BERT는 양쪽
ELMo와의 차이ELMo는 따로 학습한 두 방향을 마지막에 이어 붙인다(얕은 결합). BERT는 모든 층에서 양쪽을 함께 본다
왜 양방향 LM이 안 되나층이 2개만 돼도 정답이 이웃을 거쳐 돌아온다("자기 자신을 본다") — 경로 수 ((n−1)L + (n−1)(−1)L)/n
MLM15%를 골라 80% [MASK] · 10% 무작위 · 10% 그대로. 모델은 어느 토큰이 거짓말인지 모르므로 모든 토큰의 문맥 표현을 유지해야 한다
80/10/10의 효과파인튜닝에는 거의 무관(MNLI 폭 0.8). 특징 기반에서 [MASK]만 쓰면 NER 94.9 → 94.0
NSP50% 진짜 다음 / 50% 무작위. QNLI −3.5 등 도움이 됐다고 보고 — 이후 RoBERTa·ALBERT가 반론
크기BASE 109.48M(임베딩 21.8%) · LARGE 335.14M. 커질수록 작은 과제에서도 엄격하게 좋아진다
파인튜닝이 새로 배우는 것MNLI 2,304개 · SQuAD 1,536개 · SWAG 768개. 나머지는 전부 사전학습 값에서 출발
128/512 스케줄계산 약 3.2배 절약 — 대부분은 제곱 항이 아니라 스텝당 토큰 수가 줄어서

BERT · GPT · ELMo 한 장 비교 (부록 A.4)

BERTOpenAI GPTELMo
몸통Transformer 인코더Transformer 디코더(인과 마스크)LSTM 두 개(→, ←)
방향깊은 양방향왼→오얕은 양방향(이어 붙이기)
사전학습 목표MLM + NSP다음 토큰 예측두 방향 LM 각각
하위 과제에 쓰는 법파인튜닝파인튜닝특징 기반
말뭉치BooksCorpus + 위키백과 (33억 단어)BooksCorpus (8억 단어)—
배치 × 스텝128,000 단어 × 1M32,000 단어 × 1M—
[CLS]·[SEP]·세그먼트사전학습 때부터 학습파인튜닝 때 처음 도입—
잘하는 것이해(분류·태깅·추출형 QA)생성—

Transformer 자료의 마지막 표에서 "인코더 셀프 어텐션만 남기면 BERT, 마스크 셀프 어텐션만 남기면 GPT"라고 적었습니다. BERT 논문은 그 갈림길에서 인코더 쪽을 고르고, 그 선택이 가능하도록 학습 과제를 새로 만든 논문입니다. 대신 BERT는 MLM으로 학습했으니 GPT처럼 한 토큰씩 이어 쓰는 생성은 자연스럽지 않습니다 — 이해와 생성이라는 두 갈래가 여기서 갈라졌습니다.

§11 이해도 퀴즈