<b>本文講的是在使用過采樣或欠采樣處理類别不均衡的資料後,如何正确的做交叉驗證?,</b>
<b></b>
但是,這篇文章并沒有涉及到我們在實際應用經常出現的問題。例如,如何在不均衡的資料上合理的進行交叉驗證。在醫療領域,我們所擁有的資料集一般隻包含兩種類别的資料, 正常 樣本和 相關 樣本。譬如說在癌症檢查的應用我們可能隻有很小一部分病人患上了癌症(相關樣本)而其餘的大部分樣本都是健康的個體。就算不在醫療領域,這種情況也存在(甚至更多),比如欺詐識别,它們的資料集中的相關樣本和正常樣本的比例都有可能會是 1:100000。
我最近無意中發現兩篇關于早産預測的文章,他們是使用 Electrohysterography (EHG)資料來做預測的。作者隻使用了一個單獨的 EHG 橫截面資料(通過捕獲子宮電活動獲得)訓練出來的模型就聲稱在預測早産的時候具備很高的精度( [2], 對比沒有使用過采樣時的 AUC = 0.52-0.60,他的模型的 AUC 可以達到 0.99 ).
這個結果給我們的感覺像是 過拟合和錯誤的交叉驗證 所造成的,在我解釋原因之前,讓我們先來觀看下面的資料:
這四張密度圖表示的是他所用到的四個特征的在兩個類别上的分布,這兩個類别為正常分娩與早産(f = false,表示正常分娩,使用紅色的線表示;t = true, 則表示為早産,用藍色的線表示)。我們從圖中可以看到這四個特征并沒有很強的區分兩個類别的能力。他所提取出來的特征在兩個特征上的分布基本上就是重疊的。我們可以認為這是一個無用輸入,無用輸出的例子,而不是說這個模型缺少資料。
隻要稍微思考一下該問題所在的領域,我們就會對 auc=0.99 這個結果提出質疑。因為區分正常分娩和早産沒有一個很明确的區分。假設我們設定 37 周就為正常的分娩時間。 那麼如果你在第 36 周後的第 6 天分娩,那麼我們則标記為早産。反之,如果在 37 周後 1 天妊娠,我們則标記為在正常的妊娠期内。 很明顯,這兩種情況下區分早産和正常分娩是沒有意義的,37 周隻是一個慣例,是以,預測結果會大受影響并且對于分娩時間在 37 周左右的樣本,結果會非常不精确。
資料集
我們使用的資料來自于盧布爾雅那醫學中心大學婦産科,資料中涵蓋了從1997 年到 2005 年斯洛維尼亞地區的妊娠記錄。他包含了從正常懷孕的 EHG 截面資料。 這個資料是非常不均衡的,因為 300 個記錄中隻有 38 條才是早孕。 更加詳細的資訊可以在 [3] 中找到。簡單來說,我們選擇 EHG 截面的理由是因為 EHG 測量的是子宮的電活動圖,而這個活動圖在懷孕期間會不斷的變化,直到導緻子宮收縮分娩出孩子。是以,研究推斷非侵入性情況下監測懷孕活動可以盡早的發現哪些孕婦會早産。
特征與分類器
評測名額
交叉驗證
我決定使用 留一法 來做交叉驗證。這種技術在使用資料集時或者當欠采樣時不會有任何錯誤的餘地。但是,當過采樣時,情況又會有點不一樣,是以讓我們看下面的分析。
當我們遇到資料不均衡的時候,我們該如何做:
忽略這個問題
對占比較大的類别進行欠采樣
對占比較小的類别進行過采樣
如果我們使用不均衡的資料來訓練分類器,那麼訓練出來的分類器在預測資料的時候總會傳回資料集中占比最大的資料所對應的類别作為結果。這樣的分類器具備太大的偏差,下面是訓練這樣的分類器所對應的代碼:
從上面的代碼可以看出,在每次疊代中,我隻需選擇 index_subj 下标所對應的資料作為驗證集,然後使用剩餘的資料(即訓練資料)構模組化型。結果如下圖所示
如預期的那樣,分類器的偏差太大,召回率為零或非常接近零,而真假率為1或非常接近于1,即所有或幾乎所有記錄被檢測為會正常分娩,是以基本沒有識别出早産的記錄。下面的實驗則使用了欠采樣的方法。
處理類别不平衡資料的最常見和最簡單的政策之一是對大類樣本進行欠采樣。 盡管過去也有很多關于解決資料不均衡的辦法(例如,對具體樣本進行欠采樣,例如“遠離決策邊界”的方法)[4],但那些方法都不能改進在簡單随機選擇樣本的情況下有任何性能上的提升。 是以,我們的實驗将從占比較大的類别下的樣本中随機選擇 n 個樣本,其中 n 的值等于占比較小的類别下的樣本的總數,并在訓練階段使用它們,然後在驗證中排除掉這些樣本。 代碼如下:
如上所述,上面的代碼與之前最大的不同的是在每次疊代的時候,我們從占比較大的類别下的樣本中選取了 n ,然後使用這個 n 個樣本和占比類别較小的樣本組成了訓練集來訓練我們的分類器。結果如下圖所示:
通過欠采樣,我們解決了資料類别不均衡的問題,并且提高了模型的召回率,但是,模型的表現并不是很好。其中一個原因可能是因為我們用來訓練模型的資料過少。一般來說,如果我們的資料集中的類别越不均衡,那麼我們在欠采樣中抛棄的資料就會越多,那麼就意味着我們可能抛棄了一些潛在的并且有用的資訊。現在我們應該這樣問我們自己,我們是否訓練了一個弱的分類器,而原因是因為我們沒有太多的資料?還是說我們依賴了不好的特征,是以就算資料再多對模型也沒有幫助?
如果我們在 交叉驗證 之前進行過采樣會導緻 過拟合 的問題。那麼産生這個問題的原因是什麼呢?讓我們來看下面的一個關于過采樣的簡單執行個體。
最簡單的過采樣方式就是對占比類别較小下的樣本進行重新采樣,譬如說建立這些樣本的副本,或者手動制造一些相同的資料。現在,如果我們在交叉驗證之前做了過采樣,然後使用留一法做交叉驗證,也就是說我們在每次疊代中使用 N-1 份樣本做訓練,而隻使用 1 份樣本驗證。 但是我們注意到在其實在 N-1 份的樣本中是包含了那一份用來做驗證的樣本的。是以這樣做交叉驗證完全違背了初衷。 讓我們用圖形化的方式來更好的審視這個問題。
最左邊那清單示的是原始的資料,裡面包含了少數類下的兩個樣本。我們拷貝這兩個樣本作為副本,然後再進行交叉驗證。在疊代的過程,我們的訓練樣本和驗證樣本會包含相同的資料,如最右那張圖所示,這種情況下會導緻過拟合或誤導的結果,合适的做法應該如下圖所示。
也就是說我們每次疊代做交叉驗證之前先将驗證樣本從訓練樣本中分離出來,然後再對訓練樣本中少數類樣本進行過采樣(橙色那塊圖所示)。在這個示例中少數類樣本隻有兩個,是以我拷貝了三份副本。這種做法與之前最大的不同就是訓練樣本和驗證樣本是沒有交集的。因為我們獲得一個比之前好的結果。即使我們使用其他的交叉驗證方法,譬如 k-flod ,做法也是一樣的。
但是,我們有一定必須要清楚的是 使用 SMOTE 過采樣的确會提升決策邊界,但是卻并沒有解決前面所提到的交叉驗證所面臨的問題。 如果我們使用相同的樣本來訓練和驗證模型,模型的技術名額肯定會比采樣了合理交叉驗證方法所訓練出來的模型效果好。也就是說我在上面所舉的例子對應的問題是仍然存在的。 下面讓我們來看一下在交叉驗證之前進行過采樣會得出怎樣的結果。
錯誤的使用交叉驗證和過采樣
下面的代碼将會先進行過采樣,然後再進入交叉驗證的循環,我們使用 SMOTE 方法合成了我們的樣本:
結果相當不錯。尤其是随機森林在沒有做任何特征工程和調參的前提下 auc 的值達到了 0.93 ,但是與前面不同的是我們使用了 SMOTE 方法進行欠采樣,現在這個問題的核心在于我們應該在什麼時候使用恰當的方法,而不是使用哪種方法。在交叉驗證之前使用過采樣的确獲得很高的精度,但模型已經 過拟合 了。你看,就算是最簡單的分類樹都可以獲得 0.84 的 AUC 值。
正确的使用過采樣和交叉驗證
正确的在交叉驗證中配合使用過拟合的方法很簡單。就和我們在交叉驗證中的每次循環中做特征選擇一樣,我們也要在每次循環中做過采樣。 根據我們目前的少數類建立樣本,然後選擇一個樣本作為驗證樣本,假裝我們沒有使用在訓練集中的資料來作為驗證樣本,這是毫無意義的。 這一次,我們在交叉驗證循環中過采樣,因為驗證集已經從訓練樣本中移除了,因為我們隻需要插入那些不用于驗證的樣本來合成資料,我們交叉驗證的疊代次數将和樣本數一樣,如下代碼所示:
最後,使用了 SMOTE 過采樣技術和合适交叉驗證下模型的結果如下所示:
如之前所說,更多的資料并沒有解決任何的問題,對于使用“智能”的過采樣。它帶來了非常高的精确度,但那是過拟合。下面是一些關于召回率和真假率名額的結果的分析和總結可以看看。
召回率
真假率
正如我們所看到,分别使用合适的過采樣(第四張圖)和欠采樣(第二張圖)在這個資料集上訓練出來的模型差距并不是很大。
在這篇文章中,我使用了不平衡的 EHG 資料來預測是否早産,目的是講解在使用過采樣的情況下該如何恰當的進行交叉驗證。關鍵是過采樣必須是交叉驗證的一部分,而不是在交叉驗證之前來做過采樣。
總結一下,當在交叉驗證中使用過采樣時,請確定執行了以下步驟進而保證訓練的結果具備泛化性:
在每次交叉驗證疊代過程中,驗證集都不要做任何與特征選擇,過采樣和構模組化型相關的事情
過采樣少數類的樣本,但不要選擇已經排除掉的那些樣本。
用對少數類過采樣和大多數類的樣本混合在一起的資料集來訓練模型,然後用已經排除掉的樣本做為驗證集
重複 n 次交叉驗證的過程,n 的值是你訓練樣本的個數(如果你使用留一交叉驗證法的話)
<b>原文釋出時間為:2017年7月25日</b>
<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>