RAG2026-5일35차시 · 평가 데이터셋 구축10 / 18← 이전목차다음 →MetaContents

35차시. 평가 데이터셋 구축

7. 데이터 누출 방지

출처: 원본 PDF 35차시_평가데이터셋구축.pdf 16~17쪽 · 쪽 그림 16쪽 17쪽

평가 데이터로 시스템을 튜닝하면 점수가 부풀려집니다.

7-1) 무엇이 문제인가

⚠️ 이런 상황을 조심하세요
​1. 평가 돌림 → 85%
​2. 틀린 질문 5개를 봄
​3. 그 질문이 맞게 나오도록 프롬프트 수정
​4. 다시 평가 → 95% 🎉
이 95%는 가짜입니다.
새로운 질문에서는 여전히 85%일 겁니다.
평가 데이터에만 맞춰진 것입니다.
14차시에서 이렇게 튜닝했습니다.
방향을 잡기엔 괜찮았지만,
최종 성능을 주장하기엔 부적절합니다.

7-2) Dev / Holdout 분리

출력
50문항을 두 묶음으로 나눕니다

┌─────────────────────────────────────┐
│  Dev Set (35문항, 70%)               │
│  · 튜닝하면서 자유롭게 봐도 됩니다     │
│  · 틀린 질문을 보고 개선합니다        │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│  Holdout Set (15문항, 30%)          │
│  · 튜닝 중에는 절대 보지 않습니다     │
│  · 최종 성능 보고에만 씁니다          │
│  · 여기 점수가 진짜 실력입니다        │
└─────────────────────────────────────┘

📝 분리 코드

Python
import json, random

data = json.load(open("data/eval_set.json", encoding="utf-8"))

# 유형별로 균등하게 나눈다 (한쪽에 쏠리지 않게)
from collections import defaultdict
by_type = defaultdict(list)
for d in data:
    by_type[d["type"]].append(d)

dev, holdout = [], []
random.seed(42)                    # 재현 가능하게 고정
for t, items in by_type.items():
    random.shuffle(items)
    n = max(1, int(len(items) * 0.3))
    holdout += items[:n]
    dev     += items[n:]

json.dump(dev, open("data/eval_dev.json", "w", encoding="utf-8"),
          ensure_ascii=False, indent=2)
json.dump(holdout, open("data/eval_holdout.json", "w",
          encoding="utf-8"), ensure_ascii=False, indent=2)

print(f"Dev {len(dev)}문항 / Holdout {len(holdout)}문항")

실행 결과 예시 (코드를 읽고 만든 예상 화면입니다. 실제 실행 결과, 특히 모델의 답은 다를 수 있습니다)

출력
Dev 37문항 / Holdout 13문항

💡 random.seed(42)를 쓰는 이유
시드를 고정하면 몇 번을 실행해도 같은 분할이 나옵니다.
고정하지 않으면 실행할 때마다 Holdout이 바뀌어
"이번엔 쉬운 게 걸렸네" 같은 일이 생깁니다.
숫자 42는 관례일 뿐 아무 의미 없습니다.

← 이전 절35차시 · 6. 실습 ③ — 데이터셋 검증다음 절 →35차시 · 8. 데이터셋 관리