Judge 편향과 안정성 — median, σ, 재판정
앞 글에서 LLM-as-a-Judge를 세웠다. 이제 진짜 어려운 얘기다.
같은 (컨텍스트, 답) 쌍을 판정자에게 5번 물어보면
매번 다른 점수가 나온다.
판정자 자체가 흔들리는데 그걸 어떻게 신뢰할 수 있나? 이번 글은 그 흔들림의 정체(편향)와, 흔들림을 억제하는 기법(안정화)을 다룬다.
Judge bias 4종
LLM 판정자가 흔들리는 이유는 랜덤성 하나가 아니다. 연구에서 반복해서 관측되는 편향이 크게 넷 있다.
1. Position bias
같은 두 답 A, B를 순서만 바꿔서 비교시키면
LLM이 앞에 오는 답을 선호하는 경향이 있다.
이건 특히 pairwise judge(둘 중 어느 게 나은가?)에서 심하다. 싱글 스코어링(0~1로 매김)에서는 덜 하지만, 여러 문단을 순서대로 평가할 때는 여전히 남는다.
대응: A/B 순서를 랜덤 셔플하거나, 양쪽 순서로 두 번 물어보고 평균낸다.
2. Verbosity bias
긴 답이 짧은 답보다 높은 점수를 받는다.
"자세하다"는 게 좋아 보이니까 판정자가 자연스럽게 그쪽으로 기운다. 그런데 실제로는 긴 답이 오히려 환각을 더 잘 섞는다. faithfulness는 verbosity가 늘수록 오히려 떨어져야 정상이다.
대응: rubric에 "길이는 평가하지 말라"고 명시한다. 길이 자체를 하나의 지표로 따로 뺀다.
3. Self-preference bias
모델이 자기가 만든 답을 자기가 판정하면 후하게 준다.
이건 이 시리즈 다음 편(cross-model judge)에서 정면으로 다룬다. 지금은 이름만 기억.
4. Calibration bias
"0.8이 뭘 뜻하는지"에 대한 감각이 판정자마다 다르다.
같은 답이라도 어떤 모델은 0.7, 어떤 모델은 0.9를 준다.
절대값 비교가 위험한 이유가 여기 있다. 오늘 0.8이 어제 0.9보다 나쁘다고 단정할 수 없다 — 판정자 감각이 바뀌었을 가능성이 있다.
대응: 절대 스코어보다 델타(어제→오늘)를 본다. 그리고 판정자 모델을 자주 바꾸지 않는다.
흔들림을 어떻게 줄이나
편향의 원인은 위처럼 여럿이지만, 실무에서 통제할 수 있는 손잡이는 크게 세 개다.
1) 여러 번 판정하고 median 을 쓴다
2) 분산이 크면 자동으로 재판정한다
3) rubric을 아주 구체적으로 쓴다
1. N회 median 판정
같은 (컨텍스트, 답)을 판정자에게 N번(보통 3~5회) 물어보고 중앙값을 최종 점수로 쓴다.
raw scores: [0.85, 0.90, 0.62, 0.88, 0.86]
mean: 0.822
median: 0.86
평균 대신 중앙값을 쓰는 이유는 outlier에 덜 흔들리기 때문이다. 0.62 하나가 평균을 크게 끌어내리는데, 중앙값은 그걸 무시해준다.
3회로 시작해도 충분히 안정적이다. 5회는 확실히 안정적이지만 비용이 늘고, 7회부터는 개선폭이 급격히 줄어든다.
2. σ 임계 자동 재판정
median만으로 모든 케이스가 잡히지는 않는다. 분산 자체가 큰 케이스를 따로 처리해야 한다.
raw scores: [0.30, 0.85, 0.20, 0.90, 0.88]
median: 0.85
σ (표준편차): 0.322 ← 너무 큼
median이 0.85로 나왔지만, 이 케이스는 판정자가 "확신 못 하는 케이스"다. 0.85를 그대로 쓰면 위험하다. σ가 임계값(예: 0.15)을 넘으면 자동 재판정을 걸어서 그 답을 사람에게 넘기거나, 다른 모델로 다시 판정한다.
if σ > 0.15:
escalate to secondary judge (다른 모델)
or flag as "unstable" for human review
이렇게 하면 판정자 신뢰도가 확 올라간다. 자신 없는 케이스만 골라내는 필터가 무료로 붙는 셈이다.
3. rubric을 세밀하게
Rubric이 두루뭉술하면 판정이 흔들린다. 반대로 rubric이 구체적일수록 판정자 간·판정 간 일관성이 올라간다.
나쁜 예:
"답이 얼마나 정확한지 0~1로 판정하라."
좋은 예:
답의 각 문장을 아래 규칙으로 채점한 뒤 평균을 낸다.
1) 문장이 사실 진술이 아니면(의견, 인사, 안내) 채점에서 제외한다.
2) 사실 진술이면 컨텍스트에서 근거 문장을 찾는다.
- 근거가 명확: 1.0
- 근거가 부분적: 0.5
- 근거가 없음: 0.0
3) 답 안에 컨텍스트에 없는 숫자·고유명사가 있으면 무조건 0.0.
4) 길이는 평가하지 않는다.
출력은 JSON:
{
"per_sentence": [...],
"final_score": 0.0~1.0,
"reason": "..."
}
Rubric이 세밀할수록 재현성이 올라간다. 그리고 나중에 판정 로그를 볼 때 "왜 이렇게 매겼는지"가 사람이 읽을 수 있게 남는다.
실측 감각
프로젝트에서 15종목 × 5회 판정을 돌린 실측이다.
1회 판정만 썼을 때:
종목 간 grounded 편차 σ = 0.11
같은 종목 재판정 편차 σ = 0.08
5회 median 후:
종목 간 grounded 편차 σ = 0.09
같은 종목 재판정 편차 σ = 0.03
"같은 종목을 판정자에게 다시 물어봤을 때 얼마나 흔들리는가"가 0.08 → 0.03으로 떨어졌다. 이 정도면 판정 결과가 실제로 파이프라인 변경의 신호인지 노이즈인지 구분이 된다.
σ 임계 재판정을 붙인 뒤에는 15종목 중 2종목이 "unstable"로 걸렸다. 그 2종목은 사람 리뷰로 넘겼는데, 둘 다 실제로 판정하기 애매한 답이었다. 판정자가 자기 자신 없는 케이스를 잘 골라낸 셈이다.
rag-retriever/03과의 연결
이 시리즈에서 판정자를 세밀하게 다루고 있지만, 원래 rag-retriever/03 검색 품질 평가 편에서 LLM-as-Judge를 짧게 언급했다. 거기서는 "이런 지표가 있다" 정도로 넘어갔는데, 이 편이 그 심화판이다.
정리하면:
rag-retriever/03 → 검색이 잘 되는지 재는 지표 (Recall@k, MRR, nDCG)
rag-eval/01 → 생성까지 포함한 판정 지표 (RAGAS 5개)
rag-eval/02 (여기) → 그 판정자를 어떻게 흔들리지 않게 만들 것인가
세 편을 세트로 읽으면 "검색과 생성을 어떻게 평가할지"가 하나의 그림으로 정리된다.
다음 편 예고
편향 4개 중 self-preference bias는 이번 편에서 이름만 언급했다. 그건 판정자를 한 개 쓰는 한 근본적으로 해결이 안 되기 때문이다.
다음 편에서는 판정자를 두 개 쓴다. Sonnet과 Opus를 나란히 세워서 disagreement를 재고, 그 disagreement 자체를 파이프라인 신호로 쓰는 법을 다룬다.