Skip to main content

BERT — Bidirectional Encoder Representations from Transformers

BERT는 2018년 Google이 발표한 양방향 인코더 모델로, NLP의 사전학습 패러다임을 본격적으로 열었습니다. 발표 당시 11개 NLP 벤치마크에서 SOTA(State-of-the-Art)를 달성하며, 사전학습 후 Fine-tuning이라는 접근법을 NLP의 표준으로 확립했습니다.

핵심 아이디어

기존 언어 모델(ELMo, GPT-1)은 좌에서 우로(left-to-right) 또는 좌우를 독립적으로 학습하는 방식이었습니다. BERT는 **양방향 컨텍스트(bidirectional context)**를 동시에 학습하여, 단어의 의미를 문맥 전체에서 파악합니다. 핵심 차이: GPT는 다음 토큰을 예측하지만, BERT는 문장 중간의 가려진 토큰을 양쪽 문맥을 모두 사용하여 예측합니다.

아키텍처 상세

BERT는 Transformer의 인코더(Encoder) 블록만 사용합니다.
구성 요소BERT-BaseBERT-Large
Transformer 레이어 (L)1224
Hidden 차원 (H)7681024
Attention Head 수 (A)1216
파라미터 수110M340M
최대 시퀀스 길이512512

입력 표현 (Input Representation)

BERT의 입력은 세 가지 임베딩의 합으로 구성됩니다.
  • Token Embedding: WordPiece 토크나이저로 분리된 각 토큰의 임베딩
  • Segment Embedding: 첫 번째 문장(A)과 두 번째 문장(B)을 구분하는 임베딩
  • Position Embedding: 학습 가능한(learned) 위치 임베딩 (최대 512)
특수 토큰:
  • [CLS]: 문장의 시작. 이 토큰의 최종 Hidden State를 분류 태스크에 사용합니다.
  • [SEP]: 문장 사이의 구분자. 두 문장을 하나의 입력으로 연결할 때 사용합니다.
  • [MASK]: MLM에서 가려진 토큰 위치를 나타냅니다.

사전학습 목표 (Pre-training Objectives)

BERT는 두 가지 사전학습 목표를 동시에 학습합니다.

1. Masked Language Model (MLM)

입력 토큰의 15%를 무작위로 선택하고, 해당 위치의 토큰을 예측하는 것이 목표입니다. 선택된 15% 토큰의 처리 방식:
  • 80%: [MASK] 토큰으로 대체 → "I love [MASK]""NLP" 예측
  • 10%: 무작위 토큰으로 대체 → "I love apple""NLP" 예측
  • 10%: 변경하지 않음 → "I love NLP""NLP" 확인
이 전략은 Fine-tuning 시 [MASK] 토큰이 없는 환경과의 괴리(mismatch)를 줄이기 위해 설계되었습니다. MLM 손실 함수: LMLM=iMlogP(xix\M)\mathcal{L}_{\text{MLM}} = -\sum_{i \in \mathcal{M}} \log P(x_i \mid \mathbf{x}_{\backslash \mathcal{M}}) 여기서 M\mathcal{M}은 마스킹된 토큰의 위치 집합이고, x\M\mathbf{x}_{\backslash \mathcal{M}}은 마스킹되지 않은 나머지 토큰입니다.

2. Next Sentence Prediction (NSP)

두 문장이 연속된 문장인지 예측하는 이진 분류 태스크입니다.
입력레이블
[CLS] 오늘 날씨가 좋다 [SEP] 산책을 나가자 [SEP]IsNext
[CLS] 오늘 날씨가 좋다 [SEP] 주식이 올랐다 [SEP]NotNext
학습 데이터의 50%는 실제 연속 문장, 50%는 무작위 문장 쌍으로 구성됩니다. [CLS] 토큰의 출력 벡터에 분류 헤드를 달아 예측합니다.
참고: 후속 연구(RoBERTa)에서 NSP는 성능 향상에 기여하지 않거나 오히려 방해가 될 수 있다는 결과가 나왔습니다. 자세한 내용은 RoBERTa, ALBERT, DeBERTa 문서에서 다룹니다.

사전학습 데이터 및 설정

항목
학습 데이터BooksCorpus (800M 단어) + English Wikipedia (2,500M 단어)
배치 크기256 시퀀스
학습 스텝1,000,000 (약 40 에폭)
옵티마이저Adam (lr=1e-4, warmup 10,000 스텝)
학습 시간4일 (TPU v3 Pod 16칩, BERT-Base 기준)

Fine-tuning 전략

BERT의 가장 큰 강점은 다양한 다운스트림 태스크에 쉽게 적용할 수 있다는 것입니다. 사전학습된 BERT 위에 간단한 출력 레이어를 추가하고, 전체 모델을 태스크 데이터로 미세 조정합니다.

Fine-tuning 하이퍼파라미터 권장 값

하이퍼파라미터권장 범위
학습률 (Learning Rate)2e-5, 3e-5, 5e-5
배치 크기16, 32
에폭 수2~4
Warmup 비율학습 스텝의 10%
Weight Decay0.01

구현 예제

HuggingFace Transformers를 사용하여 BERT로 텍스트 분류를 수행하는 예제입니다.

Masked Language Model 추론

from transformers import BertTokenizer, BertForMaskedLM
import torch

# 모델과 토크나이저 로드
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model = BertForMaskedLM.from_pretrained("bert-base-uncased")
model.eval()

# 마스킹된 문장 입력
text = "The capital of France is [MASK]."
inputs = tokenizer(text, return_tensors="pt")

# 예측 수행
with torch.no_grad():
    outputs = model(**inputs)
    predictions = outputs.logits

# [MASK] 위치의 상위 5개 예측 토큰
mask_index = (inputs["input_ids"] == tokenizer.mask_token_id).nonzero(as_tuple=True)[1]
top_5 = torch.topk(predictions[0, mask_index, :], 5, dim=-1)

print("입력:", text)
print("상위 5개 예측:")
for i, (token_id, score) in enumerate(zip(top_5.indices[0], top_5.values[0])):
    token = tokenizer.decode(token_id)
    print(f"  {i+1}. {token} (점수: {score:.4f})")

Fine-tuning: 텍스트 분류

from transformers import BertTokenizer, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
from datasets import load_dataset

# 데이터셋 로드 (IMDB 감성 분류)
dataset = load_dataset("imdb")
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")

# 토큰화 함수
def tokenize_fn(examples):
    """텍스트를 BERT 입력 형식으로 토큰화합니다."""
    return tokenizer(
        examples["text"],
        padding="max_length",
        truncation=True,
        max_length=256,
    )

tokenized = dataset.map(tokenize_fn, batched=True)

# 모델 초기화 (이진 분류)
model = BertForSequenceClassification.from_pretrained(
    "bert-base-uncased",
    num_labels=2,
)

# 학습 설정
training_args = TrainingArguments(
    output_dir="./results",
    num_train_epochs=3,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=32,
    learning_rate=2e-5,
    weight_decay=0.01,
    warmup_ratio=0.1,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
)

# Trainer로 학습 실행
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized["train"],
    eval_dataset=tokenized["test"],
)

trainer.train()

Feature Extraction (임베딩 추출)

from transformers import BertTokenizer, BertModel
import torch

tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased")
model.eval()

# 문장 인코딩
text = "BERT produces contextualized embeddings."
inputs = tokenizer(text, return_tensors="pt")

with torch.no_grad():
    outputs = model(**inputs)

# [CLS] 토큰의 Hidden State (문장 표현)
cls_embedding = outputs.last_hidden_state[:, 0, :]  # shape: (1, 768)

# 전체 토큰의 Hidden State
all_embeddings = outputs.last_hidden_state  # shape: (1, seq_len, 768)

# 평균 풀링으로 문장 임베딩 생성
# attention_mask를 사용하여 패딩 토큰 제외
mask = inputs["attention_mask"].unsqueeze(-1).float()
mean_embedding = (outputs.last_hidden_state * mask).sum(dim=1) / mask.sum(dim=1)

print(f"[CLS] 임베딩 차원: {cls_embedding.shape}")
print(f"평균 풀링 임베딩 차원: {mean_embedding.shape}")

관련 기술 비교

모델방향성사전학습 목표주요 용도
ELMo (2018)양방향 (독립적)양방향 LMFeature 추출
GPT-1 (2018)단방향 (좌→우)Autoregressive LM생성, Fine-tuning
BERT (2018)양방향 (동시)MLM + NSP이해, 분류, 추출
XLNet (2019)순열 기반 양방향Permutation LM이해 + 생성
BERT는 ELMo의 양방향 아이디어와 GPT-1의 Fine-tuning 접근법을 결합하여, 두 모델의 장점을 취한 아키텍처입니다.

BERT의 한계

  1. 고정 길이 제한: 최대 512 토큰까지만 처리 가능합니다. 긴 문서 처리에 한계가 있습니다.
  2. [MASK] 토큰 불일치: 사전학습 시 사용하는 [MASK]가 Fine-tuning에는 없어 미스매치가 발생합니다.
  3. 토큰 독립 가정: MLM에서 마스킹된 토큰들이 서로 독립이라고 가정하지만 실제로는 상관관계가 있을 수 있습니다.
  4. NSP의 효과: 후속 연구에서 NSP가 불필요하거나 해로울 수 있다는 결과가 보고되었습니다.
이러한 한계를 극복하기 위한 후속 모델은 RoBERTa, ALBERT, DeBERTa에서 다룹니다.
WordPiece는 BPE(Byte Pair Encoding)의 변형으로, 빈도가 아닌 우도(likelihood)를 기준으로 서브워드를 병합합니다. "playing"["play", "##ing"]으로 분리하며, ## 접두사는 이전 토큰에 이어지는 서브워드임을 나타냅니다. 어휘 크기는 30,522개입니다.
BERT의 [CLS] 토큰은 NSP 목표에 최적화되어 있어, 범용 문장 임베딩으로는 부적합할 수 있습니다. 문장 유사도 태스크에는 Sentence-BERT(SBERT)처럼 전용으로 학습된 모델을 사용하거나, 평균 풀링(mean pooling)을 적용하는 것이 더 나은 결과를 보입니다.
BERT는 양방향 모델이므로 자기회귀(autoregressive) 텍스트 생성에는 적합하지 않습니다. 생성이 필요하다면 GPT 계열(디코더 모델)이나 T5(인코더-디코더 모델)를 사용하는 것이 적절합니다. 다만, BERT의 MLM 헤드를 활용한 제한적인 빈칸 채우기는 가능합니다.

참고 논문

논문저자연도핵심 기여
BERT: Pre-training of Deep Bidirectional Transformers for Language UnderstandingDevlin et al.2018MLM + NSP 기반 양방향 사전학습
Attention Is All You NeedVaswani et al.2017Transformer 아키텍처 (BERT의 기반)
Deep contextualized word representations (ELMo)Peters et al.2018문맥 의존적 임베딩의 시초