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%) │
│ · 튜닝 중에는 절대 보지 않습니다 │
│ · 최종 성능 보고에만 씁니다 │
│ · 여기 점수가 진짜 실력입니다 │
└─────────────────────────────────────┘📝 분리 코드
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는 관례일 뿐 아무 의미 없습니다.