Files
frankenstallm/source/eval/data_quality_audit.md
ModelHub XC d4abdb70fa 初始化项目,由ModelHub XC社区提供模型
Model: pathcosmos/frankenstallm
Source: Original Platform
2026-07-14 04:21:16 +08:00

9.4 KiB
Raw Permalink Blame History

SFT 데이터 품질 감사 보고서

날짜: 2026-02-26
데이터: data/sft/train.jsonl (159,125 샘플)
소스: 6개 HuggingFace 데이터셋 (KOR-OpenOrca-Platypus-v3, kullm-v2, ko-alpaca-12k, korean_safe_conversation, evol-instruct-korean, kovast)


1. 데이터 기본 통계

항목
총 샘플 수 159,125
Output 평균 길이 608 chars
Output 중앙값 468 chars
Output 최소/최대 10 / 7,393 chars
중복 (instruction+output) 0 (dedup 적용됨)
중복 (instruction only) 0

Output 길이 분포

구간 수량 비율
< 50 chars 16,519 10.4%
50-100 11,112 7.0%
100-500 55,550 34.9%
500-1000 47,023 29.6%
1000-2000 23,731 14.9%
2000-4000 5,049 3.2%
> 4000 141 0.1%

2. 발견된 품질 문제

🔴 심각 (반복 루프 직접 원인 가능성)

문제 1: 특수 토큰 오염 — </s> 113건

  • Output 텍스트 안에 </s> 문자열이 리터럴로 포함된 샘플 113건
  • 영향: 학습 시 chat template이 {output}</s>를 붙이므로, output 내부의 </s>는 premature EOS를 학습시킴. 이후 모델이 EOS를 제대로 생성하지 못하거나, EOS 이후에도 계속 생성하는 패턴을 학습
  • 기타: <|endoftext|> 1건, EOS 44건, [PAD] 3건

문제 2: Output 내 질문/답변 마커 — 약 550건

  • "질문:" 503건, "답변:" 430건 (output 내부)
  • "### 답변:" 141건, "### 질문:" 10건
  • "### Instruction:" 4건, "### Response:" 2건
  • 영향: 모델이 답변 중에 "질문:" → "답변:" 패턴을 학습하여 자체적으로 Q/A 루프를 생성

문제 3: Self-repetition 패턴 — 57건

  • 10-gram 기준 50% 이상 반복되는 output 57건
  • 영향: 반복 생성 패턴을 직접 학습

🟡 중간 (품질 저하)

문제 4: 짧은 Output — 16,519건 (10.4%)

  • 50자 미만 output이 전체의 10.4%
  • 30자 미만은 8,833건
  • 영향: 모델이 충분히 긴 답변을 생성하는 능력 저하. 짧게 끝내야 할 곳에서 EOS를 배우지만, 대부분의 질문에서는 너무 짧은 답변 → EOS 미생성 → 계속 생성 → 루프

문제 5: 낮은 한국어 비율 — 21,774건 (13.7%)

  • 한글 문자 비율 30% 미만인 샘플 (코드, 영어, 중국어 등 혼재)
  • prepare_sft_data.py의 필터가 이미 30% 기준을 적용하지만, 가중치 샘플링 이후 적용 순서 문제 가능성
  • 영향: 한국어 LLM으로서의 일관성 저하

3. 가설 검증 결과

가설 A: Output에 Q/A 루프 패턴 존재 → ⚠️ 부분 확인

  • ### 질문: ... ### 답변: 정확한 패턴: 4건 (0.003%)
  • 질문: ... 답변: 비공식 패턴: 119건 (0.07%)
  • 단순 "질문:" 또는 "답변:" 포함: ~550건
  • 결론: 정확한 루프 패턴은 극소수이나, "질문/답변" 키워드가 output에 포함된 샘플이 수백 건 존재. 이것만으로 루프의 주 원인이라 보기 어려움.

가설 B: 짧은 Output → 유력 원인

  • 50자 미만 16,519건 (10.4%)이 output 분포의 상당 부분
  • 모델이 짧은 답변 후 EOS를 생성하지 못하고 계속 토큰을 생성할 가능성
  • 특히 </s> 토큰 오염(113건)과 결합하면: 모델이 EOS 경계를 정확히 학습하지 못함

가설 C: 소스별 품질 편차 → 확인 (간접)

  • prepare_sft_data.py 기준: KOR-OpenOrca-Platypus-v3 5배 업샘플링, kovast 0.8배 다운샘플링
  • 가중치가 매우 공격적 (5.0배는 동일 데이터 5회 반복 = 과적합 위험)
  • kovast는 멀티턴 대화에서 첫 턴만 추출 → 문맥 부족으로 이상한 output 가능
  • 결론: 5배 업샘플링된 OpenOrca-Platypus가 주 학습 데이터를 지배. 해당 소스에 문제가 있으면 전체 모델에 직접 영향.

🔍 추가 발견: 반복 루프의 진짜 원인 추정

EOS 학습 실패가 핵심. 원인 조합:

  1. Output 내 </s> 리터럴 (113건) → EOS 경계 혼란
  2. 짧은 output 10.4% → EOS 타이밍 학습 불안정
  3. 5000 steps로 159K 데이터 학습 → 각 샘플 평균 1.6 epoch도 안 됨 → underfitting 가능
  4. inference 시 repetition_penalty 미적용 (eval 코드에는 top_p/top_k만 있고 repetition_penalty 없음)

4. 즉시 적용 가능한 데이터 필터링 코드

"""
enhanced_quality_filter.py — SFT 데이터 품질 강화 필터
Usage: python enhanced_quality_filter.py data/sft/train.jsonl data/sft/train_cleaned.jsonl
"""
import json
import re
import sys

def enhanced_filter(sample: dict) -> bool:
    instruction = sample.get("instruction", "").strip()
    output = sample.get("output", "").strip()
    
    # 1. 기본 길이 필터 (강화)
    if len(output) < 80:  # 50 → 80으로 상향
        return False
    if len(output) > 3000:  # 4000 → 3000으로 하향
        return False
    if len(instruction) < 15:
        return False
    
    # 2. 특수 토큰 제거
    BAD_TOKENS = ["</s>", "<|endoftext|>", "<|end|>", "<s>", "<pad>", "[PAD]", "<unk>"]
    for tok in BAD_TOKENS:
        if tok in output:
            return False
    
    # 3. Q/A 마커 오염 제거
    QA_PATTERNS = [
        r"###\s*(질문|답변|Instruction|Response|Input|Output)\s*:",
        r"^(질문|답변)\s*:",  # 줄 시작에서 "질문:" "답변:"
    ]
    for pat in QA_PATTERNS:
        if re.search(pat, output, re.MULTILINE):
            return False
    
    # 4. 한국어 비율 강화 (30% → 40%)
    ko_chars = sum(1 for c in output if '\uac00' <= c <= '\ud7a3')
    if len(output) > 0 and ko_chars / len(output) < 0.4:
        return False
    
    # 5. N-gram 반복 필터 (강화)
    words = output.split()
    if len(words) > 15:
        # 5-gram 반복 체크
        fivegrams = [tuple(words[i:i+5]) for i in range(len(words) - 4)]
        if fivegrams:
            unique_ratio = len(set(fivegrams)) / len(fivegrams)
            if unique_ratio < 0.7:  # 30% 이상 반복이면 제거
                return False
    
    # 6. "EOS" 리터럴 제거
    if re.search(r'\bEOS\b', output):
        return False
    
    return True


def main():
    input_path = sys.argv[1]
    output_path = sys.argv[2]
    
    kept, dropped = 0, 0
    with open(input_path) as fin, open(output_path, "w") as fout:
        for line in fin:
            sample = json.loads(line)
            if enhanced_filter(sample):
                fout.write(line)
                kept += 1
            else:
                dropped += 1
    
    print(f"Kept: {kept:,} | Dropped: {dropped:,} | Drop rate: {dropped/(kept+dropped)*100:.1f}%")


if __name__ == "__main__":
    main()

5. 데이터 파이프라인 개선 권장사항

5.1 가중치 재조정

현재 가중치가 너무 공격적. 권장 변경:

DATASET_WEIGHTS = {
    "KOR-OpenOrca-Platypus-v3": 2.0,   # 5.0 → 2.0 (과적합 방지)
    "kullm-v2":                 1.0,
    "ko-alpaca-12k":            1.5,   # 2.0 → 1.5
    "korean_safe_conversation": 1.0,   # 1.5 → 1.0
    "evol-instruct-korean":     1.5,
    "kovast":                   0.5,   # 0.8 → 0.5 (품질 이슈)
}

5.2 학습 설정 수정

# 현재: 5000 steps, batch 4×8×2 = 64
# 159K samples / 64 = 2,486 steps/epoch → 현재 약 2 epochs

# 권장: 필터링 후 ~120K 데이터로 3 epochs
MAX_STEPS=6000

5.3 Inference 시 repetition_penalty 추가

# eval/comprehensive_eval.py 수정
repetition_penalty = 1.2  # 반복 억제

6. 추천 고품질 데이터셋 (HuggingFace)

데이터셋 URL 설명 예상 크기
Open-Orca Korean kyujinpy/KOR-OpenOrca-Platypus-v3 이미 사용 중 -
ShareGPT Korean junelee/sharegpt_deepl_ko ShareGPT 한국어 번역 ~90K
KoAlpaca v1.1 beomi/KoAlpaca-v1.1a 고품질 한국어 Alpaca ~21K
LIMA Korean HAERAE-HUB/KMMLU 한국어 벤치마크 (평가용) -
Korean HC3 heegyu/korean_chatgpt_corpus ChatGPT 한국어 대화 ~12K
Orca DPO Korean kyujinpy/orca_dpo_pairs_ko DPO 페어 (SFT+DPO 가능) ~12K
OpenHermes 2.5 Ko maywell/ko_Ultrafeedback_binarized 한국어 Ultrafeedback ~60K
KOpen-platypus kyujinpy/KOpen-platypus 한국어 Platypus ~25K

가장 추천하는 추가 데이터:

  1. junelee/sharegpt_deepl_ko — 다양한 주제의 멀티턴 대화, 충분히 긴 output
  2. heegyu/korean_chatgpt_corpus — ChatGPT 품질 한국어 답변
  3. beomi/KoAlpaca-v1.1a — 검증된 한국어 instruction 데이터

7. 요약: 즉시 조치 사항

우선순위 조치 예상 효과
🔴 P0 </s>, `< endoftext
🔴 P0 Output 최소 길이 80자로 상향 짧은 답변으로 인한 EOS 미학습 방지
🔴 P0 Inference에 repetition_penalty=1.2 추가 즉시 반복 루프 완화
🟡 P1 Q/A 마커 포함 샘플 제거 (~550건) 자체 Q/A 루프 패턴 학습 방지
🟡 P1 OpenOrca 가중치 5.0 → 2.0 과적합 방지, 다양성 확보
🟡 P1 한국어 비율 필터 40%로 강화 한국어 일관성 향상
🟢 P2 추가 고품질 데이터셋 수집 전반적 품질 향상
🟢 P2 Self-repetition 필터 강화 (5-gram, 70% threshold) 반복 패턴 원천 차단

예상 필터링 후 데이터: ~120,000-130,000 샘플 (현재 대비 18-25% 제거)