LLM 25일 코스 - Day 21: 파인튜닝 데이터셋 준비

Day 21: 파인튜닝 데이터셋 준비

파인튜닝의 성패는 데이터 품질에 달려 있습니다. 아무리 좋은 모델과 기법을 써도 데이터가 나쁘면 결과도 나쁩니다. 오늘은 실무에서 가장 많이 쓰이는 두 가지 데이터 형식과 준비 과정을 배웁니다.

Alpaca 형식 (Instruction Tuning)

Alpaca 형식은 instruction/input/output 3개 필드로 구성됩니다. 단일 턴 질의응답에 적합합니다.

import json

# Alpaca 형식 데이터 예시
alpaca_data = [
    {
        "instruction": "주어진 텍스트를 한국어로 번역하세요.",
        "input": "The weather is beautiful today.",
        "output": "오늘 날씨가 아름답습니다."
    },
    {
        "instruction": "다음 코드의 버그를 찾아 수정하세요.",
        "input": "def add(a, b):\n    return a - b",
        "output": "연산자가 잘못되었습니다. `a - b`를 `a + b`로 수정해야 합니다.\n\n```python\ndef add(a, b):\n    return a + b\n```"
    },
    {
        "instruction": "파이썬의 리스트 컴프리헨션을 설명하세요.",
        "input": "",  # input이 없는 경우 빈 문자열
        "output": "리스트 컴프리헨션은 기존 리스트를 기반으로 새 리스트를 간결하게 만드는 문법입니다. `[표현식 for 요소 in 반복가능객체 if 조건]` 형태로 사용합니다."
    },
]

# JSON 파일로 저장
with open("train_alpaca.json", "w", encoding="utf-8") as f:
    json.dump(alpaca_data, f, ensure_ascii=False, indent=2)

print(f"저장 완료: {len(alpaca_data)}개 샘플")

ShareGPT 형식 (Multi-turn Conversation)

ShareGPT 형식은 여러 턴의 대화를 기록합니다. 챗봇 파인튜닝에 적합합니다.

# ShareGPT 형식 데이터 예시
sharegpt_data = [
    {
        "conversations": [
            {"from": "system", "value": "당신은 파이썬 전문가입니다. 코드와 함께 설명하세요."},
            {"from": "human", "value": "딕셔너리와 리스트의 차이점이 뭔가요?"},
            {"from": "gpt", "value": "딕셔너리는 키-값 쌍으로 데이터를 저장하고, 리스트는 순서가 있는 값의 모음입니다.\n\n```python\n# 리스트: 인덱스로 접근\nfruits = ['사과', '바나나', '체리']\nprint(fruits[0])  # 사과\n\n# 딕셔너리: 키로 접근\nprices = {'사과': 1000, '바나나': 500}\nprint(prices['사과'])  # 1000\n```"},
            {"from": "human", "value": "딕셔너리의 키로 리스트를 사용할 수 있나요?"},
            {"from": "gpt", "value": "아니요, 리스트는 변경 가능(mutable)하므로 딕셔너리의 키로 사용할 수 없습니다. 키는 반드시 해시 가능(hashable)한 불변 객체여야 합니다. 대신 튜플을 사용할 수 있습니다."},
        ]
    },
]

with open("train_sharegpt.json", "w", encoding="utf-8") as f:
    json.dump(sharegpt_data, f, ensure_ascii=False, indent=2)

데이터 정제와 검증

수집한 데이터는 반드시 정제 과정을 거쳐야 합니다. 중복 제거, 품질 필터링, 형식 검증이 핵심입니다.

from datasets import Dataset
import hashlib

def validate_and_clean(data):
    """데이터 품질 검증 및 정제"""
    cleaned = []
    seen_hashes = set()
    issues = {"duplicate": 0, "too_short": 0, "empty_output": 0}

    for item in data:
        # 빈 출력 제거
        if not item.get("output", "").strip():
            issues["empty_output"] += 1
            continue

        # 너무 짧은 출력 제거 (10자 미만)
        if len(item["output"].strip()) < 10:
            issues["too_short"] += 1
            continue

        # 중복 제거 (해시 기반)
        content_hash = hashlib.md5(
            (item["instruction"] + item["output"]).encode()
        ).hexdigest()
        if content_hash in seen_hashes:
            issues["duplicate"] += 1
            continue
        seen_hashes.add(content_hash)

        cleaned.append(item)

    print(f"원본: {len(data)}개 -> 정제 후: {len(cleaned)}개")
    print(f"제거 사유: {issues}")
    return cleaned

# 정제 실행
cleaned_data = validate_and_clean(alpaca_data)

# Hugging Face datasets로 변환
dataset = Dataset.from_list(cleaned_data)
print(dataset)

# 학습/검증 분할
split_dataset = dataset.train_test_split(test_size=0.1, seed=42)
print(f"학습: {len(split_dataset['train'])}개, 검증: {len(split_dataset['test'])}개")

datasets 라이브러리로 허브 데이터 로드

from datasets import load_dataset

# Hugging Face Hub에서 공개 데이터셋 로드
dataset = load_dataset("tatsu-lab/alpaca", split="train")
print(f"Alpaca 데이터셋: {len(dataset)}개 샘플")
print(f"컬럼: {dataset.column_names}")
print(f"\n첫 번째 샘플:\n{dataset[0]}")

# 한국어 데이터셋 예시
ko_dataset = load_dataset("heegyu/ko-chatgpt-qa", split="train")
print(f"\n한국어 Q&A: {len(ko_dataset)}개 샘플")

오늘의 연습문제

  1. 본인의 전문 분야에서 Alpaca 형식으로 20개 이상의 instruction-output 쌍을 직접 작성하고, validate_and_clean() 함수로 검증해보세요.
  2. ShareGPT 형식으로 3턴 이상의 대화 데이터 5개를 작성하고, datasets 라이브러리로 로드하여 학습/검증 세트로 분할해보세요.
  3. Hugging Face Hub에서 한국어 instruction 데이터셋을 3개 이상 찾고, 각각의 크기, 형식, 라이선스, 품질을 비교 분석해보세요.

이 글이 도움이 되었나요?