혼란도
훈련 단계와 평가 단계
언어 모형의 훈련과 최종 평가는 서로 다른 질문
| 구분 | 훈련 단계 | 평가 단계 |
|---|---|---|
| 목표 | 다음 토큰 예측 오차 최소화 | 인간의 기대와 실제 과업의 성공 정도 확인 |
| 측정 대상 | 모형의 예측 확률과 정답 토큰의 차이 | 유창성, 정확성, 일관성, 안전성 등 다면적 품질 |
| 대표 방법 | 교차 엔트로피 손실 | 자동 지표, 벤치마크, 인간 평가, 평가 기준표(rubric) |
| 활용 | 손실을 줄이는 방향으로 가중치 갱신 | 모형 비교, 오류 분석, 배포 여부 판단 |
- 훈련 손실이 낮아도 사용자가 선호하거나 사실과 일치하는 답변이 보장되지는 않음
- 내부 확률 지표와 실제 과업의 평가를 함께 확인해야
혼란도
- 혼란도(perplexity)는 언어 모형이 다음 토큰을 예측할 때 느끼는 평균적인 불확실성
- 모형이 실제 토큰에 높은 확률을 줄수록 혼란도가 낮아짐
- 낮은 혼란도: 실제 토큰의 범위를 좁혀 예측한 상태
- 높은 혼란도: 여러 토큰 사이에서 선택하기 어려운 상태
- 분기계수(branching factor)로서 혼란도: 혼란도 10의 의미는 매 시점에서 평균적으로 비슷한 후보 10개 중 하나를 고르는 정도의 불확실성
더 알아보기: 혼란도의 수학적 정의
토큰별 조건부 확률
토큰 시퀀스를 이라고 하자. 언어 모형은 앞의 토큰 가 주어졌을 때 실제 토큰 가 나타날 조건부 확률을 계산한다.
문장이 길어질수록 확률을 더 많이 곱하므로 문장 확률은 작아진다. 길이가 다른 문장을 비교하려면 토큰 수 으로 정규화해야 한다.
평균 교차 엔트로피
실제 토큰에 부여한 확률의 음의 로그를 평균하여 토큰당 손실을 계산한다.
- 실제 토큰의 확률이 높음: 가 작아짐
- 실제 토큰의 확률이 낮음: 가 커짐
혼란도
평균 교차 엔트로피에 지수 함수를 적용하면 혼란도가 된다.
마지막 식은 실제 토큰에 부여한 확률의 기하평균을 구한 뒤 역수를 취한 형태다. 자연로그를 사용하면 를 적용하고, 밑이 2인 로그를 사용하면 의 거듭제곱을 적용한다.
혼란도의 한계
- 생성 품질과 불일치 가능
- 확률이 높은 문장이 항상 정확하거나 유용한 문장은 아님
- 인간이 느끼는 유창성, 일관성, 안전성을 직접 측정하지 않음
- 토큰화 방식에 민감
- 같은 문장도 토크나이저와 어휘 크기에 따라 토큰 수와 확률이 달라짐
- 서로 다른 조건의 모형을 직접 비교하기 어려움
- 같은 테스트 말뭉치와 같은 토큰화 조건을 사용하는 비교가 원칙
- 과업 성공 여부를 설명하지 못함
- 요약의 핵심 정보 보존이나 질의응답의 정답 여부는 별도 평가 필요
Transformers에서 혼란도 계산
- EXAONE 4.0 1.2B 모형으로 한 문장의 혼란도를 계산
- Colab에서는 런타임 → 런타임 유형 변경 → T4 GPU를 먼저 선택
!pip install -q "transformers==4.55.4" accelerate jinja2
EXAONE 4.0을 지원하고 다른 실습과 호환되는 Transformers 4.55.4를 설치
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "LGAI-EXAONE/EXAONE-4.0-1.2B" # 모델명
tokenizer = AutoTokenizer.from_pretrained(model_name) # 토크나이저
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16, # T4 GPU에서 사용하는 16비트 자료형
device_map="auto", # 사용 가능한 GPU에 자동 배치
)
model.eval() # 평가 모드
EXAONE의 원본 파라미터를 T4 GPU가 지원하는 float16으로 변환하고 사용 가능한 장치에 배치한다. eval()은 모형을 평가 모드로 전환한다.
text = "밥을 먹었다." # 예시 문장
inputs = tokenizer(text, return_tensors="pt").to(model.device) # 토큰화 하여 PyTorch 텐서로 변환
with torch.no_grad(): # 기울기 계산을 생략
outputs = model(**inputs, labels=inputs["input_ids"]) # 다음 토큰 예측 손실 계산
outputs.loss # 평균 교차 엔트로피 손실
평균 교차 엔트로피에 지수 함수를 적용하면 혼란도를 계산할 수 있음
torch.exp(outputs.loss).item() # 혼란도