原始資料從來都不乾淨
在前兩篇指南裡,你已經認識了什麼是資料集,見過了特徵與標籤,也把資料切成了訓練、驗證、測試三份。但那次劃分假設了一張行列整齊的表格。真實資料幾乎從不這麼乖。問卷裡有空著沒填的題;感測器一斷線就把溫度記成 -999;某一欄寫著「Yes/No」,另一欄卻混著「yes」「y」和「YES」。在模型能學到任何東西之前,總得有人先把這張表整治得誠實可靠。這項工作就是資料清洗,而在大多數真實專案裡,它吃掉的時間遠比建模本身還多。
先弄清楚「乾淨」到底指什麼會很有幫助。一張乾淨的表,每一欄只有一個含義,每一列只對應你所研究的一個對象,單位統一,而且每個值都名副其實。清洗就是為達到這種狀態而做的那些不起眼的手藝活:揪出不可能的取值、統一拼寫、修正單位,並決定如何處置那些必然存在的缺口。這裡頭沒有什麼高深數學,但每一步都決定了你之後的模型,是建在磐石上還是建在沙地上。
缺失值:別一刪了之
最常見的毛病是空洞——某個值壓根就不在那裡。偷懶的做法是把每一列有缺口的都刪掉,但這可能丟掉你大部分資料,更糟的是它可能帶來偏差:如果低收入者更常跳過薪資那一題,刪掉這些列就悄悄把你的資料集向富裕人群傾斜了。更穩妥的替代方案是 插補——用一個合理的猜測把缺口填上。最簡單的猜測,對數值是用該欄的均值或中位數,對類別是用該欄出現最多的取值。
但值為什麼會缺?有時純粹是隨機雜訊(表單頁面卡了一下)。有時這種「缺」本身就是一個信號——空白的「最近一次購買日期」也許意味著這位顧客從未買過任何東西。這種情況下,誠實的做法不是憑空編一個數字,而是加一個標記欄「這裡原本是缺失的嗎?」,好讓模型能利用「缺失」這件事本身。對數值來說,中位數通常比均值更穩妥,因為少數幾個極端值就能把均值拽得離典型值很遠——而這些極端值,正好把我們引向下一個問題。
離群點:是錯誤,還是重要的罕見情形?
離群點是指遠在常見範圍之外的取值——年齡登記成 200 歲的人、標價一美元的房子、一筆一千萬的交易。最關鍵的第一個問題是:*為什麼*。200 歲幾乎肯定是錄入錯誤,應當更正或剔除。但一筆真實存在的巨額交易,也許恰恰就是你的模型本該抓出來的那樁詐欺。僅僅因為它「看著怪」就刪掉,反而會把你最需要的信號一筆勾銷。
所以要把離群點的處理當成一項決策,而非條件反射。如果它明顯不可能,就更正或刪除。如果它真實但極端,你還有更溫和的選擇:把它截頂到一個合理的上限(把所有超過第 99 百分位的值「裁剪」到那個百分位),或者對整欄做變換(取對數能把一長串大值的尾巴拽回到大部隊附近)。目的從來不是把資料弄得更好看——而是不讓區區幾個點主宰模型學到的一切。
把數值放到同一把尺上
設想兩個特徵:年齡(大致 0–100)和年收入(大致 0–1,000,000)。在許多演算法眼裡,收入僅僅因為數字更大就顯得「大」了一千倍,於是把年齡完全蓋了過去——哪怕年齡其實更重要。對策就是特徵縮放:重寫各欄,讓它們的量級彼此可比。對基於距離的方法(k 近鄰)、基於梯度的訓練、以及任何帶正則化的方法來說,這一步不是可選項;少了它,模型就被你隨手選的單位悄悄帶偏了。
歸一化與標準化之下有兩個主力配方。歸一化(最小-最大縮放)把一欄壓進固定區間,通常是 0 到 1:減去最小值,再除以全距。標準化則把一欄重新縮放成均值為 0、標準差為 1:減去均值,再除以標準差。歸一化能把數值約束在整齊的範圍內,但對離群點敏感(一個巨大的值就會把整個區間撐開);標準化對離散程度的處理更從容,也是更常用的預設選項。兩者都不改變資料的*形狀*——只改變它的尺度。
# Standardize, the leak-free way mean, std = compute_on(train) # fit on TRAIN only train = (train - mean) / std val = (val - mean) / std # reuse train's numbers test = (test - mean) / std # never refit here
把類別變成數字
縮放的前提是數字,可有很多欄裝的是文字:城市、血型、產品類別。分清類別特徵與數值特徵的區別,就贏了一半。數值特徵帶有真實的順序和算術意義——30 度確實比 20 度熱,而且差距正好是 10。類別特徵則是標籤:「紅」「藍」「綠」之間沒有內在順序,藍也絕不是紅的「兩倍」。有些類別是有序的(小 < 中 < 大)——那叫定序,你可以把它映射成名次。但大多數並非如此。
經典陷阱是把「紅=1、藍=2、綠=3」這樣標上去再餵進模型。於是模型就以為綠 > 藍 > 紅,還以為藍恰好落在正中間——這套虛構的關係,是你不經意間自己造出來的。誠實的解法是 獨熱編碼:把一個類別欄拆成好幾個「是/否」欄,每個取值佔一欄。某一列是「藍」,就變成 是紅=0、是藍=1、是綠=0。沒有假的順序,沒有假的距離——只是為每一種可能性立一個明確無誤的標記。
黃金法則:在訓練集上擬合,再套用到所有資料
這裡的每一步——插補值、縮放的均值與標準差、離群點的截頂界限,乃至「到底存在哪些類別」——都是從資料中學來的參數。還有一條鐵律,把本篇指南和你的資料劃分牢牢綁在一起:這些參數只能從訓練集學,然後把凍結下來的結果套用到驗證集和測試集。一旦偷看了測試集的統計量,你就讓答案滲進了準備階段;分數會好看得不行,到了真實世界卻轟然崩塌。這是整條流水線裡最常見的新手錯誤,沒有之一。
- 先理解空洞:在填補任何東西之前,先弄清每個值*為什麼*會缺。
- 逐類排查離群點——更正不可能的,保留有意義的罕見值,對其餘的溫和地截頂或變換。
- 對類別欄做獨熱編碼;對數值欄做縮放或標準化。
- 每一種變換都在訓練資料上擬合,再把完全相同的那組數字套用到驗證集和測試集。
清洗談不上光鮮,也很少有「徹底完工」的時候——隨著你對問題理解加深,還會一次次回頭打磨它。但好模型的勝負,往往就在這裡悄悄分曉。手握一張乾淨、縮放過、誠實編碼過的表格,你就為下一步做好了準備:把現有的這些欄,雕琢成能讓模型*更容易*看出規律的特徵。