ROUGE

Recall-Oriented Understudy for Gisting Evaluation

ROUGE

ROUGE는 Recall-Oriented Understudy for Gisting Evaluation 의 약자로, 모델이 생성한 텍스트가 정답과 얼마나 겹치는지 측정하는 지표다. 원래 요약(summarization) 평가용으로 만들어졌지만, QA나 번역 등 텍스트 생성 전반에서 쓰인다.

핵심 아이디어는 단순하다: 정답에 있는 단어가 예측에 얼마나 등장하는가?


공통 수식: Precision, Recall, F1

모든 ROUGE 변형은 동일한 프레임워크를 따른다. 겹침(overlap)을 세는 단위만 달라질 뿐이다.

\[\text{Recall} = \frac{|\text{overlap}|}{|\text{Reference}|}\] \[\text{Precision} = \frac{|\text{overlap}|}{|\text{Prediction}|}\] \[F_1 = \frac{2 \times P \times R}{P + R}\]

예시 설정

아래 예시로 모든 ROUGE를 계산해본다.

정답(Reference):    "서울의 인구는 약 천만 명이고 대한민국의 수도이다"
예측(Prediction):   "서울은 대한민국의 수도이며 인구는 약 구백만 명이다"

토큰 분리 (공백 기준):

R = [서울의, 인구는, 약, 천만, 명이고, 대한민국의, 수도이다]     → m = 7
P = [서울은, 대한민국의, 수도이며, 인구는, 약, 구백만, 명이다]   → n = 7

ROUGE-1 (Unigram)

수식

\[\text{ROUGE-1}_{recall} = \frac{\sum_{w \in R} \min(\text{count}_R(w),\ \text{count}_P(w))}{\sum_{w \in R} \text{count}_R(w)}\]

각 unigram $w$에 대해, 정답에서의 출현 횟수와 예측에서의 출현 횟수 중 작은 값을 취해 합산한다.

카운팅

정답 토큰 예측에 있나?
서울의 ❌ (“서울은”과 다른 토큰)
인구는
천만 ❌ (“구백만”과 다른 토큰)
명이고 ❌ (“명이다”와 다른 토큰)
대한민국의
수도이다 ❌ (“수도이며”와 다른 토큰)

겹치는 토큰: {인구는, 약, 대한민국의} → $|\text{overlap}| = 3$

계산

\[R = \frac{3}{7} \approx 0.4286\] \[P = \frac{3}{7} \approx 0.4286\] \[F_1 = \frac{2 \times 0.4286 \times 0.4286}{0.4286 + 0.4286} \approx 0.4286\]

ROUGE-2 (Bigram)

수식

\[\text{ROUGE-2}_{recall} = \frac{\sum_{b \in R_{bigram}} \min(\text{count}_R(b),\ \text{count}_P(b))}{\sum_{b \in R_{bigram}} \text{count}_R(b)}\]

unigram 대신 연속 2개 단어 쌍(bigram)으로 겹침을 센다.

카운팅

정답 bigrams (6개):
  (서울의, 인구는)       (인구는, 약)         (약, 천만)
  (천만, 명이고)         (명이고, 대한민국의)   (대한민국의, 수도이다)

예측 bigrams (6개):
  (서울은, 대한민국의)   (대한민국의, 수도이며) (수도이며, 인구는)
  (인구는, 약)           (약, 구백만)          (구백만, 명이다)

겹치는 bigram:
  (인구는, 약) ✅
  나머지 전부 ❌

$|\text{overlap}| = 1$

계산

\[R = \frac{1}{6} \approx 0.1667\] \[P = \frac{1}{6} \approx 0.1667\] \[F_1 \approx 0.1667\]

ROUGE-2가 ROUGE-1보다 낮은 이유: “인구는”과 “약”이 각각 겹쳐도, 이 둘이 연속으로 나타나야만 bigram으로 잡힌다. “대한민국의”가 겹치지만 앞뒤 토큰이 달라서 어떤 bigram에도 기여하지 못한다.


ROUGE-L (Longest Common Subsequence)

수식

LCS(Longest Common Subsequence)의 길이를 이용한다.

\[R_{lcs} = \frac{\text{LCS}(R, P)}{m}\] \[P_{lcs} = \frac{\text{LCS}(R, P)}{n}\] \[F_{lcs} = \frac{(1 + \beta^2) \times R_{lcs} \times P_{lcs}}{R_{lcs} + \beta^2 \times P_{lcs}}\]

$m$ = 정답 길이, $n$ = 예측 길이, $\beta = P_{lcs} / R_{lcs}$ (이렇게 설정하면 $F_{lcs} = F_1$과 동일해진다)

핵심: subsequence는 연속일 필요 없다. 원래 순서만 유지하면 건너뛸 수 있다.

LCS 구하기 (DP 테이블)

R = [서울의, 인구는, 약, 천만, 명이고, 대한민국의, 수도이다]
P = [서울은, 대한민국의, 수도이며, 인구는, 약, 구백만, 명이다]

DP 테이블 $L[i][j]$ = $R[0..i]$와 $P[0..j]$의 LCS 길이:

  서울은 대한민국의 수도이며 인구는 구백만 명이다
서울의 0 0 0 0 0    
인구는 0 0 0 1 1    
0 0 0 1 2    
천만 0 0 0 1 2    
명이고 0 0 0 1 2    
대한민국의 0 1 1 1 2    
수도이다 0 1 1 1 2    

$\text{LCS}(R, P) = 2$ → [인구는, 약]

“대한민국의”가 양쪽에 존재하지만, 정답에서는 6번째(인구는, 약 뒤), 예측에서는 2번째(인구는, 약 앞)이므로 [인구는, 약]과 동시에 LCS에 포함될 수 없다.

계산

\[R_{lcs} = \frac{2}{7} \approx 0.2857\] \[P_{lcs} = \frac{2}{7} \approx 0.2857\] \[F_1 \approx 0.2857\]

이 예시에서 ROUGE-L < ROUGE-1이다. ROUGE-1은 순서를 무시하고 {인구는, 약, 대한민국의} 3개를 세지만, ROUGE-L은 순서 제약 때문에 2개만 센다.

ROUGE-1 = 1.0인데 ROUGE-L이 낮은 극단 예시

R = [A, B, C]
P = [C, B, A]

ROUGE-1: overlap = {A, B, C} → 3/3 = 1.0
ROUGE-L: LCS = [A] 또는 [B] 또는 [C] → 1/3 = 0.33

모든 단어가 있지만 순서가 완전히 뒤집혀서 ROUGE-L은 크게 떨어진다. 이것이 ROUGE-L의 존재 이유다.


ROUGE-Lsum

수식

다중 문장에서 문장별로 LCS를 따로 구한 뒤 합산한다.

정답이 문장 $r_1, r_2, \ldots, r_k$로 구성될 때:

\[R_{lsum} = \frac{\sum_{i=1}^{k} \text{LCS}(r_i, P)}{m}\]

예시

정답:
  r1: "서울의 인구는 약 천만 명이다"           (5토큰)
  r2: "서울은 대한민국의 수도이다"              (3토큰)

예측:
  "서울은 대한민국의 수도이며 인구는 약 구백만 명이다"
LCS(r1, P) = [인구는, 약] → 2
LCS(r2, P) = [서울은, 대한민국의] → 2

Recall = (2 + 2) / (5 + 3) = 4/8 = 0.5

ROUGE-L을 전체에 한 번 적용하면 문장 경계를 무시해서 한 문장의 매칭이 다른 문장의 점수를 방해할 수 있다. ROUGE-Lsum은 문장별로 독립 계산하므로 요약처럼 여러 문장이 있는 태스크에서 더 공정하다.

단일 문장이면 ROUGE-L = ROUGE-Lsum.


전체 비교 정리

지표 수식의 overlap 단위 예시 F1 특징
ROUGE-1 unigram 0.4286 가장 관대. 순서 무시
ROUGE-2 bigram 0.1667 구문 유사도. 연속 매칭 필요
ROUGE-L LCS 0.2857 순서 고려. 비연속 허용
ROUGE-Lsum 문장별 LCS 합 - 다중 문장에서 ROUGE-L 개선

일반적으로: ROUGE-1 >= ROUGE-L >= ROUGE-2


ROUGE의 한계

1. 동의어를 못 잡는다

정답: "기쁘다"
예측: "행복하다"
→ ROUGE = 0 (의미는 같지만 토큰이 다름)

2. 길게 쓰면 Precision이 희석된다

정답: "교향곡"               → m = 1
예측: "바그너는 교향곡을 쓰려 했다"  → n = 4

Recall = 1/1 = 1.0  (정답 토큰을 다 잡음)
Precision = 1/4 = 0.25  (예측의 75%가 불필요)
F1 = 2 × (1.0 × 0.25) / (1.0 + 0.25) = 0.4

3. 의미적 정확도를 못 본다

정답: "2023년"
예측: "2024년"
→ ROUGE-1 = 0이지만, 사실상 거의 맞춘 것

이런 한계 때문에 실무에서는 ROUGE 단독이 아니라 BERTScore(임베딩 유사도), Exact Match, Human Evaluation 등을 함께 쓴다.


파이썬으로 직접 계산

import evaluate

rouge = evaluate.load("rouge")

predictions = ["서울은 대한민국의 수도이며 인구는 약 구백만 명이다"]
references = ["서울의 인구는 약 천만 명이고 대한민국의 수도이다"]

results = rouge.compute(predictions=predictions, references=references)
print(results)
# {'rouge1': 0.4286, 'rouge2': 0.1667, 'rougeL': 0.2857, 'rougeLsum': 0.2857}