Field Log · Entry
LLM 사전학습 데이터 파이프라인: 수집·정제·중복 제거·혼합 (1/10)
오늘의 결론
- 사전학습 dataset은 파일 묶음이 아니라 출처와 정책, 변환 이력을 보존하는 versioned data product입니다.
- 문서 품질 필터 하나보다 provenance, exact·near deduplication, benchmark contamination, mixture, tokenizer, packing의 연쇄가 중요합니다.
- “깨끗한 데이터”는 단일 점수가 아닙니다. 품질·대표성·privacy·안전·라이선스·재현성 사이의 명시적 정책입니다.
- 모든 제거에는 reason code와 sample audit이 필요하고, 모든 학습 token은 가능한 범위에서 원문 record까지 역추적되어야 합니다.
- 최종 판단은 필터 점수가 아니라 작은 model의 held-out loss, downstream slice, memorization·risk 평가로 검증합니다.
앞 글까지 우리는 RAG system을 검색·근거·trajectory 단위로 평가했습니다. 이번 시리즈에서는 한 층 아래로 내려갑니다.
RAG Agent가 호출하는 기반 LLM은 어디에서 능력과 습관을 얻었을까요?
pretraining data
→ next-token prediction
→ base model
→ instruction / preference tuning
→ quantization / serving
→ RAG Agent
첫 단추는 model architecture가 아니라 학습 token이 만들어지는 과정입니다.
그림 1. 파이프라인의 각 단계는 입력·출력 hash, 정책 version, 제거 reason, 통계를 남긴다. 최종 shard만 보관하면 재현·삭제·오염 감사가 불가능하다.
사전학습 Dataset은 왜 “많은 텍스트”가 아닌가
웹 페이지 10억 개를 저장했다고 dataset이 완성되지는 않습니다.
같은 원문이 복제되어 있을 수 있고, navigation·광고·cookie banner만 남을 수 있습니다. 개인정보나 secret이 섞일 수 있고, 평가 정답이 통째로 들어 있을 수도 있습니다. 언어와 domain 비율은 raw volume에 끌려갑니다.
실제 학습 입력은 여러 변환을 거친 결과입니다.
raw bytes
≠ parsed document
≠ accepted document
≠ deduplicated document
≠ sampled document
≠ token sequence
≠ packed training sample
각 등호가 아닌 지점에서 정보가 사라집니다. 그래서 변환 전후를 연결하는 lineage가 필요합니다.
먼저 Artifact를 구분하자
1. Source Snapshot
수집 시점의 원본에 가까운 불변 입력입니다.
type SourceSnapshot = {
snapshotId: string;
sourceUri: string;
fetchedAt: string;
collectorVersion: string;
contentHash: string;
mediaType: string;
licenseEvidence?: string;
consentBasis?: string;
accessPolicy: string;
rawObjectUri: string;
};
같은 URL도 시간에 따라 내용이 달라집니다. URL만 기록해서는 재현할 수 없습니다.
2. Document Record
Parser가 만든 논리 문서입니다.
type DocumentRecord = {
documentId: string;
snapshotId: string;
text: string;
title?: string;
language?: string;
sourceDomain: string;
contentHash: string;
parserVersion: string;
normalizationVersion: string;
metadata: Record<string, string>;
};
3. Decision Record
문서를 유지·수정·격리·제거한 이유입니다.
type DataDecision = {
documentId: string;
action: "keep" | "redact" | "quarantine" | "drop";
reasonCodes: string[];
policyVersion: string;
modelVersions: string[];
scores: Record<string, number>;
decidedAt: string;
};
4. Training Sample
Tokenizer와 packing을 거쳐 optimizer가 보는 단위입니다.
type TrainingSample = {
sampleId: string;
tokenIds: number[];
lossMask: number[];
sourceDocumentIds: string[];
sourceTokenSpans: Array<[number, number]>;
tokenizerVersion: string;
packingVersion: string;
split: "train" | "validation" | "test";
};
이 네 artifact를 한 테이블에 덮어쓰면 나중에 “왜 이 token이 들어갔는가?”에 답할 수 없습니다.
0단계: 목적과 정책을 먼저 쓴다
수집기를 만들기 전에 dataset card 초안을 씁니다.
dataset_intent:
target_capabilities:
- korean_and_english_general_language
- software_engineering
- grounded_tool_use_prerequisites
excluded_uses:
- medical_diagnosis_without_review
- identity_inference
source_policy:
require_provenance: true
unknown_license: quarantine
private_or_authenticated_content: deny
deletion_contact: [email protected]
risk_policy:
direct_identifiers: redact_or_drop
credentials_and_secrets: drop
malware_payloads: quarantine
benchmark_overlap: quarantine_and_report
“인터넷에 공개되어 있다”와 “학습에 사용해도 된다”는 같은 문장이 아닙니다. 라이선스·저작권·privacy·계약 판단은 관할과 사용 목적에 따라 달라지므로 법률 자문을 model이나 heuristic으로 대신해서는 안 됩니다.
Engineering이 할 일은 결정 근거를 추적 가능하게 만드는 것입니다.
Source Registry
| 필드 | 질문 |
|---|---|
| owner | 누가 source를 책임지는가? |
| acquisition | 어떤 crawler·API·dump로 얻었는가? |
| time | 언제 어떤 version을 받았는가? |
| license evidence | 어떤 문서와 판단을 근거로 허용했는가? |
| privacy class | public·restricted·private 중 무엇인가? |
| deletion route | 제거 요청 시 어떤 shard까지 찾아가는가? |
| retention | raw snapshot을 언제까지 보관하는가? |
Unknown은 allow의 다른 이름이 아닙니다. quarantine이라는 별도 상태가 필요합니다.
1단계: Raw Snapshot을 불변으로 저장한다
정제된 text만 저장하면 parser bug를 고쳐도 다시 처리할 원본이 없습니다.
raw/{source}/{snapshot_date}/{content_hash}
derived/{pipeline_version}/{document_id}
Raw zone과 derived zone을 분리합니다.
- Raw: write-once, access restricted, retention policy 적용
- Derived: 언제든 같은 code와 manifest로 재생성
- Quarantine: 일반 학습 경로와 권한 분리
- Tombstone: 삭제 대상과 영향을 받은 artifact 기록
원본 보관도 무제한이 답은 아닙니다. Privacy와 retention 요구를 함께 적용합니다.
Content-addressed ID
snapshot_id = hash(source_id || fetched_at || raw_bytes)
document_id = hash(snapshot_id || parser_version || normalized_text)
충돌에 안전한 hash를 사용하고 algorithm 이름도 manifest에 기록합니다. 같은 text라도 source provenance를 잃지 않도록 content hash와 record ID를 구분합니다.
2단계: Parsing과 Normalization
HTML, PDF, code repository, forum dump는 같은 parser를 쓰지 않습니다.
HTML
- main content와 navigation·footer·cookie banner 분리
- title, heading, list, table 구조 보존
- hidden text와 script 제거 정책
- canonical URL과 publication time 보존
- reading order와 page boundary 보존
- header·footer 반복 제거
- table·formula·caption 처리
- OCR confidence와 scanned/native 구분
Code
- repository·commit·path·license lineage
- generated file, vendored dependency, minified artifact 구분
- secret scan을 parsing 직후 수행
- file boundary와 language metadata 보존
Unicode Normalization
무조건 모든 문자를 한 형태로 바꾸면 code, 수식, identifier 의미를 훼손할 수 있습니다.
normalize only with an explicit policy
→ preserve original bytes
→ record normalization form
→ measure changes by language and domain
공백 정리도 마찬가지입니다. Python indentation이나 Markdown code block은 연속 공백이 의미를 가집니다.
3단계: 언어와 Script를 측정한다
Language ID는 단일 label이 아닐 수 있습니다.
{
"document_id": "doc-91",
"language_distribution": {
"ko": 0.62,
"en": 0.31,
"other": 0.07
},
"scripts": ["Hangul", "Latin"],
"code_ratio": 0.18
}
한국어 기술 문서는 영문 API 이름과 code가 많이 섞입니다. “한 문서 한 언어” classifier가 mixed document를 저품질로 버릴 수 있습니다.
다음을 slice별로 봅니다.
- language와 script 비율
- 문서·문단 단위 confidence
- 짧은 문서의 오분류율
- code·수식·이름이 많은 문서
- tokenizer fertility와 결합한 효율
4단계: Quality Filter를 계층화한다
Quality는 하나의 score로 환원하기 어렵습니다.
Layer A. Deterministic Sanity Check
- decode 실패
- 빈 문서
- 지나치게 짧거나 긴 문서
- 제어 문자 비율
- 반복 문자·반복 line 비율
- boilerplate 비율
- 비정상 markup
Layer B. Heuristic Features
- 단어·문장 길이 분포
- alphabetic·numeric·punctuation 비율
- stopword 존재
- 문장 종결 패턴
- heading·paragraph 구조
- link·advertisement density
Layer C. Learned Classifier
Human-curated positive·negative sample로 학습한 classifier를 사용할 수 있습니다. 그러나 classifier가 선호하는 style을 dataset 전체에 강제할 위험이 있습니다.
Layer D. Sampled Human Audit
통과·탈락 양쪽에서 stratified sample을 뽑아 false positive와 false negative를 측정합니다.
filter precision alone is insufficient
also measure:
what valuable data did we remove?
which groups and domains were removed more often?
DataComp-LM은 고정된 training recipe 아래 data curation 방법을 비교하는 testbed를 제시합니다. 중요한 메시지는 특정 filter가 영원한 정답이라는 것이 아니라, data decision을 통제된 학습 실험으로 비교해야 한다는 점입니다.
5단계: Privacy·Secret·Safety Gate
품질이 높은 문서도 학습에 부적절할 수 있습니다.
PII를 한 종류로 보지 않는다
| 범주 | 예 | 가능한 처리 |
|---|---|---|
| direct identifier | 주민번호, 계좌, 개인 전화번호 | drop 또는 검증된 redact |
| quasi-identifier | 희귀한 직장·지역·날짜 조합 | context별 risk review |
| public professional info | 공식 저자·소속 | source policy에 따라 유지 |
| sensitive attribute | 건강·성적·정치 정보 | 강화된 제한·제거 |
Redaction token 자체가 위치와 형태를 누설할 수 있습니다. 잘못된 redact가 문서 의미를 깨뜨리는지도 sample audit합니다.
Secret Scan
- API key pattern
- private key block
- cloud credential
- database URI
- access token
- password dump marker
Pattern match만으로 충분하지 않지만, 명확한 secret은 학습 전에 제거해야 합니다. 발견된 credential을 검증하기 위해 실제 endpoint에 사용해서는 안 됩니다.
Safety는 “나쁜 단어 제거”가 아니다
보안·의학·역사 문서는 위험한 표현을 교육적으로 포함할 수 있습니다. 단어 blacklist만 쓰면 유용한 방어 문서를 버리고, 우회 표현의 실제 위험 문서는 남깁니다.
content category + intent + provenance + expected use
→ allow / restricted / quarantine / drop
6단계: Exact Deduplication
동일한 content hash를 가진 record를 묶습니다.
exact_cluster_id = hash(canonical_normalized_text)
하지만 representative를 하나 남길 때 provenance를 지우면 안 됩니다.
{
"cluster_id": "exact-17",
"representative_document_id": "doc-a",
"member_document_ids": ["doc-a", "doc-b", "doc-c"],
"source_domains": ["original.example", "mirror.example"],
"selection_rule": "earliest_authoritative_source"
}
Exact duplicate는 쉽지만 normalize 범위를 잘못 잡으면 다른 code나 숫자를 같은 것으로 만들 수 있습니다.
7단계: Near Deduplication
웹 복제 문서는 광고 한 줄, 날짜, template만 달라 exact hash가 다릅니다.
Shingle
문서를 연속된 token 또는 character n-gram 집합으로 바꿉니다.
"RAG는 외부 문서를 검색한다"
3-token shingles:
[RAG는 외부 문서를]
[외부 문서를 검색한다]
두 집합의 Jaccard similarity는 다음과 같습니다.
J(A, B) = |A ∩ B| / |A ∪ B|
모든 문서 쌍을 직접 비교하면 문서 수의 제곱에 가깝게 커집니다. MinHash는 Jaccard similarity를 근사하는 짧은 signature를 만들고, LSH는 비슷한 signature를 candidate bucket에 모읍니다.
documents
→ shingles
→ MinHash signatures
→ LSH candidate pairs
→ exact similarity check
→ duplicate clusters
Threshold는 Dataset마다 검증한다
0.8 같은 threshold를 보편 법칙으로 쓰지 않습니다.
- 짧은 문서는 우연히 겹치기 쉽습니다.
- 법령·약관은 template가 같고 핵심 숫자만 다를 수 있습니다.
- code는 boilerplate가 많습니다.
- 번역문은 semantic duplicate지만 lexical overlap이 낮습니다.
Threshold 주변 sample을 human audit하고, domain별 threshold나 별도 feature를 고려합니다.
어디까지 Dedup할까
within snapshot
within source across time
across sources
across train / validation
across train / benchmarks
Cross-source dedup에서 권위 있는 원본을 남길 수 있도록 source priority와 time을 사용합니다.
Lee et al.의 deduplication 연구는 학습 data의 near duplicate가 memorization과 train-test overlap에 연결될 수 있고, 연구 설정에서 deduplication이 효율과 품질을 개선했음을 보였습니다. 이를 “중복은 무조건 모두 제거”로 과장해서는 안 됩니다. 의도적 반복이 필요한 domain도 있으므로 cluster와 sampling policy를 분리해야 합니다.
8단계: Benchmark Contamination Firewall
평가 문제와 정답이 train data에 들어가면 model 능력이 아니라 기억을 측정할 수 있습니다.
가장 중요한 순서는 다음입니다.
1. evaluation set을 먼저 lock한다
2. benchmark record의 hash와 searchable fingerprints를 만든다
3. train candidate와 exact / n-gram / near overlap을 검사한다
4. 의심 record를 quarantine한다
5. benchmark별 overlap report를 남긴다
6. 평가 결과와 함께 contamination policy를 공개한다
무엇을 비교할까
- question exact match
- answer exact match
- question+answer 긴 n-gram
- option 순서가 바뀐 multiple-choice
- paraphrase·translation near match
- benchmark 해설·정답 페이지
- code test와 canonical solution
Semantic similarity만으로 자동 삭제하면 같은 주제를 다룬 정상 문서까지 제거할 수 있습니다. 자동 탐지와 sampled adjudication을 결합합니다.
오염을 조용히 지우지 않는다
{
"benchmark": "example-eval-v3",
"train_candidate_count": 840000000,
"exact_overlap": 12,
"near_overlap_reviewed": 91,
"confirmed_contamination": 27,
"action": "quarantine",
"detector_version": "contam-2.4.1"
}
나중에 benchmark version이 바뀌면 detector를 다시 실행해야 합니다.
9단계: Data Mixture는 Sampling Distribution이다
정제 후 source A가 10TB, B가 1TB라고 해서 A를 10배 자주 학습해야 하는 것은 아닙니다.
raw byte ratio
≠ document ratio
≠ token ratio
≠ sampling probability
≠ learning contribution
Domain별 token 수를 n_d, sampling weight를 w_d라 하면 단순한 mixture는 다음처럼 표현할 수 있습니다.
p(d) = w_d / Σ_j w_j
Temperature sampling의 한 형태는 다음입니다.
p(d) ∝ n_d^α
α = 1 → raw token 비율에 가까움
α < 1 → 작은 domain을 상대적으로 upsample
단, 작은 corpus를 과도하게 반복하면 memorization이 증가합니다.
Mixture Manifest
mixture_id: pretrain-mix-v7
seed: 20260716
domains:
- name: curated_korean
dataset_version: ko-v4
available_tokens: 120000000000
target_probability: 0.22
max_epochs: 2.0
- name: english_web
dataset_version: web-v9
available_tokens: 900000000000
target_probability: 0.38
max_epochs: 0.8
- name: code
dataset_version: code-v5
available_tokens: 210000000000
target_probability: 0.20
max_epochs: 1.5
- name: books_and_reference
dataset_version: ref-v3
available_tokens: 160000000000
target_probability: 0.20
max_epochs: 1.2
위 수치는 예시이지 권장 비율이 아닙니다. 목표 능력, tokenizer, model scale, budget, source policy에 맞춰 pilot으로 결정합니다.
DoReMi는 작은 proxy model과 group DRO를 사용해 domain weight를 학습한 뒤 큰 model data mixture에 적용하는 접근을 제안했습니다. 논문의 특정 개선 수치는 해당 dataset과 실험 조건의 결과이며, 어떤 corpus에도 같은 배율을 보장하지 않습니다.
10단계: Train·Validation·Test Split
Random document split은 복제와 시간 leakage를 만들 수 있습니다.
Group Split
다음을 같은 group으로 묶은 뒤 split합니다.
- duplicate cluster
- source article과 mirror
- 같은 repository 또는 project
- 같은 author·series
- 같은 event의 update chain
Time Split
미래 일반화나 freshness를 평가하려면 cutoff 이후 문서를 validation/test로 둡니다.
train: published_at < 2025-01-01
validation: 2025-01-01 ≤ published_at < 2025-04-01
test: 2025-04-01 ≤ published_at < 2025-07-01
수집 시각과 작성 시각은 다릅니다. 두 timestamp를 모두 보존합니다.
Validation도 Dedup한다
Train과 validation이 near duplicate면 validation loss가 과도하게 낙관적입니다. Split 이후가 아니라 cluster를 만든 뒤 split해야 합니다.
11단계: Tokenizer Audit
같은 문장도 tokenizer에 따라 token 수가 다릅니다.
Fertility
fertility = token count / linguistic unit count
언어별 word boundary가 다르므로 절대값보다 일관된 기준과 slice 비교가 중요합니다.
확인할 항목은 다음과 같습니다.
- 언어·script별 token/character
- code language별 token/byte
- 숫자·날짜·URL 분절
- emoji와 rare Unicode
- byte fallback 비율
- invalid replacement character
- special token collision
- normalization 전후 token 변화
Tokenizer가 한국어를 비효율적으로 쪼개면 같은 context window에 더 적은 의미를 담고 학습 compute도 더 씁니다.
Tokenizer Train Data도 Versioning한다
Tokenizer vocabulary 자체가 data distribution의 산물입니다.
tokenizer:
algorithm: example-bpe
vocab_size: 64000
training_sample_manifest: tok-sample-v3
normalization: NFC
special_tokens:
bos: 1
eos: 2
pad: 0
artifact_hash: sha256:...
Model checkpoint와 tokenizer artifact를 분리 배포하거나 잘못 조합하면 token ID 의미가 바뀝니다.
12단계: Sequence Packing
짧은 문서를 context length에 맞게 이어 붙이면 padding 낭비를 줄일 수 있습니다.
context length = 16
doc A: [a a a EOS]
doc B: [b b b b b EOS]
doc C: [c c EOS]
packed:
[a a a EOS b b b b b EOS c c EOS PAD PAD PAD]
반드시 결정할 것
- 문서 사이 EOS 삽입
- 다른 문서 token끼리 attention을 허용할지
- boundary 다음 token loss를 계산할지
- 긴 문서 truncation·windowing 방식
- leftover를 다음 shard로 넘길지
- packing seed와 order
- sample에서 원문 span으로 역매핑
일반적인 causal LM에서는 이전 token을 보고 다음 token을 예측합니다. 문서 경계가 불명확하면 B의 첫 token이 A의 끝과 인위적으로 연결됩니다.
Packing Efficiency
packing_efficiency
= non_padding_tokens / total_sequence_slots
효율만 최대화하면 특정 source가 같이 묶이는 pattern이나 긴 문서의 과도한 truncation을 놓칠 수 있습니다.
13단계: Sharding과 Determinism
Training shard는 단순히 파일 크기로만 나누지 않습니다.
{
"shard_id": "train-000417",
"format": "example-binary-v2",
"sample_count": 18321,
"token_count": 2147483648,
"content_hash": "sha256:...",
"mixture_id": "pretrain-mix-v7",
"tokenizer_hash": "sha256:...",
"packing_version": "pack-3.2.0",
"seed": 20260716
}
재현 가능하다는 말은 같은 input과 code에서 같은 sample order와 shard hash가 나오는 것을 뜻합니다.
병렬 처리에서 흔한 비결정성은 다음과 같습니다.
- map iteration order
- worker 완료 순서
- floating-point classifier threshold 경계
- nondeterministic compression metadata
- 시간값이 포함된 output
- seed가 없는 shuffle
Manifest에는 container image, dependency lock, code commit도 포함합니다.
14단계: 삭제 가능성을 설계한다
삭제 요청이 왔을 때 raw object만 지우면 derived shard와 checkpoint 영향은 남습니다.
source record
→ parsed document
→ dedup cluster
→ packed sample
→ training shard
→ training run
→ model checkpoint
Lineage graph는 적어도 어느 dataset version과 training run이 영향을 받았는지 보여야 합니다.
Model에서 특정 data의 영향을 제거하는 문제는 dataset 삭제와 별개의 machine unlearning 문제입니다. “원본 파일 삭제”를 “model이 잊음”과 동일시하지 않습니다.
15단계: Synthetic Data도 Source다
Model이 생성한 text는 provenance가 없는 무료 data가 아닙니다.
type SyntheticProvenance = {
generatorModel: string;
generatorCheckpoint: string;
promptTemplateHash: string;
decodingConfig: Record<string, number | string>;
seed?: number;
sourceRecordIds: string[];
verifierVersions: string[];
generatedAt: string;
};
확인할 위험은 다음과 같습니다.
- generator의 오류와 style 반복
- 답을 포함한 benchmark prompt 재생성
- 원 source 라이선스·privacy의 승계 문제
- model collapse와 diversity 저하
- verifier와 generator의 동일한 blind spot
Synthetic과 human-origin data를 구분해 mixture와 평가 slice를 보고합니다.
Filter가 좋아졌는지 어떻게 아는가
최종 token count가 줄었다고 좋아진 것이 아닙니다.
Data Metric
- source·language·domain별 yield
- removal reason distribution
- duplicate cluster 크기와 tail
- PII·secret 발견률과 sampled false-negative
- contamination confirmed count
- tokenizer fertility
- packing efficiency
- source repetition과 effective epochs
Model Metric
- held-out loss와 perplexity
- 목표 downstream task
- language·domain별 slice
- memorization probe
- privacy·toxicity·security evaluation
- calibration과 robustness
- training stability
Small-Scale Ablation
baseline corpus → small model B
candidate corpus → same-size small model C
freeze:
architecture
tokenizer
token budget
optimizer
schedule
evaluation suite
random seeds where feasible
compare:
held-out loss
downstream slices
memorization / risk
compute and data yield
Model size가 달라지면 data effect도 완전히 같다고 보장할 수 없습니다. 그래서 proxy 결과를 큰 run의 확정 답이 아니라 risk-reduction evidence로 사용합니다.
운영 Dashboard
Funnel
raw snapshots 100.0%
parse success 96.8%
policy-eligible 82.4%
quality accepted 61.7%
deduplicated representatives 47.1%
contamination-safe 47.0%
sampled into mixture 39.3%
packed non-padding tokens 38.6%
전체 평균만 보면 안 됩니다. Source·language·domain·time별 funnel을 나눕니다.
Alert 예시
alerts:
- metric: parse_success_rate
condition: drop_more_than_2_percent_vs_previous_snapshot
- metric: korean_filter_rejection_rate
condition: exceeds_english_by_15_percent_without_review
- metric: secret_scan_confirmed
condition: greater_than_zero_in_training_shards
- metric: benchmark_overlap_confirmed
condition: greater_than_zero_after_quarantine
- metric: lineage_coverage
condition: below_100_percent
흔한 실패와 처방
1. 모든 것을 Quality Score 하나로 정렬한다
점수가 style, 언어, 길이에 대한 hidden policy가 됩니다.
처방: 품질·privacy·license·safety gate를 분리하고 score distribution과 removal slice를 공개합니다.
2. Dedup은 Hash 한 번이면 끝난다
Template·mirror·부분 복제는 exact hash가 다릅니다.
처방: exact와 near dedup을 분리하고 cluster lineage를 보존합니다.
3. Split 후에 Dedup한다
같은 cluster의 문서가 train과 validation으로 갈 수 있습니다.
처방: cluster를 먼저 만들고 group 단위로 split합니다.
4. 평가 오염은 Model을 학습한 뒤 찾는다
이미 비싼 run과 평가 신뢰도를 잃었습니다.
처방: benchmark를 lock하고 train candidate 단계에서 firewall을 실행합니다.
5. Raw Volume을 그대로 Sampling한다
큰 source가 목표 능력과 상관없이 학습을 지배합니다.
처방: token 기준 mixture, caps, effective epochs를 명시하고 pilot ablation으로 조정합니다.
6. 최종 Shard만 남긴다
오류 원인, 삭제 영향, 재현 경로를 찾을 수 없습니다.
처방: snapshot·record·decision·sample·shard manifest를 연결합니다.
7. Filter 통과율만 본다
가치 있는 minority language·domain을 체계적으로 제거할 수 있습니다.
처방: 통과와 탈락 양쪽을 stratified human audit하고 작은 model 결과까지 봅니다.
8. 공개 Data면 Risk가 없다
공개 페이지에도 PII, secret, restrictive terms, 삭제 요청 대상이 있습니다.
처방: 공개 여부와 사용 적합성 판단을 분리하고 근거를 source registry에 기록합니다.
최소 구현 순서
처음부터 trillion-token pipeline을 만들 필요는 없습니다.
Phase 1. 100만 문서
- source registry와 immutable snapshot
- parser별 golden test
- exact hash와 basic filter
- decision reason code
- tokenizer·packing manifest
Phase 2. 1억 문서
- MinHash/LSH near dedup
- distributed statistics
- contamination firewall
- source·language slice audit
- deletion lineage drill
Phase 3. 학습 Pilot
- baseline과 candidate corpus
- 동일 token budget의 작은 model
- held-out·downstream·memorization 평가
- mixture ablation
Phase 4. 큰 Run 전 Freeze
- dataset version
- tokenizer hash
- split and benchmark versions
- shard hashes
- training recipe
- sign-off와 rollback plan
Production 체크리스트
- Dataset 목적과 제외 use case가 문서화되어 있다.
- 모든 source에 provenance, acquisition time, policy 상태가 있다.
- Raw snapshot과 derived artifact가 분리되어 있다.
- Parser·normalizer version과 content hash를 기록한다.
- 언어·script·code 혼합 문서를 별도 audit한다.
- 품질, privacy, secret, safety, license decision을 분리한다.
-
keep,redact,quarantine,drop과 reason code가 있다. - Exact와 near dedup을 모두 수행한다.
- Dedup cluster member와 representative 선택 이유를 보존한다.
- Train·validation·benchmark 사이 overlap을 학습 전에 검사한다.
- Mixture probability와 raw token 비율을 구분한다.
- Source별 effective epoch과 repetition을 측정한다.
- Tokenizer fertility를 language·domain별로 측정한다.
- EOS, attention mask, loss mask, truncation 정책이 명시되어 있다.
- Packed sample에서 원문 document로 역추적할 수 있다.
- Shard hash, seed, code commit, container version이 manifest에 있다.
- 삭제 요청의 downstream 영향을 찾는 lineage가 있다.
- Synthetic data에 generator·prompt·source provenance가 있다.
- Filter 전후를 작은 model ablation으로 비교한다.
- Removal false positive와 risk false negative를 human audit한다.
스스로 확인하기
- Content hash와 document ID를 왜 분리해야 하는가?
- Exact dedup만으로 웹 문서 중복을 충분히 제거할 수 없는 이유는 무엇인가?
- Train·validation split보다 duplicate clustering을 먼저 해야 하는 이유는 무엇인가?
- Raw data 비율과 학습 sampling probability가 달라야 할 수 있는 이유는 무엇인가?
- Packing efficiency를 높이면서도 문서 경계와 lineage를 보존하려면 무엇을 기록해야 하는가?
- Filter score가 좋아 보여도 작은 model ablation이 필요한 이유는 무엇인가?
다음 글에서는 사전학습 목표와 Scaling Law를 다룹니다. Data와 model parameter, training compute를 어떤 비율로 늘려야 하는지, Kaplan scaling law와 Chinchilla compute-optimal 관점, 실제 serving 비용을 위해 over-training하는 경우를 구분합니다.
참고자료
- DataComp-LM: In Search of the Next Generation of Language Model Pretraining Datasets
- Dolma: An Open Corpus of Three Trillion Tokens for Language Model Pretraining Research
- The RefinedWeb Dataset for Falcon LLM
- Deduplicating Training Data Makes Language Models Better
- DoReMi: Optimizing Data Mixtures Speeds Up Language Model Pretraining
- The Data Provenance Initiative