Skip to main content

한국어 PLM — 한국어 사전학습 인코더 모델

영어 중심으로 발전한 BERT 계열 모델을 한국어에 직접 적용하면 성능이 크게 떨어집니다. 한국어는 교착어(agglutinative language)로서 조사, 어미 변화, 띄어쓰기 불일치 등 고유한 언어적 특성이 있기 때문입니다. 이 문서에서는 한국어에 특화된 주요 사전학습 인코더 모델을 비교하고 실습합니다.

학습 목표

이 문서를 완료하면 다음을 할 수 있습니다.
  • 한국어 PLM의 필요성과 영어 모델 대비 장점을 설명할 수 있습니다
  • KoBERT, KoELECTRA, KLUE-BERT, KR-BERT의 차이를 구분할 수 있습니다
  • HuggingFace를 사용하여 한국어 PLM을 로드하고 추론할 수 있습니다
  • KLUE 벤치마크의 구성과 평가 방식을 이해합니다

왜 중요한가

한국어 NLP 실무에서 모델 선택은 성능에 직접적인 영향을 미칩니다.
  1. 한국어 특수성 반영: 한국어 토크나이저, 한국어 코퍼스로 학습된 모델이 더 나은 성능을 보입니다
  2. 실무 선택 기준: 한국어 벤치마크(KLUE) 기반의 객관적 비교가 가능합니다
  3. 생태계 이해: 한국 AI 연구 생태계(SKT, ETRI, KAIST 등)의 기여를 파악합니다

핵심 개념

한국어 NLP의 과제

과제설명예시
교착어 특성조사/어미가 어근에 결합하여 다양한 형태 생성”먹었다”, “먹겠니”, “먹었을까”
띄어쓰기 불일치같은 문장도 띄어쓰기가 다를 수 있음”나는 학생이다” vs “나는학생이다”
형태소 분석 필요어절 단위로는 의미 파악이 어려움”먹었다” → “먹” + “었” + “다”
학습 데이터 부족영어 대비 고품질 학습 데이터가 제한적영어 Wikipedia >> 한국어 Wikipedia
다양한 문체구어체, 문어체, 신조어 등 변이가 큼”ㅋㅋ”, “ㄱㄱ”, “갓생”

KoBERT (SKT, 2019)

SK텔레콤이 공개한 최초의 한국어 BERT 모델입니다.
항목
발표2019, SKT
기반 모델BERT-Base
토크나이저SentencePiece (8,002 vocab)
학습 데이터한국어 위키백과 (약 5,400만 문장)
파라미터92M
특징최초 공개 한국어 BERT, 한국어 SentencePiece 적용
장점: 한국어 NLP의 시작점으로, 많은 후속 연구의 기반이 되었습니다. 한계: 어휘 크기(8,002)가 작아 OOV(Out-of-Vocabulary) 토큰이 많고, 학습 데이터가 위키백과에 한정됩니다.

KoELECTRA (monologg, 2020)

ELECTRA 아키텍처를 한국어에 적용한 모델입니다. ELECTRA는 MLM 대신 **Replaced Token Detection(RTD)**을 사용하여 더 효율적으로 학습합니다.
항목
발표2020, monologg (박장원)
기반 모델ELECTRA
토크나이저WordPiece (35,000 vocab)
학습 데이터34GB (뉴스, 위키, 나무위키 등)
파라미터Base: 110M, Small: 14M
특징RTD 목표 함수, 모든 토큰에서 학습

ELECTRA의 학습 방식

ELECTRA의 핵심 장점은 모든 토큰에서 학습 신호를 받는다는 것입니다. BERT의 MLM은 마스킹된 15%의 토큰에서만 학습하지만, ELECTRA의 RTD는 100%의 토큰에서 원본/대체 여부를 판별하여 학습합니다.

KLUE-BERT / KLUE-RoBERTa (KLUE, 2021)

KAIST 등 한국 주요 연구기관이 공동으로 구축한 KLUE(Korean Language Understanding Evaluation) 벤치마크와 함께 공개된 베이스라인 모델입니다.
항목KLUE-BERTKLUE-RoBERTa
발표2021, KLUE Consortium
기반 모델BERT-BaseRoBERTa-Large
토크나이저Morpheme-aware WordPiece (32,000)Morpheme-aware BPE (32,000)
학습 데이터62GB (모두의 말뭉치 + 뉴스 + 위키 등)
파라미터110M337M
특징KLUE 벤치마크 공식 베이스라인

KLUE 벤치마크

KLUE는 한국어 NLU(Natural Language Understanding)를 평가하기 위한 8개 태스크로 구성됩니다.
태스크유형설명평가 지표
TC (Topic Classification)문장 분류뉴스 주제 분류 (7개 카테고리)Macro F1
STS (Semantic Textual Similarity)문장 쌍두 문장의 의미 유사도 (0~5)Pearson’s r
NLI (Natural Language Inference)문장 쌍전제-가설 관계 (함의/모순/중립)Accuracy
NER (Named Entity Recognition)토큰 분류개체명 인식 (6개 유형)Entity-level F1
RE (Relation Extraction)문장 분류두 개체 간 관계 추출 (30개 유형)Micro F1
DP (Dependency Parsing)구조 예측의존 구문 분석UAS / LAS
MRC (Machine Reading Comprehension)추출형 QA지문에서 답 구간 추출EM / ROUGE-W
DST (Dialogue State Tracking)대화 이해대화에서 슬롯-값 추출JGA / Slot F1

KR-BERT (SNU, 2020)

서울대학교에서 공개한 모델로, 한국어 특성에 맞는 문자 수준(character-level) 토크나이저를 사용합니다.
항목
발표2020, 서울대학교
기반 모델BERT-Base
토크나이저Character-level + WordPiece (16,424 vocab)
학습 데이터23GB (위키, 뉴스, 댓글)
특징한글 자모 분리, 오타/신조어에 강건
KR-BERT는 한글 자모(ㄱ, ㅏ 등)를 활용하여 미등록어(OOV) 문제를 완화합니다. “먹었다”를 “ㅁㅓㄱㅇㅓㅆㄷㅏ”로 분리하여 처리할 수 있어, 신조어나 오타가 많은 소셜 미디어 텍스트에서 강점을 보입니다.

한국어 PLM 종합 비교

모델파라미터어휘 크기학습 데이터KLUE NLIKLUE NER추천 용도
KoBERT92M8,0025GB--경량 프로토타입
KoELECTRA-Base110M35,00034GB82.787.2균형잡힌 성능
KLUE-BERT110M32,00062GB81.686.3공식 벤치마크
KLUE-RoBERTa-Large337M32,00062GB89.088.5최고 성능
KR-BERT110M16,42423GB--소셜 미디어 텍스트

어떤 모델을 선택해야 할까?

상황추천 모델이유
한국어 NLU 최고 성능KLUE-RoBERTa-LargeKLUE 벤치마크 최고 점수
파라미터 효율적 학습KoELECTRA-Small/BaseRTD로 효율적 학습, 좋은 성능
소셜 미디어 / 비정형 텍스트KR-BERT자모 분리로 오타/신조어 강건
빠른 프로토타이핑KoBERT가볍고 많은 예제 코드
연구 / 공정한 비교KLUE-BERT공식 벤치마크 베이스라인

HuggingFace 실습

모델 로드 및 Masked LM 추론

from transformers import AutoTokenizer, AutoModelForMaskedLM
import torch

# KLUE-BERT로 Masked LM 추론
model_name = "klue/bert-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForMaskedLM.from_pretrained(model_name)
model.eval()

# 마스킹된 문장
text = "오늘 날씨가 정말 [MASK]."
inputs = tokenizer(text, return_tensors="pt")

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

# [MASK] 위치 예측
mask_idx = (inputs["input_ids"] == tokenizer.mask_token_id).nonzero(as_tuple=True)[1]
top_5 = torch.topk(outputs.logits[0, mask_idx, :], 5, dim=-1)

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

텍스트 분류 (감성 분석)

from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import Trainer, TrainingArguments
from datasets import Dataset
import torch

# KoELECTRA로 감성 분류
model_name = "monologg/koelectra-base-v3-discriminator"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=2,  # 긍정/부정
)

# 예시 데이터셋 구성
train_data = {
    "text": [
        "이 영화 정말 재미있었어요!",
        "배우들의 연기가 훌륭합니다.",
        "시간 낭비였어요. 별로입니다.",
        "스토리가 너무 지루해서 잠이 왔어요.",
    ],
    "label": [1, 1, 0, 0],  # 1: 긍정, 0: 부정
}
dataset = Dataset.from_dict(train_data)

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

tokenized = dataset.map(tokenize_fn, batched=True)
tokenized.set_format("torch", columns=["input_ids", "attention_mask", "label"])

# 학습 설정
training_args = TrainingArguments(
    output_dir="./ko-sentiment",
    num_train_epochs=5,
    per_device_train_batch_size=4,
    learning_rate=3e-5,
    weight_decay=0.01,
    warmup_ratio=0.1,
    logging_steps=10,
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized,
)

trainer.train()

추론 파이프라인

from transformers import pipeline

# KLUE-RoBERTa를 사용한 문장 유사도
classifier = pipeline(
    "text-classification",
    model="klue/roberta-base",
    tokenizer="klue/roberta-base",
)

# 추론 테스트
texts = [
    "오늘 서울 날씨가 맑습니다.",
    "인공지능 기술이 빠르게 발전하고 있습니다.",
    "맛있는 커피를 마시며 코딩하고 있습니다.",
]

for text in texts:
    result = classifier(text)
    print(f"입력: {text}")
    print(f"예측: {result}")
    print()

개체명 인식 (NER)

from transformers import AutoTokenizer, AutoModelForTokenClassification
import torch

# KLUE-BERT NER 모델
model_name = "klue/bert-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)

# NER 태그 정의 (KLUE NER 기준)
ner_tags = ["O", "B-PS", "I-PS", "B-LC", "I-LC", "B-OG", "I-OG",
            "B-DT", "I-DT", "B-TI", "I-TI", "B-QT", "I-QT"]

model = AutoModelForTokenClassification.from_pretrained(
    model_name,
    num_labels=len(ner_tags),
)

# 문장 토큰화 및 추론
text = "삼성전자가 서울에서 AI 컨퍼런스를 개최합니다."
inputs = tokenizer(text, return_tensors="pt")

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

# 예측 태그 변환
predictions = torch.argmax(outputs.logits, dim=-1)[0]
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])

print(f"입력: {text}")
print("토큰별 NER 태그:")
for token, pred in zip(tokens, predictions):
    tag = ner_tags[pred.item()]
    if tag != "O":  # O 태그가 아닌 것만 출력
        print(f"  {token}: {tag}")

AI/ML 활용

한국어 PLM은 다양한 실무 시나리오에서 활용됩니다.
  • 고객 리뷰 분석: KoELECTRA로 한국어 리뷰의 감성 분류 및 감정 분석
  • 문서 분류: KLUE-RoBERTa로 뉴스, 법률, 의료 문서 자동 분류
  • 검색 시스템: KLUE-BERT 임베딩을 활용한 한국어 시맨틱 검색
  • 대화 시스템: 한국어 NLU(의도 분류, 개체 추출)에 PLM 적용
  • 정보 추출: 한국어 문서에서 인물, 기관, 날짜 등 개체명 자동 추출
다국어 모델도 한국어를 지원하지만, 한국어 전용 모델이 대체로 더 나은 성능을 보입니다. mBERT는 104개 언어를 동시에 학습하므로 한국어에 할당된 어휘와 학습 데이터가 제한적입니다. 다만 다국어 태스크(번역, 다국어 검색)에서는 XLM-RoBERTa가 유용할 수 있습니다.
한국어는 교착어이므로 “먹었다”를 하나의 토큰으로 처리하면 “먹다”, “먹었다”, “먹었었다”가 모두 다른 토큰이 됩니다. 형태소 기반 토크나이저는 “먹” + “었” + “다”로 분리하여 어근과 어미를 공유할 수 있게 합니다. KLUE 모델들의 Morpheme-aware 토크나이저가 이 접근을 취합니다.
KLUE-RoBERTa-Large는 337M 파라미터로 가장 큰 모델이며, RoBERTa의 검증된 학습 전략(동적 마스킹, NSP 제거, 대규모 배치)을 한국어에 적용했습니다. 또한 62GB의 고품질 한국어 코퍼스와 형태소 인식 토크나이저의 조합이 높은 성능에 기여합니다.
  1. 학습률은 2e-5 ~ 5e-5 범위에서 시작하는 것이 안전합니다. 2) 한국어 데이터는 영어보다 토큰 수가 많아질 수 있으므로 max_length를 충분히 설정합니다. 3) 형태소 분석기 버전에 따라 토크나이저 결과가 달라질 수 있으므로, 학습과 추론에서 동일한 환경을 사용해야 합니다. 4) 한국어 특유의 띄어쓰기 변형을 데이터 전처리에서 정규화하면 성능이 향상됩니다.

체크리스트

학습을 마치셨다면 아래 항목을 확인해 보세요.
  • 영어 BERT 대신 한국어 PLM을 사용해야 하는 이유를 설명할 수 있다
  • KoBERT, KoELECTRA, KLUE-BERT의 핵심 차이(토크나이저, 학습 데이터, 학습 방법)를 구분할 수 있다
  • KLUE 벤치마크의 8개 태스크를 나열하고 각각의 목적을 설명할 수 있다
  • HuggingFace로 한국어 PLM을 로드하고 추론할 수 있다
  • 태스크 특성에 따라 적합한 한국어 PLM을 선택할 수 있다