機器學習基石系列(12) — 驗證

Martin Huang
機器學習系列
Published in
Jun 28, 2021

回顧一下目前為止在「二元分類」任務上,為了讓模型學得更好,有做過哪些調整:

  1. 模型本身:有PLA、pocket algorithm、線性回歸、羅吉斯回歸
  2. 遍訪資料次數:和錯誤時給予的懲罰權重有一點關聯,在資料不足或不對等的時候使用
  3. 學習速率:在梯度下降時使用,可以決定一步要跨多大
  4. 線性轉換:將原始特徵非線性可分的情況投影到高維空間
  5. 正規化因子:對模型權重的另一種限制
  6. 正規化大小:限制的多寡

現在如果有M個模型,H_1、H_2、…、H_M,對應到A_1、A_2、…、A_M,M個演算法。從中挑選一個H,使目標演算法g_m=A_m時有最低的E_out。這是機器學習的最終目標。如果知道E_out的話就不是問題了,但這當然是不可能的。

如果用E_in呢?E_in雖然知道,不過會造成一些趨勢:

  1. 為了追求E_in夠低,就不斷地把資料投射到越高維的空間。
  2. 然後不斷的調整多項式的係數(權重),讓他盡量符合資料。

以上這兩項都是因為E_in的資料是有限的,即使再大也有限。可是E_out對應的資料是無限的。到了外面的世界,多項式的預測將會只精巧的命中E_in的資料,而對於外面的資料作出迥異的判斷。

這就是overfitting。

那如果把H分組,先從各組找到一個最好的H,然後再來比較呢?那還是一樣,變成從兩組H的聯集中找到最好的A,本質上沒有不同。所以只用E_in來篩選是不適合的。

在這個系列的最開始,開宗明義提到機器學習要成功的兩大要素:E_in夠小,且E_out接近E_in。所以只做好前半是不夠的。有沒有其他方法?

拿另一組資料

既然拿模型訓練的資料,也就是E_in,比較會有問題,那我拿模型沒看過的資料總可以吧?叫E_test。

根據Hoffeding’s inequality:

式1.

似乎是可行的。藉由確保E_test的大小,可以控制E_out,讓模型學習變得可能。可惜最大的問題是:這個資料要怎麼取得?如果這是另外蒐集要給模型訓練的,那E_test就變成E_in了,因為模型看了。它變成收集到的資料之一,而不是外面世界的資料。如果它是外面世界的資料,那在完成訓練前模型不能看,才符合真實世界的情況。

比較一下E_in和E_test的差別:

唉呀,這邊有個有趣的東西:E_test的資料來源「理論上」無法取得?不是不能取得嗎?還有分什麼理論上實際上?

對。我們確實無法取得外面世界的資料,按照定義,E_in的訓練資料是從外面世界抽來的一部分,但模型訓練時看過了。E_test則是模型沒看過的外部資料,既然沒看過,當然也無法取得…嗎?

別忘了訓練資料也是從外部取得的。所以,如果我們從外部取得資料之後,在訓練時保留一些資料不給模型看,然後在類似E_test的行為時把資料拿出來評估模型的表現,就可以保留資料的乾淨性(一直到訓練結束前都沒被看過)、評估的客觀性,還兼具資料的可取得性。這個步驟就叫做驗證。我們可以說,驗證是一種「合法的作弊」。關鍵是

只要模型看過資料,這資料就不再乾淨,因為它已經影響到模型當中的某個部分。最乾淨的資料就是外面世界沒被取來訓練用,而是直接實戰使用的。

驗證的具體步驟

我們把驗證的E稱為E_val。驗證時,把手上的資料切一部分出來專門負責。相對的,訓練時這部分資料不可以加入。為了讓驗證用資料和訓練用資料都保有獨立且同分布的性質,驗證用資料必須也是隨機且平均的分布。綜上所述,驗證的執行步驟大致上如下:

圖片來源:林軒田<機器學習基石>,第十四講,第59段,第8張

如果全部的資料集,其個數為N,分割一部分的資料作驗證,其個數為K。訓練用資料的個數則為N-K。E_val和E_in的關係可以對照式1,把E_test換成E_val即可:

但D_val來自於D,和D_train系出同源,某種程度上,還可以直接說E_val是另一種形式的E_in,而D_val就是另一種形式的D_train。這就呼應了前面說的:一旦讓模型看過資料,不管再怎麼保護,它對模型就會造成影響,資料也就不再是完全乾淨的。

但因為至少我們讓驗證用的資料不在訓練時被模型看到,這樣它的乾淨度還是比訓練用的資料好一些。把它拆分之後,訓練用資料不參與驗證,專心讓A找到g。驗證用的資料則用來評估E。

資料越多,可以把E壓得越小。如果驗證之後再用全部的資料(不分訓練和驗證)一起丟下去,可以找到更小的E。所以訓練的流程是這樣的:先切割資料,用訓練資料找到g,用驗證資料挑最小E的g,然後再用全部資料去調整這個g讓它有更小的E。

圖片來源:林軒田<機器學習基石>,第十四講,第59段,第9張

E之間的關係式如下:

各種作法對於E_out對應驗證資料集K的數量的關係則如下:

圖片來源:林軒田<機器學習基石>,第十四講,第59段,第10張
  1. 不切割資料:得到E_in,in-sample。E_out始終維持在一個較高值,因為容易有overfitting。
  2. 用外部資料E_test:最好的狀況,但實際上不可行。可以避免overfitting,客觀,可惜做不到。得到optimal,但是是虛線。
  3. 根據驗證資料選出h之後不用全部資料再訓練一次,得到紅色線。隨著K越多,訓練可用的資料也減少,導致E_out越來越高,最後可能甚至不如只從E_in挑選的狀況。
  4. 根據驗證資料選出h之後再用全部資料再訓練一次,得到藍色線。K增加之後影響也不大,因為最後會用全部資料再訓練一次。

從上圖可以知道驗證資料集的大小K對於訓練結果是有影響的。整個邏輯建立在兩件事上面:

式2.

可以做到的是E_val(g-),但最終目標是E_out(g)。K在這件事上面扮演一個造成衝突的角色,因為在上式,K越小越好做到,但在下式,K越大才越好做到。實務上,K通常抓整體資料量的5分之一(訓練:驗證資料量比=4:1)。

交叉驗證

Leave-one-out cross validation(loocv)

承接K的數量問題,先來看一個極端的狀況:K=1

此時的線條應該是接近上圖的in-sample,幾乎沒有驗證資料。式2的上式可以做到,但下式很難,因為只有一筆驗證用資料。如果把驗證用資料記為

此時n=1。而用驗證資料得到的E記為

g_n-為模型從n-1筆資料中得到的,因為驗證資料只有一筆,所以就把g拿來用在唯一的資料上,看看結果如何。只看一個e_n,當然結果是不理想的。假如預測的任務是二元分類,那預測的答案只有0/1兩個選項;但E_out(g)則未必,因為是計算和真實答案之間的落差。所以它可能是一個0–1之間的數,例如0.32。

雖然只看一筆是不準的,但如果重複做呢?一次只挑一筆來做沒錯,但每次都選不同的一筆資料來做驗證,其他時候該筆資料則是訓練資料。當然,因應每次訓練時的資料有些微變動,挑出來的模型有可能有一點不一樣,但至少,它可以通盤的考慮這個演算法本身到底表現如何。怎麼做?把每次驗證得到的e_n取平均。這樣一來,即使單一個e_n我們只能得到0/1的答案(因為和標準答案0/1比),但e_n一多之後取平均,就有機會使式2.的下式可行。

這種方法稱為leave-one-out cross validation。每次留一筆資料作驗證。

原本求E_val也改成求E_loocv。為了讓這個概念具體一點,這邊用三個資料組成的資料群和模型來做loocv。首先是線性回歸:

圖片來源:林軒田<機器學習基石>,第十四講,第60段,第14張

按照操作定義,一次去掉一個點,讓模型盡量滿足剩餘的資料點之後,再用去掉的資料點和這個模型計算落差。在這裡,落差的距離是垂線差值的平方。從這張圖可以看到,e_1的落差很大。

接著,用一個較簡單的模型 — 常數。再做一次:

圖片來源:林軒田<機器學習基石>,第十四講,第60段,第14張

和線性回歸一模一樣的操作方式。結果兩相比較之後,發現常數的E_loocv還比較小!這三個資料點,其實不用什麼複雜的模型,連線性回歸都太複雜了,常數做得比較好。在這個實驗中,利用E_loocv成功挑出適合的模型。

原本評估E_val時的式子是這樣:

現在把它用E_loocv替換:

E_loocv能提供E_out(g)的相關訊息

這一段要試著用一些數學代換的方式解釋理論上E_loocv能提供E_out(g)的相關訊息。實際上,我們只要能得到E_loocv和E_out(g-)的平均值接近就可以了,因為g-和g的訓練只差一筆資料。而E_out(g-)本身就是E_loocv的定義。

回到基礎定義,

其中ε是期望值的意思。這段式子是基礎定義,e_n就是挑出一筆資料後進行訓練,然後用那筆資料代入模型得到的差值。因為期望值和Σ都是線性的,所以可以交換,變成

然後把期望值的部分拆分,把訓練的(N-1)筆資料和驗證的1筆資料的期望值分開。因為TeX的網頁編輯器顯示不出來,我貼老師投影片的式子。

其中紅色項是訓練的部分,而藍色項就是唯一一筆驗證用的(x_n, y_n)。然後還有e_n項呀!怎麼沒寫出來呢?別急,這邊要把e_n的定義寫出來:

e_n就是驗證,也就是把訓練好的g-用剩下一筆驗證資料的x_n代入之後,看看它跟y_n的差值。但也可以想成這筆資料是g-沒看過的,因為驗證的目的就是不讓模型在訓練完成前看過資料。換句話說,e_n和期望值相乘其實就是g-的E_out

然後我們在不同的(N-1)筆資料反覆做訓練和驗證,平均求得的值是什麼呢?

就是E_out的平均值。E_out的平均值還是E_out,所以我們可以說E_loocv可以透漏(N-1)筆資料的E_out的平均,然後E_out(g-)和E_out(g)相差很近,所以就可以推論E_loocv確實能提供E_out(g)的相關訊息。

loocv在實務上的成果

例如手寫數字辨識,針對數字1,用模型來分辨是不是1。把手寫數字圖片的一些二為特徵先提取好,例如對稱性,或黑色格子的密度。針對這兩個特徵作圖如下:

圖片來源:林軒田<機器學習基石>,第十四講,第60段,第16張

然後根據多項式維度挑選模型。先做非線性轉換,把特徵投影到高維空間。模型訓練後再看E。得到E和多項式維度的關係如下

圖片來源:林軒田<機器學習基石>,第十四講,第60段,第16張

如果看E_in挑選模型,當然多項式維度越高越好,但就像前面說的,這是因為overfitting的關係。反映的是E_out在高維度表現很差。但如果是用E_loocv挑選,結果便不同。它的最低點在5次和7次多項式,對應的E_out也很不錯。因此無論是上面的三筆資料測試、理論的推導、實務上的使用,E_loocv確實是個有效的方法。

比較一下用E_in篩選的模型和用E_loocv篩遠的模型,對特徵圖畫出來的分界線。可以看到E_loocv挑出來的模型,線比較平滑,也比較不會overfitting(看到右上方那一塊和中間偏上的交界處,是兩者主要的差別)

圖片來源:林軒田<機器學習基石>,第十四講,第60段,第16張

但它也有缺點。因為每次只挑一筆資料做驗證,如果有N筆資料,交叉驗證得重複N次,相當耗時。大部分的模型都必須要重複操作,除了線性回歸 — 它在E_loocv也有公式解。而且,雖然利用平均可以較不極端,但項二元分類這樣的工作,在每個數值輸出的結果還是極端的,每一次的驗證可能會帶來比較大的影響。

V-fold cross validation

既然每次只挑一筆實在太慢,我就一次挑多一點。把全部資料分做V分,每次挑一份來驗證,剩下(V-1)份用作訓練。這樣重複的動作就從N次縮小為V次了。上面的式子一樣適用。

loocv就是V-fold的極端狀況:每份小到只有一筆資料。

通常,V會用5或10。雖然整體而言會比較穩定,因為驗證的時候有比較多資料提供計算;但整體而言運算時間可能會拉長。

驗證的本質

驗證和訓練一樣都是在挑選模型。訓練是從hypothesis set挑出最適合資料的模型,驗證則是在這些挑出來的模型中做選擇。驗證挑出來的模型理論上只剩一個,然後就要送去實戰測試了。

記住,

只要模型看過資料,這資料就不再乾淨,因為它已經影響到模型當中的某個部分。最乾淨的資料就是外面世界沒被取來訓練用,而是直接實戰使用的。

因為驗證也是選擇,只要是選擇,就會付出資料汙染、提升模型複雜度…等等的代價。所以即使經過驗證,模型的預測能力仍可能比實際樂觀,而且這還蠻常見的。

當我們回報模型的表現結果,不應該是訓練的成果,也不該是驗證的成果。應該是測試或實戰的成果。

機器學習基石系列的課程基本上紀錄到這邊。後續有時間的話還會再把老師做結論的第15講 — 機器學習的三法則,以及後續相關的一些議題補充上來。將來有時間的話也可能再針對技法篇作整理。

謝謝看到這裡的每一個你,希望這些整理對你是有幫助的。也再次謝謝林教授無私地把課程分享在線上。

我們有緣的話,在這個園地再見。此系列以外,我會繼續在深度學習發表相關文章或見解,以及代碼實作。

--

--

Martin Huang
機器學習系列

崎嶇的發展 目前主攻CV,但正在往NLP的路上。 歡迎合作或聯絡:martin12345m@gmail.com