7장. SFT 데이터 구성과 Chat Template
학습·검증·평가 데이터 나누기
학원에서 문제집으로 공부하고(학습), 중간중간 모의고사로 실력을 확인하고(검증), 마지막에 실전 시험을 봅니다(평가). 실전 시험 문제를 미리 풀어 보면 점수가 올라가지만 진짜 실력은 알 수 없습니다. 데이터도 세 묶음으로 나누고, 평가 묶음은 끝까지 손대지 않습니다.
그림의 세 상자가 각 묶음의 쓰임입니다. 원본 노트북은 df.sample(frac=1, random_state=42) 로 행을 섞은 뒤 앞 10% 를 test, 다음 10% 를 valid, 나머지를 train 으로 자릅니다. 손으로 계산하면 327 × 0.1 = 32.7 이고 int 로 소수점 아래를 버려 32 입니다. 그래서 test 32, valid 32, train 327 − 32 − 32 = 263 입니다.
세 묶음의 쓰임
| 데이터 | 용도 | 비율 | 이 장의 개수 |
|---|---|---|---|
| train(학습) | 모델 가중치(LoRA)를 고친다 | 80% | 263 |
| valid(검증) | 학습 중 과적합 확인, 설정 비교 | 10% | 32 |
| test(평가) | 학습이 끝난 뒤 최종 성능 확인 | 10% | 32 |
짧은 예시
import pandas as pd
persona = pd.read_csv("data/persona_sft_raw.csv")
# sample(frac=1): 모든 행을 무작위 순서로 뽑는다(섞기). random_state=42 는 섞는 순서를 고정하는 씨앗
shuffled = persona.sample(frac=1, random_state=42).reset_index(drop=True)
# int(327 * 0.1) = int(32.7) = 32
n = int(len(shuffled) * 0.1)
test, valid, train = shuffled.iloc[:n], shuffled.iloc[n:2 * n], shuffled.iloc[2 * n:]
print(len(train), len(valid), len(test)) # 결과: 263 32 32
# 세 묶음의 질문이 서로 겹치지 않는지 집합의 교집합(&)으로 확인한다
overlap = set(train["prompt"]) & (set(valid["prompt"]) | set(test["prompt"]))
print("겹치는 질문:", len(overlap)) # 결과: 0이 코드가 뜻하는 것
카드 327장을 잘 섞어서 위에서 32장은 실전 시험용 봉투, 다음 32장은 모의고사용 봉투에 넣고, 남은 263장을 문제집으로 쓰는 일입니다. 섞은 뒤 잘랐으므로 같은 카드가 두 봉투에 들어갈 수 없고, 교집합 0 이 그것을 확인합니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
sample(frac=1, random_state=42) | 모든 행을 같은 순서로 섞는다 | 카드 섞기(늘 같은 순서로) |
int(len(shuffled) * 0.1) | 10% 개수를 정수로 | 봉투 하나에 넣을 장 수 |
iloc[:n], iloc[n:2 * n], iloc[2 * n:] | 앞에서부터 잘라 나눈다 | 봉투 셋에 나눠 담기 |
set(...) & set(...) | 겹치는 질문을 찾는다 | 같은 카드가 두 봉투에 있는가 |
주의할 점
random_state를 빼면 실행할 때마다 나뉘는 행이 달라져 결과를 견줄 수 없습니다. 씨앗을 고정합니다.- 질문이 거의 같은 행(예: 말끝만 다른 질문)이 train 과 test 에 나뉘어 들어가면 시험 문제가 새어 나간 셈입니다. 비슷한 질문은 같은 묶음에 넣습니다.
- 분류가 있는 데이터는 분류별로 따로 나눠야 묶음마다 비율이 고릅니다. 프로젝트에서 해 봅니다.