器學(xué)習(xí)特征工程實(shí)戰(zhàn):從數(shù)據(jù)清洗到特征選擇的方法論)
做機(jī)器學(xué)習(xí)這幾年我越來越覺得“模型調(diào)參”遠(yuǎn)沒有“特征工程”對(duì)最終效果的影響大。很多人把項(xiàng)目時(shí)間全砸在選算法、調(diào)超參數(shù)上結(jié)果效果死活上不去實(shí)際上多數(shù)基礎(chǔ)模型只要給到合適特征效果立刻就能起來。今天這篇就想聊聊機(jī)器學(xué)習(xí)里這個(gè)最“土”但最值錢的環(huán)節(jié)——特征工程。它解決的核心問題很簡(jiǎn)單把原始數(shù)據(jù)變成模型真正能學(xué)懂、能區(qū)分規(guī)律的樣子。無論你是剛?cè)腴T想搞懂怎么處理好數(shù)據(jù)還是已經(jīng)在用 sklearn、Pandas 跑項(xiàng)目但總感覺瓶頸在數(shù)據(jù)端這篇文章都適合你慢慢看。很多教材把特征工程講得像一門玄學(xué)動(dòng)不動(dòng)就“業(yè)務(wù)理解”“行業(yè)經(jīng)驗(yàn)”聽著高大上落地時(shí)卻不知道從哪下手。我這幾年的體會(huì)是特征工程其實(shí)是有方法論的從數(shù)據(jù)清洗、特征構(gòu)造到特征選擇每一步都有明確的判斷依據(jù)和通用套路。今天我把這套思路完整拆開結(jié)合一個(gè)經(jīng)典案例走一遍完整流程也把那些只有實(shí)際踩坑才能總結(jié)出來的細(xì)節(jié)一并交代清楚。1. 特征工程到底在解決什么問題1.1 一句話理解特征工程特征工程就是把“原始數(shù)據(jù)”加工成“更好用的數(shù)據(jù)”的過程。什么叫“更好用”三個(gè)標(biāo)準(zhǔn)模型能讀、規(guī)律更明顯、冗余更少。模型能讀指的是數(shù)據(jù)格式、缺失值、異常值不會(huì)再干擾算法運(yùn)算規(guī)律更明顯指的是通過變換和構(gòu)造把原本隱藏在雜亂數(shù)據(jù)里的信號(hào)放大冗余更少指的是把那些不相關(guān)、重復(fù)、甚至起干擾作用的特征剔除掉降低模型過擬合的風(fēng)險(xiǎn)。一句話總結(jié)我在項(xiàng)目里的體會(huì)特征工程決定了模型性能的天花板而算法只是在逼近這個(gè)天花板。再?gòu)?qiáng)的樹模型、再深的神經(jīng)網(wǎng)絡(luò)喂進(jìn)去一堆噪聲學(xué)出來的也只能是噪聲。1.2 為什么特征工程如此關(guān)鍵舉個(gè)最容易理解的例子。你現(xiàn)在想預(yù)測(cè)一個(gè)房子好不好賣原始特征里有“房間數(shù)量”和“房屋面積”。單獨(dú)看這兩個(gè)特征都能提供信息但如果你構(gòu)造一個(gè)新特征叫“均價(jià)總價(jià)/面積”模型對(duì)這個(gè)特征的敏感度往往遠(yuǎn)超單獨(dú)的“總價(jià)”和“面積”——因?yàn)樗苯涌坍嬃藛挝粌r(jià)值。這就是特征構(gòu)造的作用讓模型從數(shù)據(jù)里“發(fā)現(xiàn)”規(guī)律不如你直接把規(guī)律塞給它。還有一個(gè)角度是“特征與模型的適配性”。線性模型天然假設(shè)特征與目標(biāo)的關(guān)系是線性的如果你把一個(gè)有明顯指數(shù)趨勢(shì)的特征直接丟進(jìn)去模型怎么擬合都欠擬合但你把特征做一次 log 變換讓它變成近似線性關(guān)系模型的效果可能立刻上升一大截。這不是玄學(xué)而是特征工程與模型假設(shè)之間的匹配問題。不少熱詞里提到的“機(jī)器學(xué)習(xí)三大假設(shè)”其中就有特征獨(dú)立同分布相關(guān)的討論雖然樹模型對(duì)特征尺度不敏感但對(duì)特征分布和特征間交互結(jié)構(gòu)的依賴其實(shí)一點(diǎn)不比線性模型少。1.3 特征工程在機(jī)器學(xué)習(xí)項(xiàng)目中的位置一個(gè)完整項(xiàng)目的流程一般是業(yè)務(wù)理解 → 數(shù)據(jù)采集 → 數(shù)據(jù)清洗 → 特征工程 → 模型訓(xùn)練 → 模型評(píng)估 → 上線部署。特征工程處于數(shù)據(jù)清洗和模型訓(xùn)練之間承上啟下。數(shù)據(jù)清洗解決的是“數(shù)據(jù)對(duì)不對(duì)”的問題特征工程解決的是“數(shù)據(jù)好不好用”的問題。很多人把這兩步混在一起結(jié)果導(dǎo)致后續(xù)環(huán)節(jié)完全沒有區(qū)分度出了問題也不知道是清洗的鍋還是構(gòu)造的鍋。我建議一開始就養(yǎng)成好習(xí)慣清洗和特征工程分開寫代碼、分開記錄日志、分開做版本管理。真到項(xiàng)目復(fù)盤的時(shí)候你會(huì)發(fā)現(xiàn)這個(gè)習(xí)慣能救你命。2. 數(shù)據(jù)清洗與特征理解動(dòng)手前的必修課2.1 缺失值處理不是填空題提到缺失值很多新手第一反應(yīng)就是“用均值填上”。這個(gè)做法本身沒錯(cuò)但只適用于一部分場(chǎng)景而且可能帶來嚴(yán)重的數(shù)據(jù)泄漏或分布扭曲。拿時(shí)間序列數(shù)據(jù)舉例如果你有一條股票價(jià)格數(shù)據(jù)在某天缺失你用整周均值去填等于把未來信息泄漏到了過去。正確做法要么用前向填充ffill用上一個(gè)時(shí)刻的值補(bǔ)當(dāng)前時(shí)刻要么用插值法做平滑估計(jì)。而對(duì)于用戶畫像類的表格數(shù)據(jù)如果某列缺失率超過50%直接整列刪除可能比費(fèi)勁填補(bǔ)更穩(wěn)妥——因?yàn)槿笔鄷r(shí)填補(bǔ)出來的列已經(jīng)不再是“真實(shí)信息”而是你主觀構(gòu)造的信息了。我在實(shí)際項(xiàng)目里一般按這個(gè)優(yōu)先級(jí)處理缺失值缺失率低于5%且列重要優(yōu)先用中位數(shù)或眾數(shù)填充減少極端值影響缺失率在5%~30%嘗試用其他特征構(gòu)造一個(gè)簡(jiǎn)單模型來預(yù)測(cè)缺失值比如決策樹效果通常不錯(cuò)缺失率超過50%刪除該列除非你有很強(qiáng)業(yè)務(wù)理由保留如果缺失本身代表一種業(yè)務(wù)含義比如“未填寫”表示“沒有”把缺失單獨(dú)編碼為一個(gè)類別而不是硬填。提示處理缺失值之前先搞清楚“為什么缺失”。隨機(jī)缺失和系統(tǒng)缺失是兩回事后者若不處理模型會(huì)學(xué)到錯(cuò)誤模式。2.2 異常值要“看”而不是“殺”異常值的處理比缺失值更需要謹(jǐn)慎。一個(gè)極端值可能是噪聲也可能是極其重要的信號(hào)。比如在欺詐檢測(cè)里一筆大額異常交易恰恰是模型要逮的目標(biāo)你把它刪了模型學(xué)什么所以我給項(xiàng)目定了一條鐵律先可視化再?zèng)Q定去留。最簡(jiǎn)單有效的可視化工具就是箱線圖。箱線圖能一眼看出數(shù)據(jù)的中位數(shù)、四分位距和可能的離群點(diǎn)。再用 IQR四分位距方法做定量判斷超過Q1 - 1.5*IQR或Q3 1.5*IQR的點(diǎn)視為離群點(diǎn)候選。但“候選”不等于“異?!薄N視?huì)對(duì)每一個(gè)離群點(diǎn)追問這個(gè)值是測(cè)量誤差、錄入錯(cuò)誤還是真實(shí)存在的極端情況如果是誤差直接修正或刪除如果是真實(shí)情況保留下來并考慮做截尾處理winsorize把極端值壓縮到某個(gè)百分位例如把超過99%分位的值截?cái)嗟?9%分位的值。這樣既保留了趨勢(shì)信息又避免模型被個(gè)別極端值帶偏。2.3 先理解分布再談建模我發(fā)現(xiàn)很多人拿到數(shù)據(jù)就開始調(diào)模型完全沒看過特征長(zhǎng)什么樣。這就像不看食材好壞就開始炒菜。正確姿勢(shì)是先畫直方圖看每個(gè)特征的分布形狀再看目標(biāo)變量的分布最后看特征與目標(biāo)的關(guān)系是否呈明顯的趨勢(shì)。為什么要看分布因?yàn)椴煌植紝?duì)應(yīng)的處理方法完全不同。右偏嚴(yán)重的特征適合做 log 變換雙峰分布的特征可能是兩個(gè)群體混在一起要考慮要不要分組建模重尾分布的特征模型通常會(huì)非常在意尾部值適當(dāng)截尾也許更好。做 log 變換時(shí)有個(gè)小技巧如果特征里有 0 或者負(fù)數(shù)先做log(x 1)這樣既保留了變換效果又避免了數(shù)學(xué)上的無定義問題。想更精確可以用 Box-Cox 變換它會(huì)自動(dòng)尋找最優(yōu)的變換參數(shù) λ把數(shù)據(jù)盡量拉成正態(tài)分布。3. 特征構(gòu)造把原始信息變成模型能學(xué)的東西3.1 數(shù)值特征的常見變換數(shù)值特征是最常見也最容易被輕視的一類。很多人直接標(biāo)準(zhǔn)化之后丟進(jìn)模型卻錯(cuò)過了很多提升空間。數(shù)值特征的構(gòu)造大致有三類思路。第一類是尺度變換。比如把“收入”從元改成萬(wàn)元或者做 log 變換壓縮量級(jí)。線性模型和距離類模型KNN、SVM對(duì)尺度非常敏感不做標(biāo)準(zhǔn)化時(shí)量級(jí)大的特征會(huì)主導(dǎo)距離計(jì)算模型基本就廢了。標(biāo)準(zhǔn)化的方式有兩種主流選擇Min-Max 歸一化把數(shù)據(jù)壓到 0~1 之間適合分布在有界區(qū)間內(nèi)的特征Z-score 標(biāo)準(zhǔn)化把數(shù)據(jù)變成均值為 0、方差為 1 的標(biāo)準(zhǔn)分布適合沒有明顯邊界的特征。樹模型不需要做這些變換但如果你要同時(shí)跑多個(gè)模型做對(duì)比統(tǒng)一處理是省心的做法。第二類是多項(xiàng)式展開。給模型增加特征之間的交叉項(xiàng)比如x1^2、x1*x2。這個(gè)操作在線性模型里特別有用因?yàn)榫€性模型本身學(xué)不到非線性關(guān)系你通過顯式構(gòu)造多項(xiàng)式特征相當(dāng)于讓線性模型也能擬合非線性模式。但要注意多項(xiàng)式特征會(huì)帶來維度爆炸特征從 10 個(gè)變成 50 個(gè)模型可能一下就過擬合了需要配合正則化和特征選擇使用。第三類是分箱。有時(shí)候特征和目標(biāo)是單調(diào)關(guān)系但并非線性與其讓模型去試不如直接把數(shù)值特征離散化成若干區(qū)間。比如“年齡”可以分成“未成年、青年、中年、老年”分箱后的特征對(duì)異常值更魯棒也能讓模型學(xué)到非線性節(jié)奏。分箱的區(qū)間數(shù)量一般 5~10 個(gè)太少丟信息太多又回到過擬合。可以用 pandas 的cut等寬分箱或qcut等頻分箱等頻分箱在每個(gè)箱內(nèi)有相同樣本量更適合分布不均勻的數(shù)據(jù)。3.2 分類特征的編碼思路分類特征是表格數(shù)據(jù)里最常見的“硬骨頭”因?yàn)榻^大多數(shù)模型只能吃數(shù)值。最基礎(chǔ)的方法是 One-Hot 編碼幾行代碼就能做完但一旦某個(gè)類別特征有幾十個(gè)類別生成的啞變量矩陣會(huì)撐爆內(nèi)存。此時(shí)就該考慮目標(biāo)編碼Target Encoding用目標(biāo)變量在該類別下的均值來替代類別標(biāo)簽。目標(biāo)編碼能保留類別信息且不會(huì)維度爆炸但極易引起過擬合和數(shù)據(jù)泄漏一般需要配合交叉驗(yàn)證在每一折里單獨(dú)計(jì)算編碼值避免把未來信息帶進(jìn)訓(xùn)練集。還有一個(gè)我常用的技巧低頻類別合并。把出現(xiàn)次數(shù)少于某個(gè)閾值比如 5 次的類別統(tǒng)一合并成一個(gè)“其他”類別。這個(gè)操作能顯著減少類別噪音模型也會(huì)更穩(wěn)定。注意對(duì)類別特征做編碼時(shí)如果測(cè)試集里出現(xiàn)了訓(xùn)練集沒見過的類別代碼很容易報(bào)錯(cuò)。提前把這種情況處理掉是工程經(jīng)驗(yàn)的一部分。3.3 時(shí)間特征與復(fù)合特征的構(gòu)造時(shí)間特征是一個(gè)特別值得挖的礦。把“日期”拆成年、月、日、星期幾、是否節(jié)假日往往就能給模型帶來明顯的提升。尤其是“星期幾”這個(gè)特征在電商、出行、內(nèi)容消費(fèi)等領(lǐng)域幾乎是剛需。更復(fù)雜一點(diǎn)可以構(gòu)造“距上一個(gè)特殊日期的天數(shù)”或“近 7 天累計(jì)值”這些滾動(dòng)窗口特征能捕捉時(shí)序上的趨勢(shì)和周期性。復(fù)合特征就是把兩個(gè)或兩個(gè)以上的特征按一定邏輯組合成新特征常見的有加減乘除。例如“人均消費(fèi)總消費(fèi)/人數(shù)”、“點(diǎn)擊率點(diǎn)擊數(shù)/曝光數(shù)”。這些復(fù)合特征在業(yè)務(wù)場(chǎng)景里通常比原始特征更貼近問題的核心邏輯。構(gòu)造復(fù)合特征的時(shí)候要注意做除法的特征不能為 0且分母的量級(jí)不要太小否則會(huì)爆出異常值。我一般會(huì)在構(gòu)造完后重新做一次異常值檢查防止“合法”的異常值混進(jìn)來。3.4 特征構(gòu)造的“度”在哪里有朋友問過我特征是不是構(gòu)造得越多越好我的答案是要看模型。如果你的模型是線性模型或 KNN更多特征意味著更強(qiáng)的表達(dá)能力但也意味著更容易過擬合如果你的模型是樹模型理論上它有內(nèi)在的特征選擇能力但特征過多照樣會(huì)稀釋重要特征的權(quán)重帶來不必要的訓(xùn)練開銷。我習(xí)慣在每個(gè)特征構(gòu)造階段設(shè)一個(gè)“ROI 指標(biāo)”構(gòu)造一個(gè)新特征后用相同的模型和相同的配置跑一次看驗(yàn)證集的指標(biāo)是否提升。提升了就保留沒提升就刪掉。用這種“實(shí)驗(yàn)驅(qū)動(dòng)”的方式替代“拍腦袋造特征”時(shí)間久了你會(huì)慢慢建立起對(duì)特征的直覺知道哪些方向值得嘗試。4. 特征選擇做減法才是硬功夫4.1 三種特征選擇流派各有適用場(chǎng)景特征選擇通常分成三類過濾式、包裹式、嵌入式。過濾式方法不依賴任何模型純粹靠統(tǒng)計(jì)指標(biāo)篩特征比如皮爾遜相關(guān)系數(shù)、卡方檢驗(yàn)、互信息。優(yōu)點(diǎn)是速度極快適合特征數(shù)量很大的場(chǎng)景缺點(diǎn)是它只衡量單特征和目標(biāo)的關(guān)系沒法捕捉特征之間的聯(lián)合效應(yīng)。比如兩個(gè)特征單獨(dú)看都和預(yù)測(cè)目標(biāo)無關(guān)組合起來卻很有區(qū)分度過濾式方法會(huì)直接把它們丟掉。所以我的習(xí)慣是過濾式只用來做“粗篩”把明顯沒用的特征快速去掉給后面的精篩減壓力。包裹式方法是把模型拉進(jìn)循環(huán)里比如遞歸特征消除RFE。它反復(fù)訓(xùn)練模型、刪除最不重要的特征、再訓(xùn)練直到達(dá)到預(yù)設(shè)的特征數(shù)量。效果通常不錯(cuò)但訓(xùn)練代價(jià)很高特征數(shù)量幾百個(gè)以上的時(shí)候跑起來就很磨人。嵌入式方法則是在訓(xùn)練過程中自動(dòng)完成特征選擇典型的代表是 L1 正則Lasso和樹模型的特征重要性。這個(gè)方法效率高、效果好是我個(gè)人最常用的選擇方式。4.2 從相關(guān)性到模型反饋的實(shí)操流程我自己在項(xiàng)目里一般按四步走第一步先觀察相關(guān)性矩陣。數(shù)值特征之間相關(guān)系數(shù)超過 0.8 的保留解釋性更強(qiáng)、缺失更少的那個(gè)刪除另一個(gè)。這步專治多重共線性尤其是線性模型最吃這一套。第二步計(jì)算每個(gè)特征與目標(biāo)變量的相關(guān)性同時(shí)結(jié)合業(yè)務(wù)直覺把相關(guān)性極低且業(yè)務(wù)上無明顯意義的特征放入“觀察名單”。第三步用樹模型跑一次默認(rèn)參數(shù)輸出feature_importances_。把重要性為零或極低的特征挑出來認(rèn)真審視是特征本身沒信息還是構(gòu)造方式不對(duì)多數(shù)情況下特征重要度接近 0 意味著這個(gè)特征在當(dāng)前模型結(jié)構(gòu)里確實(shí)發(fā)揮不了作用可以放心刪掉。第四步用已經(jīng)初篩后的特征集配合交叉驗(yàn)證做一次遞歸特征消除RFE看模型效果隨著特征數(shù)量變化的情況。畫一條“特征數(shù)量 vs 驗(yàn)證集分?jǐn)?shù)”的曲線找到拐點(diǎn)位置就能確定最終要保留的特征數(shù)量。提示特征選擇必須在訓(xùn)練集內(nèi)部完成不能先對(duì)全量數(shù)據(jù)做選擇、再劃分訓(xùn)練測(cè)試集。否則你會(huì)把測(cè)試集的信息泄漏進(jìn)訓(xùn)練過程上線之后效果崩得非常難看。5. 實(shí)操?gòu)?fù)盤波士頓房?jī)r(jià)數(shù)據(jù)集的入門特征工程5.1 數(shù)據(jù)初探與問題定位熱詞里出現(xiàn)頻率很高的“波士頓房?jī)r(jià)數(shù)據(jù)集”是特征工程入門最經(jīng)典的案例之一。數(shù)據(jù)本身只有 13 個(gè)特征、506 條樣本規(guī)模不大但足夠走一遍完整流程。這 13 個(gè)特征包含犯罪率CRIM、平均房間數(shù)RM、低收入人口比例LSTAT、師生比PTRATIO、到就業(yè)中心距離DIS等。拿到數(shù)據(jù)先干三件事看缺失值情況、看數(shù)據(jù)類型、看特征分布。波士頓房?jī)r(jià)數(shù)據(jù)整體質(zhì)量不錯(cuò)缺失值不多但 RM 和 LSTAT 這兩個(gè)特征的量綱差異很大如果不做標(biāo)準(zhǔn)化距離類模型會(huì)直接失衡。另外CHAS 這個(gè)特征是二分變量是否靠近查爾斯河有的人會(huì)忘記它是一個(gè)分類特征直接當(dāng)數(shù)值特征用了最后特征含義完全跑偏。先寫一段探索性代碼import pandas as pd import numpy as np import matplotlib.pyplot as plt df pd.read_csv(boston_housing.csv) # 缺失值概覽 print(df.isnull().sum()) # 描述性統(tǒng)計(jì) print(df.describe()) # 直方圖快速掃一遍分布 df.hist(bins50, figsize(16, 10)) plt.tight_layout() plt.show()這一步能快速定位哪些列有缺失、哪些列嚴(yán)重偏斜、哪些列存在明顯離群點(diǎn)。5.2 完整處理流程與關(guān)鍵參數(shù)我在這個(gè)數(shù)據(jù)集上一般按以下流程走先補(bǔ)缺失值。這里用中位數(shù)填充比均值對(duì)離群點(diǎn)更穩(wěn)健尤其是 CRIM 這種重尾特征均值會(huì)被極少數(shù)高犯罪率區(qū)域拉高中位數(shù)才代表典型水平。再處理異常值。用 IQR 法篩選出候選離群點(diǎn)再結(jié)合業(yè)務(wù)常識(shí)判斷。比如 RM 異常大平均房間數(shù)超過 8 的樣本大概率是少數(shù)豪宅類區(qū)域信息本身是有效的但做一次 99% 分位的截尾處理防止模型被這幾個(gè)特殊樣本主導(dǎo)。然后是標(biāo)準(zhǔn)化。對(duì)連續(xù)特征做 Z-score 標(biāo)準(zhǔn)化代碼非常簡(jiǎn)單from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X)但注意順序先劃分訓(xùn)練集和測(cè)試集再用訓(xùn)練集去fit這個(gè) scaler最后用同一個(gè) scaler 去transform測(cè)試集。如果你先全量做標(biāo)準(zhǔn)化再劃分?jǐn)?shù)據(jù)泄漏又來了。接著做特征構(gòu)造。我在這個(gè)數(shù)據(jù)集上最常用的復(fù)合特征是RM * LSTAT。RM 是正相關(guān)特征LSTAT 是負(fù)相關(guān)特征它們的交互項(xiàng)相當(dāng)于“高房間數(shù)且低收入比例高”這種組合信息不少模型迭代后顯示這個(gè)特征對(duì)房?jī)r(jià)預(yù)測(cè)有明顯的邊際貢獻(xiàn)。此外還有一個(gè)常用的變換對(duì) DIS 做平方項(xiàng)因?yàn)榉績(jī)r(jià)與就業(yè)中心距離的關(guān)系往往是先陡后緩的曲線平方項(xiàng)能給線性模型提供額外擬合自由度。最后是特征選擇。跑一次隨機(jī)森林輸出特征重要度f(wàn)rom sklearn.ensemble import RandomForestRegressor model RandomForestRegressor(n_estimators200, random_state42) model.fit(X_scaled, y) importance pd.Series(model.feature_importances_, indexX_scaled.columns).sort_values(ascendingFalse) print(importance)根據(jù)重要度結(jié)果把排在最末位的兩三個(gè)特征刪除再用線性回歸或隨機(jī)森林重新訓(xùn)練記錄驗(yàn)證集 R2的變化。很多人在這一步會(huì)發(fā)現(xiàn)刪掉部分特征之后效果沒有明顯下降甚至略有上升——這就是做減法的意義。把模型從不必要的噪音中解放出來泛化能力反而更強(qiáng)。5.3 交叉驗(yàn)證里的坑用波士頓房?jī)r(jià)數(shù)據(jù)做交叉驗(yàn)證時(shí)有個(gè)特別容易踩的坑樣本量只有 506 條如果不夠小心很容易把折內(nèi)誤差估計(jì)得過于樂觀。默認(rèn)的train_test_split(test_size0.2)劃分下測(cè)試集只有一百多個(gè)樣本指標(biāo)波動(dòng)很大。我建議用 5 折或 10 折交叉驗(yàn)證重復(fù)跑 3 次取均值輸出帶有方差的指標(biāo)這樣才能安心對(duì)比不同特征工程方案的效果差別。還有一點(diǎn)RM 和 LSTAT 這類在區(qū)間上分布并不均勻的特征建議分箱后再查看與目標(biāo)變量的關(guān)系圖比直接散點(diǎn)圖更容易看出非線性結(jié)構(gòu)。6. 常見問題與排查技巧實(shí)錄6.1 為什么特征越做效果越差我遇到過很多次特征是加了不少指標(biāo)反而掉頭向下。排到最前面、也最容易忽略的原因就是數(shù)據(jù)泄漏。比如你在缺失值填充時(shí)用了全數(shù)據(jù)集計(jì)算出來的均值去填訓(xùn)練集和測(cè)試集填充出來的測(cè)試集已經(jīng)包含了全局信息的影子模型在訓(xùn)練時(shí)“提前看過”測(cè)試集的統(tǒng)計(jì)量驗(yàn)證集上的分?jǐn)?shù)自然虛高但上線之后真實(shí)數(shù)據(jù)一進(jìn)來立刻打回原形。另一個(gè)常見原因是特征間產(chǎn)生了強(qiáng)共線性。你構(gòu)造了一個(gè)新特征“人均消費(fèi)總消費(fèi)/人數(shù)”但原始特征里還留著“總消費(fèi)”和“人數(shù)”模型在三個(gè)特征之間跳來跳去權(quán)重被稀釋穩(wěn)定性下降。解決辦法是構(gòu)造復(fù)合特征后主動(dòng)刪除被合成前的原始特征或者用相關(guān)性矩陣檢查一遍。還有一種情況是新增特征本身噪音太大。比如從文本描述里抽取的一些關(guān)鍵詞特征樣本量不夠時(shí)就像隨機(jī)噪聲模型非但學(xué)不到規(guī)律還會(huì)被帶偏。這時(shí)候可以用“單特征訓(xùn)練”來驗(yàn)證只拿這個(gè)新特征去訓(xùn)練一個(gè)簡(jiǎn)化模型看它在驗(yàn)證集上有沒有獨(dú)立貢獻(xiàn)。沒有貢獻(xiàn)的特征果斷刪。6.2 訓(xùn)練集和測(cè)試集分布不一致的典型表現(xiàn)特征工程做得再花哨訓(xùn)練集和測(cè)試集來自不同分布照樣會(huì)崩。典型表現(xiàn)是訓(xùn)練集指標(biāo)非常漂亮測(cè)試集或線上效果慘不忍睹。排查時(shí)不要急著調(diào)模型先對(duì)比訓(xùn)練集和測(cè)試集在每個(gè)特征上的均值、方差和分位數(shù)。如果發(fā)現(xiàn)某個(gè)特征在測(cè)試集上出現(xiàn)了訓(xùn)練集從沒見過的取值區(qū)間說明這個(gè)特征本身不穩(wěn)定要么刪除要么做截尾。時(shí)間序列數(shù)據(jù)的場(chǎng)景里這個(gè)問題尤其突出——?dú)v史數(shù)據(jù)的分布和未來數(shù)據(jù)的分布天然有漂移。我的常規(guī)操作是做一個(gè)“時(shí)間切分交叉驗(yàn)證”而不是隨機(jī)劃分訓(xùn)練集用過去的數(shù)據(jù)驗(yàn)證集用未來的數(shù)據(jù)這樣評(píng)估出來的指標(biāo)才更接近真實(shí)表現(xiàn)。6.3 幾個(gè)值得長(zhǎng)期保留的習(xí)慣每做一次特征變換就把特征命名帶上下劃線后綴比如RM_log、LSTAT_bin方便追溯來源特征工程代碼分層封裝數(shù)據(jù)清洗一個(gè)模塊、特征構(gòu)造一個(gè)模塊、特征選擇一個(gè)模塊這樣出問題時(shí)定位快每次跑實(shí)驗(yàn)都在代碼里記錄下特征列表和隨機(jī)種子否則結(jié)果不可復(fù)現(xiàn)排查起來等于大海撈針模型效果出現(xiàn)異常波動(dòng)時(shí)先退回到最近一次“表現(xiàn)正常”的特征版本用二分法定位是哪個(gè)特征或哪步操作引入了問題。特征工程這門手藝門檻不高天花板很高。很多人誤以為它只是重復(fù)勞動(dòng)實(shí)際上它要求你同時(shí)具備業(yè)務(wù)敏感度、統(tǒng)計(jì)直覺和工程能力。我見過許多效果絕佳的項(xiàng)目模型用的都是再普通不過的邏輯回歸或 GBDT但特征組合精巧到讓人拍案叫絕。反過來拿再?gòu)?fù)雜的深度學(xué)習(xí)模型硬套一堆沒整理過的原始數(shù)據(jù)出來的結(jié)果大概率也是原地打轉(zhuǎn)。如果你剛?cè)腴T我建議從今天提到的波士頓房?jī)r(jià)數(shù)據(jù)集開始按“清洗→變換→構(gòu)造→選擇→驗(yàn)證”的流程完整走一遍哪怕結(jié)果和課本差不多也一定要親手跑通。跑通之后找一份自己熟悉的業(yè)務(wù)數(shù)據(jù)嘗試構(gòu)造 10 個(gè)新特征逐一帶到模型里驗(yàn)證。踩過的坑多了特征工程的直覺就慢慢長(zhǎng)出來了。