機器學習01 - Regression 案例學習 (下)

weixin_34253539發表於2018-02-12

續上

緊接著上面一篇文章 ML01 - Regression 案例學習 (上) 講到的 Gradient Descent,我們現在有了 ModelTraining DataLoss Function,我們的 Model:

$$ y = b + w \cdot x_{cp} $$

經過訓練呢,我們得出以下結果:

$$ b=-188.4 \\\ w=2.7 $$

將 $w$ 和 $b$ 代入到原 Model 中,我們就能得到一個一次方程,我們將其畫在座標軸上就是這樣(橫軸代表進化前的 CP 值,縱軸代表進化後的 CP 值):

20180211151832902416954.jpg

計算下來的 $L(w,b)=31.9$。

當然,以上資料僅僅是我們用已知的 10 只寶可夢訓練出來的 Model,如果現在新拿給我們一隻寶可夢,代入這個 Model 進行計算,得到的預測資料與實際資料會相差多少呢?

所以我們又捉了 10 只與之前完全不同的寶可夢,代入計算了一下,如下:

20180211151832965678425.jpg

可以看到,我們 Model 計算出來的資料與新的 10 只寶可夢實際的資料還是挺契合的。實際計算下來,這 10 只寶可夢的 $L_{w,b}=35.0$。在座標軸的左下方和右上方,誤差會更大一些。

那我們如何才能將左下方和右上方的那些資料也都包含到我們的 Model 中呢?當前我們的 ModelLinear Model 也就是線性的,在圖中我們能夠很明顯的看出,用一條紅色的直線,再怎麼都不可能將所有藍色點都包含進去。所以,我們現在需要一個更強的 Model

第五步:Selecting Another Model

我們更進一步,由於圖中的藍色點並不可能在一條直線上,我們就嘗試一下,選用二次方程的曲線來擬合它們:

$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2 $$

然後我們通過之前的辦法訓練這個 Model,找出來最好的結果對應的是:

$$ b=-10.3 \\\ w_1=1.0 \\\ w_2=2.7*10^{-3} \\\ L(w_1,w_2,b)=15.4 $$

對應的圖形是這樣的:

20180211151833092840731.jpg

如果我們將其用在 Testing Set 上呢,對應的 $L(w_1,w_2,b)=18.4$,對應的圖形是:

20180211151833105363807.jpg

如果我們現在將剛才的二次 Model 改成三次方程呢:

$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2+w_3\cdot x_{cp}^3 $$

同樣訓練過後,得出:

$$ b=6.4 \\\ w\_1=0.66 \\\ w_2=4.3\*10^{-3} \\\ w_3=-1.8\*10^{-6} \\\ L(w_1,w_2,w_3,b)=15.3 $$

圖形長這樣,看上去和二次的 Model 沒有太大的區別:

20180211151833138534761.jpg

Testing Set 上得到的 $L(w_1,w_2,w_3,b)=18.1$,有好一點點:

20180211151833145573102.jpg

那如果我們換用四次方程Model 的話,訓練結果會不會更好一些呢:

$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2+w_3\cdot x_{cp}^3+w_4\cdot x_{cp}^4 $$

Training Data 下,擬合曲線如下圖,很明顯的擬合更準確了一些,$L=14.9$:

20180211151833163648570.jpg

我們再看看它在 Testing Set 上的表現如何呢:

20180211151833175341410.jpg

實際結果竟然是 $L=28.8$,反而比三次方程更糟糕了!!如果我們換做 5 次、6 次或者更高次方程的 Model 情況會不會變好呢?

下面我們再用五次方程的 Model 來訓練一下,看看效果如何:

$$ y = b+w_1\cdot x_{cp}+w_2\cdot x_{cp}^2+w_3\cdot x_{cp}^3+w_4\cdot x_{cp}^4+w_5\cdot x_{cp}^5 $$

在五次方程的 Model 下,Training Data 的 $L=12.8$,確實變好了,而 Testing Set 的 $L=232.1$,糟糕透頂。

20180211151833208245521.jpg

現在,我們將上面五個 Model (分別為一次方程、二次方程、三次方程、四次方程、五次方程),以及他們的 Loss Funciton $L$ 的值都畫在一張圖中,我們可以發現,隨著引數的增多、方程次數的增大,我們擬合的效果是越來越好,誤差是越來越小的:

20180211151833241633413.jpg

這很好解釋,因為,二次方程中其實就已經包含了一次方程的情況(使二次方程中$w_2=0$,它就變為了一次方程),所以二次方程除了擬合一次方程已經擬合到的點,還能夠擬合更多一次方程沒有擬合到的點。所以,它的誤差就會比一次方程更小。同理三次方程會比二次方程擬合更好、誤差更小...五次方程會比四次方程擬合得更好、誤差更小。

但是,在 Testing Data 上則不相同了,我們將不同 ModelTraining DataTesting Data 上 $L$ 的變化畫在同一張圖中(藍色線代表 Training Data 的結果,橙色線代表 Testing Data 的結果):

20180211151833290993393.jpg

我們發現,越複雜的 ModelTraining Data 下表現會越來越好,而在 Testing Data 下則不一定。

這種現象我們就把它叫做 Overfitting(過度擬合)。舉個例子來說,如果我們想訓練機器人識別人類,我們就把小明拿給它學習。在只讓機器人記住一項特徵的時候,他就記住:有兩隻眼睛的是人類;只讓它記住兩項特徵的時候,他會發現:噢,有兩隻眼睛,一個嘴巴的是人類;當我們讓它能記住三項特徵的時候,他就可能會記作:有兩隻眼睛,一個嘴巴,戴著帽子的是人類,這種情況下,機器人對小明這個人類的個體描述得就很明確了,但是對於人類這個整體來說,就過度擬合了(並不是所有人都戴帽子,就會導致這個機器人識別不出來很多人類)。

所以我們應當合理地選取 Model,在減少擬合不夠情況的同時避免過度擬合

前面我們的訓練都是在 10 只寶可夢的資料上做的,那如果我們選取更多的寶可夢,情況會是怎麼樣的呢?下面我們就選取了 60 只寶可夢,繪製在圖上:

20180211151833388334807.jpg

能看出來,這個分佈並不是簡單的屬於一次、二次、三次...式,它其中,應該還有另一個因素在很大程度上影響進化後的結果,很明顯,應該就是不同寶可夢對應的物種:

下圖中,我們將這些寶可夢,按照不同的物種,將其用不同顏色繪製:

20180211151833421799216.jpg

嗯,大概是這麼一個畫風:

20180211151833429555232.jpg

那看來我們可能犯了一個嚴重的錯誤,忽略了物種的影響。

重回第一步:Redesign the Model

根據不同的物種,我們需要有不同的 Model,物種這個屬性,就對應的是每個 $x$ 的 $x_s$:

$$ \mbox{輸入 }x \\\ \downarrow \\\ y = \begin{cases} b_1+w_1\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Pidgey} \\\ b_2+w_2\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Weedle} \\\ b_3+w_3\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Caterpie} \\\ b_4+w_4\cdot x_{cp}, & \mbox{if }x_s=\mbox{ Eevee} \end{cases} \\\ \downarrow \\\ \mbox{輸出 }y $$

那難道我們需要為每個不同的物種設定單獨的 Linear Model(線性模型) 嗎?這似乎太麻煩了,寶可夢的物種至少有十多類並且還在持續增加。我們能不能用某個特殊的函式將不同的物種都包含進一個 Linear Model 呢?答案是:有的!

我們需要引進一個函式 $\delta()$,它的作用就是,給一個輸入,他要麼輸出 1 要麼輸出 0 (訊號與系統的知識)

$$ \delta(x_s=\mbox{ Pidgey}) \\\ \downarrow \\\ \begin{cases} =1 & \mbox{if }x_s=\mbox{ Pidgey} \\ =0 & \mbox{ 其他情況} \end{cases} $$

那我們的 Model 就可以改寫為:

$$ \begin{align} y = & \ b_1\cdot \delta(x_s=\mbox{ Pidgey}) \\\ & +w_1\cdot \delta(x_s=Pidgey)x_{cp} \\\ & +b_2\cdot \delta(x_s=\mbox{ Weedle}) \\\ & +w_2\cdot \delta(x_s=Weedle)x_{cp} \\\ & +b_3\cdot \delta(x_s=\mbox{ Caterpie}) \\\ & +w_3\cdot \delta(x_s=Caterpie)x_{cp} \\\ & +b_4\cdot \delta(x_s=\mbox{ Eevee}) \\\ & +w_4\cdot \delta(x_s=Eevee)x_{cp} \\\ \end{align} $$

比如,我們現在輸入一個 Pidgey,那 $x_s=\mbox{ Pidgey}$,上面的式子就會變成:

$$ \begin{align} y = & \ b_1\cdot 1 \\\ & +w_1\cdot 1 \cdot x_{cp}\\\ & +b_2\cdot 0 \\\ & +w_2\cdot 0 \cdot x_{cp} \\\ & +b_3\cdot 0 \\\ & +w_3\cdot 0 \cdot x_{cp} \\\ & +b_4\cdot 0 \\\ & +w_4\cdot 0 \cdot x_{cp} \\\ \end{align} \\\ \downarrow \\\ y = b_1 +w\_1 \cdot x\_{cp} \\\ $$

所以,現在我們這個 Model 依然是一個 Linear Model

做出來的效果怎麼樣呢?

20180211151833764651008.jpg

$L=3.8$,效果和圖中看到的一樣,非常好的擬合了 Training Data。但我們真正在意的是它在 Testing Data 上的表現,這幾乎決定了這個 Model 的好壞。

20180211151833785915019.jpg

結果是 $L=14.3$,比我們以往的所有結果都要好,說明這個思考方式我們是做對了的!

但是仔細看,我們發現,還是有一些點擬合得不夠。回想一下,我們剛才只代入了寶可夢的種類 $x_s$ 進行運算,並沒有考慮它的其他屬性對進化後 CP 值的影響,比如:進化前的體重、高度、生命值等等,這些因素都有可能會影響到一隻寶可夢進化後 CP 值的變化情況:

20180211151833821134514.jpg

我們該如何將這些因素都考慮進去呢?最簡單也是最直接的一個方式就是:把所有屬性都傳進 Model 中進行運算,那我們就需要設計一個略微複雜的 Model

$$ \mbox{輸入 }x \\\ \downarrow \\\ y' = \begin{cases} b\_1+w_1\cdot x_{cp}+w_5\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Pidgey} \\\ b\_2+w_2\cdot x_{cp}+w_6\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Weedle} \\\ b\_3+w_3\cdot x_{cp}+w_7\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Caterpie} \\\ b\_4+w_4\cdot x_{cp}+w_8\cdot(x_{cp})^2, & \mbox{if }x_s=\mbox{ Eevee} \end{cases} \\\ \downarrow \\\ y = y'+w_9\cdot x_{hp}+w_{10}\cdot(x_{hp})^2+w_{11}\cdot x_{h}+w_{12}\cdot(x_{h})^2+w_{13}\cdot x_{w}+w_{14}\cdot(x_{w})^2 \\\ \downarrow \\\ \mbox{輸出 }y $$

這樣,我們既顧及了每隻寶可夢物種的特殊性,又增加了 HP 、height 和 weight 三個額外的屬性進行分析,總共 18 個引數。

果然,我們得到了一個非常低的 Loss $L=1.9$,但是,根據以往的經驗,這麼多引數,我們很有可能會造成 Overfitting 的結果。經過 Testing Data 的運算,$L=102.3$,算是比較糟糕的一個結果了。接下來又怎麼處理呢?

重回第二步:Regularization

之前我們的輸出 $y$ 定義為:

$$ y=b+ \sum w_i x_i $$

我們需要在 Loss Function $L$ 的基礎上,增加另一個因子,也就是下面公式中,$\color{Red}+$ 號後面的部分:

$$ L= {\sum_n (\widehat{y}^n - (b+\sum w_i x_i))^2} {\color{Red}+\lambda\sum(w_i)^2} $$

這裡的 $\lambda$ 是一個引數,需要我們事先給出並手動調節的(它的值越大,我們的 Loss Function 就越平滑)。加入 $w_i$ 的意思就是說,在滿足 $L$ 儘可能小的前提下,讓 $w_i$ 也儘可能地小。因為如果 $w_i$ 越小,輸入中 $x$ 值的變化,所帶來的 $w_i\cdot x$ 的變化就越小,也就是 $\Delta y$ 越小。這樣的話,不同的輸入之間,微小的差異就可以控制在一定的範圍內,不會對系統產生過大的影響,也就在最大可能上避免了 Overfitting 的發生。當然,它並不需要包含 $b$,因為 $b$ 只是一個常數,並不會隨著 $x$ 的變化而變化,所以加上與否,對系統幾乎沒有影響。

那最終結果怎麼樣呢?

20180211151834219287501.jpg

上圖中,我們將 $\lambda$ 的值從 0 調整到 100000,可以明顯看出,其在值為 100 左右的時候,效果是最好的(我們希望 Loss Function 適當地平滑,這可以去除一些噪聲對結果的干擾,但過於平滑的話,訓練資料對結果的影響又會變得過小,從而減弱了有益特徵值對系統的影響)。

最終,我們得到了一個基本可用的寶可夢進化 CP 值預測系統。當然,由於我們所用的訓練資料種類還是偏少,可能在實際的使用中會出現很多系統從來沒遇到過的物種,這個時候基本上系統會給出錯誤率很高的預測值。

本文總結

  1. 我們最開始通過確定一個 Linear Model 來訓練寶可夢的資料,結果發現,有很多的資料都是沒辦法擬合的(線性模型在圖上看來就是一條直線);
  2. 然後我們就想到了用二次方程來擬合,結果是:在 Training Data 上,Loss Function 的輸出的卻變小了,並且在 Testing Data 上,也得到了同樣的結果;
  3. 我們就開始思考,是否通過增加模型的複雜度,就能訓練出更好的模型?然後我們就嘗試了三次方程四次方程五次方程,結果發現,雖然隨著方程複雜度的增大,在 Training Data 上的 $L$ 輸出越來越小,但是在 Testing Data 上,$L$ 變得非常不穩定,並且有快速增大的趨勢。我們就意識到,現在的模型 Overfitting 了;
  4. 然後我們發現,選取的寶可夢可能有點少了,才導致了個別的特性在訓練中變得比較突出加重了 Overfitting 發生的可能性。所以我們又選取了 50 只,一共 60 只寶可夢來進行分析;
  5. 在將 60 只寶可夢繪製在座標軸上時,我們又發現了一個新的問題,這些點在某些範圍內,分佈是比較有規律的。所以我們將各個寶可夢根據它們所屬的物種進行了分類,然後重新設計了 Model,用到了 $\delta()$ 函式,這個函式針對不同的輸入,只會返回 0 或者 1;
  6. 我們將重新設計的模型通過訓練後發現,效果顯著,但是還有提升空間,因為有的點並沒有被擬合到,所以我們猜想,會不會 CP 的變化不僅和物種 $x_s$ 有關,還和它的生命值 $x_{hp}$、高度$x_h$、重量$x_w$有關呢?所以我們將這些因素都代入了 Model 進行計算,總共用到了 18 個引數。
  7. 由於之前我們有過經驗,Model 過於複雜就有很大可能發生 Overfitting 的現象。果不其然,這次又過度擬合了,為了解決這個問題,我們在 Loss Function 中,加入了一個額外的式子 $\lambda\sum(w_i)^2$,由於我們訓練的依據就是儘量的讓 Loss Function 變小,所以我們就需要讓剛才這個式子也儘量的小,也就是讓 $w_i$ 儘量小,這樣的話整個 Loss Function 就會變得比較平滑,減少噪聲的影響,這也就 Regularization(正則化)的作用;
  8. 最終,我們通過調節 $\lambda$ 的值,得到了比較滿意的一個訓練結果,在 Training DataTesting Data 上的 Loss $L$ 都比較小,不過考慮到我們所使用的寶可夢種類還是太少,如果要將這個系統做到上線實用的話,還需要更豐富的訓練資料來訓練。

今天更新到這裡,期待下一課...

相關文章