第 1 章 · 收集與清洗 Pre-training 資料¶
本章你會學到
- Pre-training 資料到底是什麼、從哪裡來、用什麼單位衡量
- 為什麼「清洗」比「收集」還重要(垃圾進,垃圾出)
- 一條真實可用的清洗流水線:抽取 → 語言辨識 → 品質過濾 → 去重 → 去個資 → 去有害 → 去污染
- 繁體中文特別會踩到的坑(簡繁混雜、資料稀缺)
1.1 先講白話:什麼是 pre-training 資料?¶
想像你要培養一位博學的新同事。在教他做任何具體工作之前,你會先讓他把公司的圖書館、網路上的百科、報章雜誌、技術手冊……全部讀過一遍。他讀的這一大堆文字,就是 pre-training(預訓練)資料。
模型從這些文字裡,自己歸納出:
- 語言怎麼運作(文法、語氣、標點)
- 世界的常識(台北是台灣的首都、水在 100°C 沸騰)
- 各領域知識(法律、醫學、程式碼……)
重點:模型不是「查」資料,是「讀」進去變成能力
訓練完之後,這些文字並不會像資料庫一樣被存起來供查詢;它們會被「消化」成模型的能力。所以當初讀了什麼、讀得乾不乾淨,直接決定這位同事的底子。
資料量的單位是 token,不是「字數」¶
模型不是一個字一個字看,而是把文字切成 token(詞元)——大約是「一個字塊」。
- 英文:
unbelievable可能被切成un+believ+able三個 token。 - 中文:常常一個字就是一個 token,有時兩三個字一組。
現代大模型的預訓練資料動輒 數兆(trillion)個 token。(1)
- 舉例:HuggingFace 的 FineWeb 資料集約 15 兆 token;Meta 的 Llama 3 用了超過 15 兆 token 預訓練。這是「把整個網路讀很多遍」的等級。
為什麼你該記住 token?
因為資料量、訓練成本、API 費用、模型能吃多長的輸入,全部都用 token 計價與計算,不是用「幾個字」。跨部門溝通時,講 token 才對得上頻道。
1.2 資料從哪裡來?¶
| 來源 | 例子 | 特點 |
|---|---|---|
| 網頁爬取 | Common Crawl(公開的全網頁存檔) | 量最大、最髒,需要大量清洗 |
| 百科 | Wikipedia、百科全書 | 品質高、結構清楚,但量有限 |
| 書籍 / 論文 | 電子書、arXiv 論文 | 長文、深度知識,需注意版權 |
| 程式碼 | GitHub 公開 repo | 訓練「寫程式」能力的關鍵 |
| 問答 / 論壇 | Stack Overflow、PTT、Dcard | 口語、真實對話語氣 |
| 政府 / 開放資料 | 法規、公報、開放資料平台 | 正式、可信、授權清楚 |
繁體中文的現實難題:好資料很稀缺
全世界高品質的繁體中文文字,遠比英文或簡體中文少。這代表兩件事:
- 我們更需要把有限的繁中資料清乾淨、用好,一滴都不能浪費。
- 從網路撈到的「中文」常常混著簡體——若不處理,會教出一個簡繁不分、甚至用語像對岸的模型。(詳見 1.9 繁中專章)
1.3 為什麼「清洗」比「收集」還重要?¶
一句業界老話:Garbage in, garbage out(垃圾進,垃圾出)。
原始網頁裡塞滿了:導覽列、廣告、亂碼、重複複製的內容、色情與仇恨言論、別人的電話與 Email、甚至……考試的答案(這會讓後面的評測作弊)。
如果不清洗,這位新同事等於是在充滿雜訊和錯誤資訊的環境裡自學長大。
清洗是一個「漏斗」:撈得多,留得少
清洗流程會層層過濾,最後只留下一小部分精華。以 HuggingFace FineWeb 為例,從 Common Crawl 原始網頁一路過濾後,最終可用的高品質資料常常只剩不到 10%。
flowchart TD
A["🌐 原始網頁存檔<br/>Common Crawl(100%,超髒)"] --> B["① 抽正文<br/>去掉廣告/導覽列/HTML"]
B --> C["② 語言辨識<br/>只留目標語言"]
C --> D["③ 品質過濾<br/>丟掉亂碼/太短/垃圾"]
D --> E["④ 去重<br/>刪掉重複與近似內容"]
E --> F["⑤ 去個資 PII<br/>遮蔽電話/Email/身分證"]
F --> G["⑥ 去有害內容<br/>色情/仇恨/詐騙"]
G --> H["⑦ 去污染<br/>剔除評測考題"]
H --> I["✨ 乾淨語料<br/>(常常只剩 <10%)"]
style A fill:#ffebee,stroke:#c62828,color:#b71c1c
style I fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20
接下來逐步拆解這條流水線。
1.4 ① 抽取正文(Text Extraction)¶
原始網頁是一坨 HTML,裡面真正有價值的正文可能只佔一小塊,其餘是選單、廣告、頁尾、Cookie 提示……這一步要把「正文」精準摳出來。
- 常用工具:trafilatura、jusText、resiliparse、readability。
- 目標:留下文章本體,丟掉樣板(boilerplate)。
做不好會怎樣?
如果正文抽取失敗,模型會讀進一堆「立即註冊 / 加入購物車 / 上一則下一則」,學到一嘴的廣告詞。
1.5 ② 語言辨識(Language Identification)¶
把每份文件標上語言,只留下你要的(例如 zh-Hant 繁體中文)。
- 常用工具:fastText 語言辨識模型(
lid.176)、CLD3、langdetect。 - 這一步會給每份文件一個「是這個語言的信心分數」,低於門檻就丟掉。
繁中的魔鬼細節
大多數語言辨識工具只會判斷「這是中文(zh)」,不會分繁體 / 簡體。要做繁中模型,得再加一層簡繁判斷(例如用 OpenCC 比對字形,或統計簡繁特徵字)。這點非常容易被忽略。
1.6 ③ 品質過濾(Quality Filtering)¶
即使語言對了,內容也可能是亂碼、關鍵字堆砌、或毫無資訊量的垃圾。品質過濾有三種常見做法,通常會搭配使用:
用一組「常識規則」把明顯的垃圾濾掉。業界最有名的是 Gopher 規則 和 C4 規則,例如:
- 文件太短(少於 N 個字)或太長 → 丟
- 平均每個詞太長 / 太短 → 可能是亂碼
- 符號(
#、...)對文字的比例太高 → 丟 - 重複行、重複段落佔比太高 → 丟
- 含有大量「lorem ipsum」占位文字 → 丟
- 結尾有標點的句子比例太低 → 可能是清單/導覽列
def passes_quality(text: str) -> bool:
words = text.split()
n = len(words)
# 規則 1:長度要合理(太短沒資訊、太長常是灌水)
if n < 50 or n > 100_000:
return False
# 規則 2:平均詞長要像正常文字(亂碼常會爆掉)
mean_word_len = sum(len(w) for w in words) / n
if not (3 <= mean_word_len <= 10):
return False
# 規則 3:重複行佔比過高 → 多半是樣板或洗版
lines = text.splitlines()
if lines and (1 - len(set(lines)) / len(lines)) > 0.30:
return False
# 規則 4:符號 vs 文字比例(# 與 ... 太多 → 導覽列/亂碼)
symbol_ratio = (text.count("#") + text.count("...")) / max(n, 1)
if symbol_ratio > 0.10:
return False
return True
優點:極快、可解釋、免訓練。缺點:規則很「粗」,會誤殺也會漏抓。
先用乾淨文字(如 Wikipedia)訓練一個很輕量的語言模型(常用 KenLM),再拿它去「讀」每份文件:
- 讀起來很順(困惑度低) → 像正常文章 → 留。
- 讀起來很卡(困惑度高) → 像亂碼/垃圾 → 丟。
這是 Facebook CCNet 流水線的核心做法。
訓練一個小分類器來打分:
- 正例:高品質文字(維基、書籍、優質教育內容)
- 負例:隨機網頁
讓分類器學會「什麼像好內容」,再對全體資料打分、留高分的。HuggingFace 的 FineWeb-Edu 就是用一個「教育價值」分類器,篩出特別適合學習的網頁——實測能顯著提升模型表現。
給非工程師的重點
品質過濾沒有唯一標準答案,是「規則 + 統計 + 模型」多管齊下、反覆調參的工程活。每多濾掉一批垃圾,模型的底子就乾淨一分。
1.7 ④ 去重(Deduplication)¶
網路上同一篇文章常被轉貼、鏡像、複製上百次。若不去重,模型會對重複內容「死背」,浪費算力又傷害品質。
| 去重層級 | 抓什麼 | 方法 |
|---|---|---|
| 完全重複 | 一字不差的複製 | 對整份文件算雜湊值(hash),一樣就刪 |
| 近似重複 | 只改幾個字、換個標題 | MinHash + LSH、SimHash |
| 子字串重複 | 長文中夾帶的重複段落 | 後綴陣列(suffix array)精確比對 |
MinHash + LSH 是什麼?(一分鐘版)
直接兩兩比對「所有文件相不相似」會慢到天荒地老(數十億份文件)。MinHash 把每份文件壓成一小串指紋,LSH 則讓「指紋相近」的文件被快速分到同一桶,只需在桶內比對。這樣就能在可接受的時間內找出海量近似重複。
- 常用工具:text-dedup、HuggingFace datatrove。
去重也有副作用
去太兇會誤刪合理的重複(例如法律條文、常見問候語),反而傷害資料多樣性。「去到剛剛好」本身就是一門調校功夫。
1.8 ⑤⑥⑦ 去個資、去有害、去污染¶
這三步是「責任與公平」的把關,跨部門同事尤其該懂。
-
⑤ 去個資(PII Removal)
用規則 + 模型偵測並遮蔽電話、Email、身分證字號、信用卡、地址等個人資訊。
- 工具:正則表達式、Microsoft Presidio。
- 為什麼重要:涉及個資法與隱私,也避免模型「背出」某人的真實資料。
-
⑥ 去有害內容(Safety Filtering)
移除色情、仇恨、暴力、詐騙、垃圾廣告。
- 工具:黑名單(如 UT1 網址清單)+內容分類器。
- 為什麼重要:模型會模仿它讀到的東西;髒東西讀進去,就會吐出來。
-
⑦ 去污染(Decontamination)
把評測考題從訓練資料裡剔除。
- 做法:比對訓練資料與各大 benchmark 的 n-gram 重疊。
- 為什麼重要:如果考卷混進了教材,模型考高分只是作弊背答案,不代表真本事。第 3 章會再呼應這點。
去污染 = 學術誠信
你不會讓學生拿到考卷去準備期末考。去污染就是確保「訓練」和「考試」的資料井水不犯河水,評測數字才可信。
1.9 繁體中文專章:最容易踩的坑¶
做繁體中文模型時,除了上面通用流程,還要特別處理:
- 簡繁洩漏:撈到的「中文」網頁常混著簡體,或整篇是簡體轉繁的機器翻譯。若不濾除,模型會學到簡繁不分、用語不道地(例如講「軟件」而非「軟體」、「視頻」而非「影片」)。
- 對策:語言辨識後再加簡繁判斷;必要時用 OpenCC 統一,或直接丟掉高簡體比例的文件。
- 在地知識稀缺:台灣的法律、地名、歷史、流行文化,在全網語料中比例極低。
- 對策:主動蒐集台灣在地來源(政府開放資料、本地新聞、論壇),提高在地內容佔比。
- 量少所以更要乾淨:因為好的繁中資料本來就少,每一份的品質權重都更高,清洗與去重要更謹慎,避免把珍貴資料誤殺。
1.10 真實世界的資料集與工具¶
常被拿來參考的大型語料
| 語料 | 規模 | 特點 |
|---|---|---|
| Common Crawl | 全網頁存檔 | 最原始、最髒的起點 |
| C4 | ~750GB | Google 清洗過的網頁語料 |
| The Pile | ~825GB | 22 種來源混合 |
| RefinedWeb | 兆級 token | 證明「純網頁+狠清洗」也能很強 |
| FineWeb / FineWeb-Edu | ~15 兆 token | 目前最受歡迎的開源網頁語料之一 |
| Dolma | ~3 兆 token | AI2 完整開源,含清洗流程 |
把上述步驟串起來的開源框架
- datatrove(HuggingFace):模組化的大規模清洗流水線。
- Dolma toolkit(AI2):完整開源的清洗工具。
- data-juicer(阿里):上百種可組合的資料處理算子。
- CCNet(Meta):語言辨識 + 困惑度過濾的經典流程。
本章 checklist¶
拿到一批 pre-training 資料,先問自己這幾題:
- 正文有沒有抽乾淨?(沒混廣告/導覽列)
- 語言對不對?繁中有沒有濾掉簡體?
- 品質過濾做了嗎?(規則 / 困惑度 / 分類器)
- 去重了嗎?(完全重複 + 近似重複)
- 個資遮蔽了嗎?
- 有害內容移除了嗎?
- 去污染了嗎?(評測考題有沒有混進來)
小結
Pre-training 資料決定模型的底子。收集只是起點,清洗才是真功夫——它同時關乎品質、成本、法遵與評測公平性。下一章,我們看模型有了底子之後,怎麼教它「好好回話」。