訓練集和測試集的分布差距太大有好的處理方法嗎?


機器學習常見步驟

1.對數據集進行劃分,分為訓練集測試集兩部分;
2.對模型在測試集上面的泛化性能進行度量;
3.基于測試集上面的泛化性能,依據假設檢驗來推廣到全部數據集上面的泛化性能。

三種數據集的含義

在進行機器學習算法之前,通常需要將數據集劃分,通常分為訓練集和測試集,部分還有驗證集。首先介紹這三種數據集的含義:

**訓練集(Training Set):**幫助我們訓練模型,即通過訓練集的數據讓我們確定擬合曲線的參數。
**驗證集(Validation Set):**用來做模型選擇(model selection),即做模型的最終優化及確定的,用來輔助我們的模型的構建,可選;


測試集(Test Set): 為了測試已經訓練好的模型的精確度。因為在訓練模型的時候,參數全是根據現有訓練集里的數據進行修正、擬合,有可能會出現過擬合的情況,即這個參數僅對訓練集里的數據擬合比較準確,如果出現一個新數據需要利用模型預測結果,準確率可能就會很差。


所以測試集的作用是為了對學習器的泛化誤差進行評估,即進行實驗測試以判別學習器對新樣本的判別能力,同時以測試集的的測試誤差”作為泛化誤差的近似。因此在分配訓練集和測試集的時候,如果測試集的數據越小,對模型的泛化誤差的估計將會越不準確。所以需要在劃分數據集的時候進行權衡。

測試集的比例
訓練集數據的數量一般占2/3到4/5。在實際應用中,基于整個數據集數據的大小,訓練集數據和測試集數據的劃分比例可以是6:4、7:3或8:2。對于龐大的數據可以使用9:1,甚至是99:1。具體根據測試集的劃分方法有所不同。


常見的劃分方法

留出法
直接將數據集D劃分為兩個互斥的的集合,其中一個集合作為訓練集S,另一個作為測試集T,即D=S∪T, S ∩ T = 空集。在S上訓練出模型后,用T來評估其誤差。

需要注意的是,訓練/測試集的劃分要盡可能保持數據分布的一致性,避免因數據劃分過程引入的額外的偏差而對最終結果產生影響。例如在分類任務中,至少要保持樣本的類別比例相似。從”采樣”的角度來看待數據集的劃分過程,則保留類別比例的采樣方式通常稱為“分層采樣”。例如從1000個數據里,分層采樣獲得70%樣本的訓練集S和30%樣本的測試集T,若D包含500個正例,500個反例,則分層采樣得到的S應包含350個正例,350個反例,T應包含150個正例,150個反例;若S、T中樣本比例差別很大,則最終擬合的誤差將會變大。

一般,在用留出法劃分集合的時候,會通過若干次隨機劃分、重復實驗評估后取平均值作為留出法的評估結果,減少誤差。留出法還有一個問題就是,到底我們訓練集和測試集應該按照什么比例來劃分呢?如果我們訓練集的比例比較大,可能會導致訓練出的模型更接近于用D訓練出的模型,同時T較小,評價結果又不夠準確;若T的比例比較大,則有可能導致評估的模型與之前有較大的差別,從而降低了評估的保真性。這個問題沒有完美的解決方案,常見的做法是將大約2/3~4/5的樣本用于訓練


交叉驗證法

將數據集D劃分為k個大小相似的互斥子集,即D=D1∪D2∪…∪Dk,Di ∩ Dj = 空集(i ≠j) 每個子集Di都盡可能保持數據分布的一致性,即從D中通過分層采樣得到。然后,每次用k-1個子集的并集作為訓練集,余下的那個子集作為測試集;這樣就可獲得k組訓練/測試集,從而可進行k次訓練和測試,最終返回的是這k個測試結果的均值。

交叉驗證法評估結果的穩定性和保真性在很大程度上取決于k的取值,為了強調這一點,通常把交叉驗證法稱為”k折交叉驗證”(k-fold cross validation),k通常取10—10折交叉驗證。


交叉驗證的好處就是從有限的數據中盡可能挖掘多的信息,從各種角度去學習我們現有的有限的數據,避免出現局部的極值。在這個過程中無論是訓練樣本還是測試樣本都得到了盡可能多的學習。

交叉驗證法的缺點就是,當數據集比較大時,訓練模型的開銷較大。

自助法

給定包含m個樣本的數據集D,我們對它進行采樣產生數據集D’:每次從D中挑選一個樣本,將其放入D’,然后再將該樣本放回初始數據集D中;這個過程重復執行m次后,我們就得到了包含m個樣本的數據集D’

即通過自助采樣,初始數據集D中約有36.8%的樣本未出現在采樣集D′里。于是 ,實際評估的模型與期望評估的模型都是使用m個樣本,而我們仍有數據總量約1/3的沒在訓練集出現過的樣本用于測試。

自助法在數據集較小、難以有效劃分訓練/測試集時比較有用。然而自助法產生的測試集改變了初始數據集的分布,這會引入誤差。

因此在數據集比較大時,采用留出法和交叉驗證法較好。


神經網絡在網絡結構確定的情況下,有兩部分影響模型最終的性能,一是普通參數(比如權重w和偏置b),另一個是超參數(例如學習率,網絡層數)。普通參數我們在訓練集上進行訓練,超參數我們一般人工指定(比較不同超參數的模型在驗證集上的性能)。那為什么我們不像普通參數一樣在訓練集上訓練超參數呢?(花書給出了解答)一是超參數一般難以優化(無法像普通參數一樣通過梯度下降的方式進行優化)。二是超參數很多時候不適合在訓練集上進行訓練,例如:如果在訓練集上訓練能控制模型容量的超參數,這些超參數總會被訓練成使得模型容量最大的參數(因為模型容量越大,訓練誤差越小),所以訓練集上訓練超參數的結果就是模型絕對過擬合。

正因為超參數無法在訓練集上進行訓練,因此我們單獨設立了一個驗證集,用于選擇(人工訓練)最優的超參數。因為驗證集是用于選擇超參數的,因此驗證集和訓練集是獨立不重疊的。

測試集是用于在完成神經網絡訓練過程后,為了客觀評價模型在其未見過(未曾影響普通參數和超參數選擇)的數據上的性能,因此測試與驗證集和訓練集之間也是獨立不重疊的,而且測試集不能提出對參數或者超參數的修改意見,只能作為評價網絡性能的一個指標。

訓練集和測試集的分布差距太大有好的處理方法嗎?的圖1


從訓練集中劃分出一部分作為驗證集,該部分不用于訓練,作為評價模型generalization error,而訓練集與驗證集之間的誤差作為data mismatch error,表示數據分布不同引起的誤差。

這種劃分方式有利于保證:數據具有相同的分布

如果訓練集和測試集的數據分布可能不相同,那么必定會導致一個問題,模型在訓練集上的表現會非常的好,而在測試集上表現可能不會那么理想。

通過訓練數據來訓練模型,就是希望模型能夠從訓練集中學習到數據的分布,如果訓練集和測試集數據不在同一個分布中,那么模型在測試集上的表現肯定是不會理想的。

訓練集高分,測試集預測提交后發現分數很低,為什么?有可能是訓練集和測試集分布不一致,導致模型過擬合訓練集,個人很不喜歡碰到這種線下不錯但線上抖動過大的比賽,有種讓你感覺好像在“碰運氣”,看誰“碰”對了測試集的分布。但實際是有方法可循的,而不是說純碰運氣。本文我將從“訓練/測試集分布不一致問題”的發生原因講起,然后羅列判斷該問題的方法和可能的解決手段。

訓練集和測試集的分布差距太大有好的處理方法嗎?的圖2

一、發生原因

訓練集和測試集分布不一致也被稱作數據集偏移(Dataset Shift)。西班牙格拉納達大學Francisco Herrera教授在他PPT[1]里提到數據集偏移有三種類型:

  • 協變量偏移(Covariate Shift): 獨立變量的偏移,指訓練集和測試集的輸入服從不同分布,但背后是服從同一個函數關系,如圖1所示。

  • 先驗概率偏移(Prior Probability Shift): 目標變量的偏移。

  • 概念偏移(Concept Shift): 獨立變量和目標變量之間關系的偏移。

訓練集和測試集的分布差距太大有好的處理方法嗎?的圖3

圖1:協變量偏移


最常見的有兩種原因[1]

  • 樣本選擇偏差(Sample Selection Bias): 訓練集是通過有偏方法得到的,例如非均勻選擇(Non-uniform Selection),導致訓練集無法很好表征的真實樣本空間。

  • 環境不平穩(Non-stationary Environments): 當訓練集數據的采集環境跟測試集不一致時會出現該問題,一般是由于時間或空間的改變引起的。


在分類任務上,有時候官方隨機劃分數據集,沒有考慮類別平衡問題,例如: 訓練集類別A數據量遠多于類別B,而測試集相反,這類樣本選擇偏差問題會導致訓練好的模型在測試集上魯棒性很差,因為訓練集沒有很好覆蓋整個樣本空間。此外,除了目標變量,輸入特征也可能出現樣本選擇偏差問題,比如要預測泰坦尼克號乘客存活率,而訓練集輸入特征里“性別”下更多是男性,而測試集里“性別”更多是女性,這樣也會導致模型在測試集上表現差。


樣本選擇偏差也有些特殊的例子,之前我參加阿里天池2021“AI Earth”人工智能創新挑戰賽[2],官方提供兩類數據集作為訓練集,分別是CMIP模擬數據和SODA真實數據,然后測試集又是SODA真實數據,CMIP模擬數據是通過系列氣象模型仿真模擬得到的,即有偏方法,但選手都會選擇將模擬數據加入訓練,因為訓練集真實數據太少了,可模擬數據的加入也無可避免的引入了樣本選擇偏差。


聊完樣本選擇偏移,我們聊下環境不平穩帶來的數據偏移,我想最常見是在時序比賽里了吧,用歷史時序數據預測未來時序,未來突發事件很可能帶來時序的不穩定表現,這便帶來了分布差異。環境因素不僅限于時間和空間,還有數據采集設備、標注人員等。


二、判斷方法

訓練集和測試集的分布差距太大有好的處理方法嗎?的圖4

1. KDE (核密度估計)分布圖

當我們一想到要對比訓練集和測試集的分布,便是畫概率密度函數直方圖,但直方圖看分布有兩點缺陷: 受bin寬度影響大和不平滑,因此多數人會偏向于使用核密度估計圖(Kernel Density Estimation, KDE),KDE是非參數檢驗,用于估計分布未知的密度函數,相比于直方圖,它受bin影響更小,繪圖呈現更平滑,易于對比數據分布。我研究生的有一門課的小作業有要去對比直方圖和KDE圖,相信這個能幫助大家更直觀了解到它們的差異:


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖5

圖2:心臟疾病患者最大心率的概率密度函數分布圖,數據源自UCI ML開放數據集


這里在略微細講下KDE,我們先看KDE函數:

   是來自未知分布的樣本,   是樣本總數,   是核函數,h是帶寬(Bandwidth)。核函數定義一個用于生成PDF(概率分布函數Probability Distribution Function)的曲線,不同于將值放入離散bins內,核函數對每個樣本值都創建一個獨立的概率密度曲線,然后加總這些平滑曲線,最終得到一個平滑連續的概率分布曲線,如下圖所示:


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖6

圖3:生成KDE的過程呈現[3]


言歸正傳,對比訓練集和測試集特征分布時,我們可以用seaborn.kdeplot()[4]進行繪圖可視化,樣例圖和代碼如下:


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖7

圖4:不同數據集下的KDE對比


import numpy as npimport seaborn as snsimport matplotlib.pyplot as plt
# 創建樣例特征train_mean, train_cov = [0, 2], [(1, .5), (.5, 1)]test_mean, test_cov = [0, .5], [(1, 1), (.6, 1)]train_feat, _ = np.random.multivariate_normal(train_mean, train_cov, size=50).Ttest_feat, _ = np.random.multivariate_normal(test_mean, test_cov, size=50).T
# 繪KDE對比分布sns.kdeplot(train_feat, shade = True, color='r', label = 'train')sns.kdeplot(test_feat, shade = True, color='b', label = 'test')plt.xlabel('Feature')plt.legend()plt.show()


2.KS檢驗

KDE是PDF來對比,而KS檢驗是基于CDF(累計分布函數Cumulative Distribution Function)來檢驗兩個數據分布是否一致,它也是非參數檢驗方法(即不知道數據分布情況)。兩條不同數據集下的CDF曲線,它們最大垂直差值可用作描述分布差異(見下圖5中的D)。


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖8

圖5:不同數據集下的CDF對比[5]


調用scipy.stats.ks_2samp()[6]可輕松得到KS的統計值(最大垂直差)和假設檢驗下的p值:

from scipy import statsstats.ks_2samp(train_feat, test_feat)輸出:KstestResult(statistic=0.2, pvalue=0.2719135601522248)

KS統計值小且p值大,則我們可以接受KS檢驗的原假設H0,即兩個數據分布一致。上面樣例數據的統計值較低,p值大于10%但不是很高,因此反映分布略微不一致。注意: p值<0.01,強烈建議拒絕原假設H0,p值越大,越傾向于原假設H0成立。


3. 對抗驗證

對抗驗證是個很有趣的方法,它的思路是:我們構建一個分類器去分類訓練集和測試集,如果模型能清楚分類,說明訓練集和測試集存在明顯區別(即分布不一致),否則反之。具體步驟如下:

  • 訓練集和測試集合并,同時新增標簽‘Is_Test’去標記訓練集樣本為0,測試集樣本為1。

  • 構建分類器(例如LGB, XGB等)去訓練混合后的數據集(可采用交叉驗證的方式),擬合目標標簽‘Is_Test’。

  • 輸出交叉驗證中最優的AUC分數。AUC越大(越接近1),越說明訓練集和測試集分布不一致。

相關代碼可參考Qiuyan918在Kaggle的Microsoft Malware Prediction比賽中使用實例代碼[7]。


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖9

圖6:對抗驗證示意圖


三、解決方法

訓練集和測試集的分布差距太大有好的處理方法嗎?的圖10

1. 構造合適的驗證集

當出現訓練集和測試集分布不一致的,我們可以試圖去構建跟測試集分布近似相同的驗證集,保證線下驗證跟線上測試分數不會抖動,這樣我們就能得到穩定的benchmark。Qiuyan918在基于對抗驗證的基礎上,提出了三種構造合適的驗證集的辦法:

  • 人工劃分驗證集

  • 選擇和測試集最相似的樣本作為驗證集

  • 有權重的交叉驗證

接下來,我將依次細講上述方法。


(1) 人工劃分驗證集

以時間序列舉例,因為一般測試集也會是未來數據,所以我們也要保證訓練集是歷史數據,而劃分出的驗證集是未來數據,不然會發生“時間穿越”的數據泄露問題,導致模型過擬合(例如用未來預測歷史數據),這個時候就有兩種驗證劃分方式可參考使用:

  • TimeSeriesSplit:Sklearn提供的TimeSeriesSplit。

  • 固定窗口滑動劃分法:固定時間窗口,不斷在數據集上滑動,獲得訓練集和驗證集。(個人推薦這種)

訓練集和測試集的分布差距太大有好的處理方法嗎?的圖11

圖7:劃分時序數據的兩種方法


除了時間序列數據,其它數據集的驗證集劃分都要遵循一個原則,即盡可能符合測試集的數據模式。像前面提到的2021“AI Earth”人工智能創新挑戰賽中氣象數據,由于測試集是真實氣象數據,那么我們劃分驗證集時,更傾向于使用真實氣象數據去評估線下模型的表現,而不是使用模擬氣象數據作為驗證集。


(2) 選擇和測試集最相似的樣本作為驗證集

前面在講對抗驗證時,我們有訓練出一個分類器去分類訓練集和測試集,那么自然我們也能預測出訓練集屬于測試集的概率(即訓練集在‘Is_Test’標簽下預測概率),我們對訓練集的預測概率進行降序排列,選擇概率最大的前20%樣本劃分作為驗證集,這樣我們就能從原始數據集中,得到分布跟測試集接近的一個驗證集了,具體樣例代碼詳見[7]。之后,我們還可以評估劃分好的驗證集跟測試集的分布狀況,評估方法:將驗證集和測試集做對抗驗證,若AUC越小,說明劃分出的驗證集和測試集分布越接近(即分類器越分不清驗證集和測試集)。


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖12

圖8:選擇和測試集最相似的樣本作為驗證集


(3) 有權重的交叉驗證

如果我們對訓練集里分布更偏向于測試集分布的樣本更大的樣本權重,給與測試集分布不太一致的訓練集樣本更小權重,也能一定程度上,幫助我們線下得到不易抖動的評估分數。在lightgbm庫的Dataset初始化參數中,便提供了樣本加權的參數weight,詳見文檔[8]。圖7中,對抗驗證的分類器預測訓練集的Is_Test概率作為權重即可。


2. 刪除分布不一致特征

如果我們遇到分布不一致且不太重要的特征,我們可以選擇直接刪去這種特征。該方法在各大比賽中十分常見。例如: 在2018年螞蟻金服風險大腦-支付風險識別比賽中,亞軍團隊根據特征在訓練集和測試集上的表現,去除分布差異較大的特征,如圖9[9]。


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖13

圖9:螞蟻金服支付風險識別比賽中刪除分布不一致特征[9]


雖然個人建議的是刪除分布不一致但不太重要的特征,但有時避免不了碰到分布不一致但又很重要的特征,這時候其實就需要自行trade off特征分布和特征重要性的關系了,比如在第四屆工業大數據創新競賽-注塑成型工藝的虛擬量測中,第5名團隊保留了sensor1_mean特征而刪除了pack_press_2特征,盡管他們發現pack_press_2從實際生產角度和相關性角度都非常重要,可為了提升模型在測試集的泛化能力和分數,他們沒用pack_press_2特征,如圖10[10]。


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖14

圖10:注塑成型工藝的虛擬量測比賽中刪除分布不一致特征[10]


3. 偽標簽

偽標簽是半監督方法,利用未標注數據加入訓練,我們先看看偽標簽的思路,再討論為什么它可能在一定程度上對分布不一致的數據集有幫助。偽標簽最常見的方法是:

  • 使用有標注的訓練集訓練模型M;

  • 然后用模型M預測未標注的測試集;

  • 選取測試集中預測置信度高的樣本加入訓練集中;

  • 使用標注樣本和高置信度的預測樣本訓練模型M';

  • 預測測試集,輸出預測結果。

TripleLift知乎主提供的入門版偽標簽思路圖如下所示,建議有興趣的朋友閱讀他原文[12],他還提供了進階版和創新版的偽標簽技術,值得借鑒學習。


訓練集和測試集的分布差距太大有好的處理方法嗎?的圖15

圖12:入門版偽標簽思路圖


由上圖我們可以看到,模型的訓練引入了部分測試集的樣本,這樣相當于引入了部分測試集的分布。但需要注意:

(1) 相比于前面的方法,偽標簽通常沒有表現的很好,因為它引入的是置信度高的測試集樣本,這些樣本很可能跟訓練集分布接近一致,所以才會預測概率高。因此引入的測試集分布也沒有很不同,所以使用時常發生過擬合的情況。

(2) 注意引入的是高置信度樣本,如果引入低置信度樣本,會帶來很大的噪聲。另外,高置信度樣本也不建議選取過多加入訓練集,這也是為了避免模型過擬合。

(3) 偽標簽適用于圖像領域更多些,表格型比賽建議最后沒辦法再考慮該方法,因為本人使用過該方法,漲分的可能性都不是很高(也可能是我沒用好)。




文章來源機器學習AI算法工程


登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP

1