ROUGE 스코어 이해하기
- Recall-Oriented : 재현율에 중점을 둔
- Understudy : 인간을 대신하여
- for Gisting Evaluation : 핵심 추출 평가
개발 목적:
ROUGE는 원래 텍스트 요약을 평가하기 위해 개발 (Lin, 2004)
요약 평가
추론 - 정답 비교 평가 기준 : 정답에 담겨있는 핵심이 얼마나 잘 추론되었는가 (정답 얼마나 잘 맞췄나)
ROUGE 사용의 한계
핵심을 빠뜨리지 않기 위해, 요약을 하지 않는다면? (출력 MAX_Length를 정한다)
ROUGE 의 발전
- 초기에는 재현율만을 평가했으나, 이후로 정밀도, f1 스코어까지 확장되었다.
- ROUGE-L, ROUGE-S, ROUGE-SU 등 다양한 측정 방식으로 확장되었다.
결론:
ROUGE는 요약 모델 평가에 가장 적합하고 널리 사용되지만, 다른 NLP 작업에도 사용할 수 있다. 다만 그 한계를 인식하고, 필요에 따라 다른 평가 지표와 함께 사용하는 것이 좋다. 최근에는 BERTScore, MoverScore 같은 의미적 유사성을 더 잘 포착하는 지표들도 있다.
실습
!pip install konlpy
from collections import Counter
from konlpy.tag import Okt
from nltk.util import ngrams
토큰화, n-gram화, 토큰의 빈도
def tokenize_korean(text):
"""한국어 텍스트를 토큰화합니다."""
okt = Okt()
return okt.morphs(text) # 형태소 단위로 토큰화
def get_ngrams(tokens, n):
"""토큰에서 n-gram을 생성합니다."""
return list(ngrams(tokens, n))
def count_ngrams(ngram_list):
"""n-gram의 빈도를 계산합니다."""
return Counter(ngram_list)
reference=결과, candidate= 정답
reference = "인공지능 기술은 우리의 일상 생활을 변화시키고 있습니다."
candidate = "인공지능 기술이 우리 생활을 크게 변화시키고 있다."
# 토큰화
ref_tokens = tokenize_korean(reference)
cand_tokens = tokenize_korean(candidate)
# bi-gram 생성
ref_ngrams = get_ngrams(ref_tokens, 2)
cand_ngrams = get_ngrams(cand_tokens, 2)
# n-gram 빈도 계산
ref_count = count_ngrams(ref_ngrams)
cand_count = count_ngrams(cand_ngrams)
정답 기준으로 정답과 결과의 count를 비교하여, 작은 값을 가져온다.
정답: 2, 결과: 1 -> 1개 맞춤
정답: 2, 결과: 3 -> 2개 맞춤
# 일치하는 n-gram 계산
matches = 0
for ngram in cand_count:
m = min(cand_count[ngram], ref_count.get(ngram, 0))
print(m)
matches += m
# @title 정답
def rouge_n(reference, candidate, n):
"""ROUGE-N 점수를 계산합니다.
Args:
reference: 참조 텍스트 (문자열)
candidate: 후보 텍스트 (문자열)
n: n-gram의 크기 (1 또는 2)
Returns:
precision, recall, f1 점수를 포함하는 튜플
"""
# 토큰화
ref_tokens = tokenize_korean(reference)
cand_tokens = tokenize_korean(candidate)
# n-gram 생성
ref_ngrams = get_ngrams(ref_tokens, n)
cand_ngrams = get_ngrams(cand_tokens, n)
# n-gram 빈도 계산
ref_count = count_ngrams(ref_ngrams)
cand_count = count_ngrams(cand_ngrams)
# 일치하는 n-gram 계산
matches = 0
for ngram in cand_count:
matches += min(cand_count[ngram], ref_count.get(ngram, 0))
# 정밀도, 재현율, F1 점수 계산
precision = matches / max(sum(cand_count.values()), 1)
recall = matches / max(sum(ref_count.values()), 1)
if precision + recall == 0:
f1 = 0
else:
f1 = 2 * precision * recall / (precision + recall)
return precision, recall, f1
def rouge_1(reference, candidate):
"""ROUGE-1 점수를 계산합니다."""
return rouge_n(reference, candidate, 1)
def rouge_2(reference, candidate):
"""ROUGE-2 점수를 계산합니다."""
return rouge_n(reference, candidate, 2)
Tags:
AI개발_교육