본문 바로가기
C.W.K.
Stream
Lesson 03 of 06 · published

BERTScore: 의미 유사도

~22 min · metrics, semantic, embeddings

Level 0추측자
0 XP0/55 lessons0/10 achievements
0/150 XP to next level150 XP to go0% complete

단어보다 의미가 중요할 때

BERTScore는 n-그램 겹침 대신 임베딩 유사도를 사용해. BERT나 다른 맥락 임베딩 모델을 이용해 후보 출력의 각 토큰을 참조 답안에서 가장 비슷한 토큰과 짝짓고, 토큰별 유사도의 평균을 계산하지. 그 결과, 같은 의미를 다른 단어로 표현한 문장은 높은 점수를 받고, 표면적인 단어만 겹치고 의미가 다른 문장은 낮은 점수를 받아.

작동 방식

  1. 참조 답안과 후보 출력을 맥락 임베딩 모델(BERT, RoBERTa 또는 이에 준하는 최신 모델)로 인코딩해.
  2. 후보 출력의 각 토큰에 대해 참조 답안에서 유사도가 가장 높은 토큰을 찾아.
  3. 정밀도(후보 출력 기준), 재현율(참조 답안 기준), F1 점수로 결과를 종합해.

대부분의 과제에서 BLEU/ROUGE보다 나은 이유

BLEU는 "physician"과 "doctor"를 겹치는 단어가 없는 것으로 보지만, BERTScore는 두 단어를 거의 같은 의미로 봐. 그래서 바꿔 쓰기, 요약, 번역 과제에서 인간의 판단과 훨씬 높은 상관관계를 보여.

원칙: LLM을 호출하지 않고 의미를 자동으로 비교해야 할 때는 BERTScore가 좋은 기본 선택이야. 표면적인 지표가 놓치는 의미를 포착하면서도 비용은 결정론적 지표에 가까워.

여전히 잡아내지 못하는 것

  • 논리 오류X가 Y의 원인이야Y가 X의 원인이야가 모두 높은 점수를 받을 수 있어.
  • 부정 — "is safe"와 "is not safe"는 임베딩의 대부분을 공유해.
  • 수치 오류 — "$1M"과 "$10M"이 임베딩 공간에서는 의미상 가깝게 보일 수 있어.

실용적인 고려 사항

모델은 신중하게 골라야 해. microsoft/deberta-large-mnli는 기본 BERT보다 평가 작업에 더 적합해. 같은 데이터셋을 반복해서 평가한다면 임베딩을 캐시해 둬. 첫 실행에는 비용이 들지만 이후 실행은 거의 무료야.

Code

공식 라이브러리로 BERTScore 계산하기·python
# pip install bert-score
from bert_score import score

refs = [
    "The doctor prescribed antibiotics for the infection.",
    "The car would not start because the battery was dead.",
]
hyps = [
    "For the infection, the physician prescribed antibiotics.",
    "The vehicle failed to start due to a dead battery.",
]

# F1 is what most papers report
P, R, F1 = score(hyps, refs, lang="en", model_type="microsoft/deberta-large-mnli")
for h, f in zip(hyps, F1.tolist()):
    print(f"{f:.3f}  {h}")
# 0.94  For the infection, the physician prescribed antibiotics.
# 0.91  The vehicle failed to start due to a dead battery.
# Both >>>> what BLEU would have given (~0.30).
임베딩의 코사인 유사도 — 직접 구현한 방식·python
# When you want fast embeddings without the BERTScore matching machinery.
import numpy as np
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-mpnet-base-v2")

def cosine_sim(a, b):
    va, vb = model.encode([a, b])
    return float(np.dot(va, vb) / (np.linalg.norm(va) * np.linalg.norm(vb)))

print(cosine_sim("safe to drink", "potable"))     # ~0.78
print(cosine_sim("safe to drink", "not safe"))    # ~0.55  ← negation trap

External links

Exercise

BLEU/ROUGE에 사용했던 출력 표본 30개에서 BERTScore F1을 계산해. 인간 평가와의 상관관계를 이전 지표들과 비교해 봐. BERTScore가 더 높은 상관관계를 보여야 해. 얼마나 큰 차이로 앞서는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.