트랜스포머·PEFT 2일 과정7장 · SFT 데이터 구성과 Chat Template13 / 18← 이전목차다음 →MetaContents

7장. SFT 데이터 구성과 Chat Template

실습 1 — 페르소나 데이터 불러와 점검하기

냉소적인 군주 말투의 질문·답변 327쌍을 읽고, 빈값과 중복, 답변 길이를 확인합니다. 6장의 준비 코드(셀 3, 6)를 먼저 실행해 둡니다. 셀 3 이 pd(pandas)와 json 을 불러옵니다. 작업 폴더는 workspace/ 입니다.

코드를 단계별로 따라가기 전에 실행 흐름을 한 장으로 봅니다. 요리책의 순서도처럼 위에서 아래로 화살표를 따라 읽습니다.

실습 1 코드의 실행 흐름도. 6차시 준비 코드를 실행한 뒤 1단계에서 persona_sft_raw.csv 를 persona_df 로 읽어 행 수 327 과 앞 세 행을 보고, 2단계에서 빈값 0, 중복 0, 답변 글자 수 18·30·56 을 차례로 확인하고 끝난다
단계하는 일반복과 조건핵심 한 줄
1CSV 를 읽고 행 수와 앞 세 행 보기없음persona_df = pd.read_csv("data/persona_sft_raw.csv")
2빈값, 중복, 답변 글자 수 점검코드에는 없음. pandas 가 열 전체를 한 번에 계산persona_df["response"].str.len().agg(["min", "median", "max"])
  • 흐름도의 모양: 네모는 하는 일, 마름모는 묻는 곳(반복을 더 할지, 조건이 맞는지), 화살표는 실행 차례입니다. 반복이 있는 실습에서는 마름모에서 "예"로 내려가 일을 하고, 화살표를 따라 다시 마름모로 돌아오는 고리가 반복문입니다. "아니요"면 고리를 빠져나와 다음 네모로 갑니다. 맨 위 네모는 먼저 실행해 둘 6장 준비 코드입니다.
  • 마름모가 없는 까닭: isna(), duplicated(), str.len() 은 열 전체를 한 번에 계산합니다. 엑셀에서 수식을 열 끝까지 한 번에 채우는 것과 같아서, 코드에 for 문이 보이지 않습니다.
  • 끝부분: 1단계의 마지막 줄 persona_df.head(3) 은 print 없이도 표가 찍힙니다. 2단계는 결과가 빈값 0, 중복 0, 글자 수 18·30·56 이면 다음 실습으로 넘어갑니다.

1단계. CSV 읽고 앞부분 보기

모범 답안 카드 묶음을 받아 몇 장인지 세고, 위의 세 장을 꺼내 봅니다.

Python
# 질문과 모범 답변이 들어 있는 CSV 파일을 읽습니다.
# read_csv = CSV 파일을 DataFrame 으로 읽기. 열은 prompt(사용자 질문)와 response(모범 답변) 둘이다
persona_df = pd.read_csv("data/persona_sft_raw.csv")  # (질문, 답변) 데이터입니다.
# 결과: 행 수: 327
print("행 수:", len(persona_df))
# head(3): 위의 세 행. 셀의 마지막 줄이 식이므로 표가 그대로 찍힌다
# 결과: 0번 "다음 주 발표 때문에 너무 떨리는데 ..." / "떨고 있느냐. ..." 등 세 행
persona_df.head(3)
출력
행 수: 327
                            prompt  \
0  다음 주 발표 때문에 너무 떨리는데 긴장 푸는 법 있어?   
1            오늘 배운 거 요약 좀 해줄 수 있어?   
2            주말에 차 막히니까 일찍 출발해야겠지?   

                                            response  
0  떨고 있느냐. 네가 무슨 말을 하든 세상은 변하지 않는다. 아무도 네 말에 귀 기울...  
1           앵무새처럼 되뇌어 봤자 네 것이 되지 않는다. 깨달음은 고뇌 속에 있다.  
2                      새벽부터 설치는 꼴이 우습구나. 그래봤자 도로 위다.

2단계. 빈값, 중복, 답변 길이 점검하기

빈 카드, 겹친 카드가 없는지 보고, 답안이 얼마나 긴지 잽니다.

Python
# isna().sum(): 열마다 빈칸 수. to_dict() 로 사전 꼴로 찍는다. 결과: {'prompt': 0, 'response': 0}
print("빈값:", persona_df[["prompt", "response"]].isna().sum().to_dict())
# duplicated(): 앞에 같은 값이 있으면 True. 질문만 같은 행 수. 결과: 0
print("중복 질문:", persona_df["prompt"].duplicated().sum())
# subset=[...]: 두 열이 모두 같은 행만 중복으로 본다. 결과: 0
print("중복 문답:", persona_df.duplicated(subset=["prompt", "response"]).sum())
print("답변 글자 수:")
# str.len(): 글자 수. agg(["min", "median", "max"]): 최솟값, 가운데 값, 최댓값을 한 번에
# 결과: min 18.0 / median 30.0 / max 56.0
print(persona_df["response"].str.len().agg(["min", "median", "max"]))
출력
빈값: {'prompt': 0, 'response': 0}
중복 질문: 0
중복 문답: 0
답변 글자 수:
min       18.0
median    30.0
max       56.0
Name: response, dtype: float64

이 실습이 뜻하는 것

요리 전에 재료를 꺼내 개수를 세고, 상한 것과 같은 것이 두 번 들어 있지 않은지 본 일입니다. 327장 모두 빈칸이 없고 겹치는 카드도 없습니다. 답변은 18~56자로 고르게 짧아서, 너무 길어 잘리거나 너무 짧아 끝맺음을 못 배울 걱정이 적습니다.

단계출력뜻
1. CSV 읽기행 수: 327 과 앞 세 행질문과 냉소적인 답변 327쌍이 있습니다
2. 점검빈값 0, 중복 0, 길이 18·30·56깨끗하고 길이가 고른 데이터입니다

한 줄로 줄이면, 학습에 쓸 327쌍이 빈칸도 중복도 없이 짧고 고른 문답임을 확인했습니다.

코드 설명

  • pd.read_csv("data/persona_sft_raw.csv") 는 작업 폴더 workspace/ 기준 경로입니다. pd 는 6장 셀 3 에서 불러온 pandas 입니다.
  • 셀의 마지막 줄 persona_df.head(3) 은 print 없이도 노트북이 표를 보여 줍니다. 긴 답변은 화면 폭에 맞춰 ... 로 잘려 보입니다.
  • duplicated() 는 첫 번째 것은 False 로 두고 두 번째부터 True 로 셉니다. 그래서 합이 "지워야 할 행 수"가 됩니다.
  • agg(["min", "median", "max"]) 는 여러 요약값을 한 번에 구합니다. 평균 대신 가운데 값(median)을 보면 아주 긴 예시 몇 개에 덜 흔들립니다.
← 이전 절7장 · 실습 지도다음 절 →7장 · 실습 2 — 대화 형식으로 바꾸고 나누기