機器學習破冰之旅(3) — Activation function的使用
初學機器學習時,對於activation function, cost function的概念一直模糊不清,直到這次整理過後一遍,好像又有發現之前沒弄清楚的部分。希望透過這篇也能帶給各位讀者新的概念。那話不多說直接開始吧~~
本篇主要以此書為主,並撰寫學習筆記,其中也會搭配書中程式碼實作。
著重討論Activation function, Cost function, Gradient descent, 標準化, Stochastic gradient descent,這些的名詞解釋,與他們對於神經元有什麼作用,日後訓練神經元時,有那些地方可以做修正。
Outline:
- 介紹Adaptive linear neuron(自適應線性神經元)+ Activation function
- 介紹Cost function(損失函數)+Gradient descent(梯度下降法)
- 標準化(Standardization)
- Batch descent(批量梯度下降法), Stochastic gradient descent(隨機梯度下降法), Mini-batch descent(小批量梯度下降法)
- 結論
- 參考資料
看到很多英文請不要慌張,一個一個字慢慢讀,多讀幾遍就會懂了~~
Adaptive linear neuron(自適應線性神經元)+ Activation function
如果已經接觸過神經網絡的話,可能會對這個單詞有點陌身,因為一般在說明時,對於adaptive linear neuron的介紹比較少(大多直接進入non-linear activation function,例如sigmoid, ReLu等等的介紹)。筆者剛開始接觸時,也沒聽過這個神經元(neuron),這次也因為才認識它。
看完之後Adaline後,感覺更能理解神經元(neuron)實際的運作,因此我認為如果可以先了解Adaline的運行模式,對日後更複雜的神經網絡,會有很大的幫助!
前情提要:上次的PLA過程實在太固定,以至於訓練效果不好的話,好像沒有太多東西可以做調整,於是想要找個辦法看可不可以找些參數來做調整(例如:縮減「迭代次數」又或者是Learning Rate等等)
正因如此,這邊就要引入新的技巧(方法)到neuron,增加其豐富性!
那就讓我們開始吧~~
進入正題:
什麼是Adaptive linear neuron?
可以想成,另一種訓練神經元的方法。
直接看圖:
回顧一下前篇的PLA
從上圖看到,Adaptive linear neuron(簡稱:Adaline)跟PLA非常相像,只差在
兩者更新(訓練) weight的方法不同
因為Adaline引入新的概念 — activation function來進行weight的更新,Adaline將其 activation function定義如下:
如果對於PLA很熟悉的話,看到上面的function應該會感到很吃驚,發現這個函式ϕ,根本什麼也沒做啊,輸入跟輸出結果完全相同。
沒錯,因為在 Adaline,最主要的目的就是引入新的概念 — activation function。也就是說,提出此概念的作者想要表示,有了activation function的出現,未來在訓練過程,不用再花大筆時間逐步更新 weight值,而是能夠透過某種方法(or function),更精準地更新 weight值。因此在 Adaline中,為了方便理解,activation function就直接延用前面的 Net_input,不多做其他的修改。
**注意**
在Adaline中使用的是 linear activation function,跟常見的non-linear activation function有所不同。
後面章節,會再介紹 linear activation function和 non-linear activation function的不同。
接下來,有了activation function,Adaline是如何精準地更新weight?
介紹Cost function + Gradient descent
在介紹activation function更精準的更新weight前,先帶大家了解一些重要的專有名詞吧。
有時候,在提到神經網絡的時候,可能會提到”target function”,這邊簡單介紹一下,target function的目的是將訓練效果最佳化,而具體呈現的過程,指得是cost function最小化的過程。
那什麼是 Cost function?
Cost function有時候也用Loss function來代替,中文翻為「損失函數」。
以筆者的理解來解釋的話,Cost function最主要的目的是計算(評估)Label資料(y)
和預測結果(y_hat)
之間的誤差。而計算(評估)的方式有很多種。常見的有「均方誤差(mean squared error)」、「交叉熵(Cross Entropy)」等等。
Adaline — Cost function
以Adaline為例,讓大家能更了解cost function的使用。
在Adaline中定義 Cost function: J
,這邊的 cost function,我們使用 sum of squared error(殘差平方和)
(公式如下)
先觀察一下,這個數學式,裡面有什麼變數:
- y (Label值)
- 函式 ϕ (activation function)
有了上述觀念,也定義好Cost function後,要怎麼讓cost function搭配weight使用呢?
別急別急,我們先將cost function放到口袋裡收好,等等再拿出來使用。
一開始有提到activation function的出現,是為了可以更精確的更新weight值吧。
那為什麼有 activation function的話,可以更精確的更新weight值?
Ans: 以 Adaline為例,計算出 net_input
z
後會先經過 linear activation function,前面有一直強調 linear的重要。因為 linear代表,在將 activation function代入cost function時,整個數學式子將會變得可微(differentiable)。(可微 → 更容易找到極值)。反之,PLA則是使用unit step function(階梯函數),不能微分。
為什麼要找到極值?
Ans: 一開始在訓練時,神經網絡的訓練出的結果與正確解答,想必其誤差一定很大吧,所以我們想要找有效且快速的方式讓誤差快速下降。這時,微分的技巧就派上用場拉!
Gradient Descent (梯度下降法)
剛剛所說的只是紙上談兵,那程式碼要如何完成求極值(微分)的方法?
Ans: 使用 Gradient Descent(梯度下降法),來尋找 Cost function的最小值。(如下圖)
可能會有人疑問,為什麼是最小值?
因為 cost function代表的是,預測結果
(y_hat)
跟資料 Label(y)
的誤差值,所以理當要讓計算出的誤差值越小越好。
計算方式,放到下面做解釋(將使用到偏微分的技巧)。
好了,現在可以把剛剛放到口袋裡的cost function 拿出來,與先前所提到的gradient descent搭配使用。
Adaline更新公式:
一步一步帶大家慢慢理解
更新公式應該還沒忘吧~~
(和PLA是一樣的)
weight應該要如何做修正?
Ans: 引入Gradient descent ∇J(w) ,作為Adaline的更新weight的依據。
請看:左圖👈
∇J(w)要怎麼計算?
Ans: 剛剛有提到說,可以利用微分來獲得極值。這邊將會對每一個cost function的weight(w_j)
進行偏微分。
請看:左圖👈
**同樣需要注意,weight是一個矩陣,所以在進行更新的過程**、
是整個矩陣「同時」進行更新
雖然這個看起來和PLA沒有什麼不一樣,但是實際上,運行的過程其概念「不相同」,在更新的過程中,Adaline使用的activation function
→ ϕ(z^(i)),得到的是一個「真值」並搭配gradient descent使用;而PLA則是使用unit step function(類似已經分類過的答案),再和原本的Label資料
資料一起計算。(如下圖)
由此可知,在Adaline更新weight值時,同時使用到
- Linear activation function
- Cost function
- Gradient descent
這些概念在機器學習中常常會使用到,希望大家能好好認識他們。
程式碼實作:
程式說明:
以防有些讀者,這段不清楚怎麼使用,說明一下。
self.w_[0] += self.eta * error().sum()
w[0]
是我們那時為了方便計算自行加上去的,其x_0
保持為1,因此程式碼省略掉x_0 = 1
,直接用errors
的總合去計算(就算用1乘上去,結果還是一樣嘛)。因此w[0]
還有另一個名稱為bias(偏差),顧名思義,也是計算整個grdient descent的總誤差。
輸出結果:
說明:(左上圖)當Learning Rate = 0.01
時,隨著迭代次數的增加,誤差值也變得越來越大,無法訓練出適當的神經元(無法收斂)。會出現這種情況,代表學習速率設得不好,導致neuron無法好好學習。(概念如下圖最右邊Too high)。
解釋:當 Learning Rate設得太大時,weight的更新,可能會突然往下修正太多,又或者是突然往回修正太多,導致神經元找不到最佳平衡點。
正常的訓練結果,應該要像中間(Just right),隨著迭代次數增加,誤差值變得越來越小。
有上述概念後,現在又出現新的問題了,為了避免一直去調整那些參數,我們還可以事先做哪些處理,讓資料變得比較好訓練呢?
接下來要介紹其他可以增加神經元(neuron)學習速度的方法。
標準化(Standardization)
標準化是feature scaling(特徵縮放)的技巧之一。
標準常態分配(Standard Normal Distribution)其特性是 μ= 0,σ = 1。
資料標準化的方法,將原始資料轉換成 Z — score,使得轉換後的資料,其平均值(μ)=0, 標準差(σ)=1,可以想成是將原資料按照比例縮放到[0, 1]之間。(公式如下)
此技巧的目的:為了讓Gradient descent能夠更快下降,以獲得良好的學習效果(更快收斂 →更快找到最小誤差值)
程式碼:
輸出結果:
從圖中,在前一個程式碼中,Learning Rate=0.01,原本是不能收斂,但經過標準化(Standization)後,即可完成收斂了,由此可見,標準化有助於梯度的下降,也就是加快神經元(neuron)的學習速度。
Batch gradient descent(批量梯度下降法), Stochastic gradient descent(隨機梯度下降法)
除了使用標準化資料的方式,更新weight的「迭代」方式,也同樣會影響學習的速度(效果)。在這邊跟各位鄭重的介紹,另一種更新方式 — Stochastic Gradient descent(通常會用SGD表示)。
前面的程式碼,是使用Batch gradient descent,一次把整個資料進行更新。由於目前的資料筆數不多,執行效果還不錯。但如果今天,資料有上百萬筆的話,weight更新速率的效果可能就不會像現在這樣那麼好了。
要換個方法更新weight才行!
而另一種替換Batch gradient descent的方法,就是使用Stochastic gradient descent(也稱 Iterative or Online gradient descent),比起一次更新一大筆資料的weight值,改成以單筆單筆資料,來做更新。
(和Batch相比,少了Sigma)
Mini-Batch gradient descent
另外還有一種是介於 Batch gradient descent 和 SGD之間的更新方式 — Mini -batch learning。比起一般的 Batch gradient descent,需要對「整筆資料」做更新;Mini-batch,則會設定某個數值來做更新。假設是 Mini-batch設定35好了,代表每35筆資料,會更新一次 weight值。而 Mini-batch會比 Batch gradient descent更容易收斂(convex),因為他更新的次數更多。
程式碼如下:
說明:整個程式碼跟Batch gradient descent大致上來說差不多。主要差在訓練weight的部分,其中有多另外加上shuffle, update_weight等等函式。Shuffle最主要的目的,是避免同樣的次序一直重複,所以加上shuffle可以把資料,打亂後,再重新訓練。
書中的作者,使用了蠻多很精簡的寫法(更符合python的寫法),很建議大家可以去了解一下,有助於增加自己的程式能力!!
我…我也在裡面學到了不少東西~~😅
除此之外:Learning Rate在訓練過程中也可以透過以下公式進行調整。
c1, c2:自行設定的常數(constant)
結論
這篇最主要想傳達的重點在於Activation function, Cost function, Gradient descent, 標準化, Stochastic gradient descent,這些的名詞解釋,與他們對於神經元有什麼作用,日後訓練神經元時,有那些地方可以做修正。這些概念在日後接觸到新的演算法時,皆佔有重要的地位。還請因為這篇能對他們有更深入的認識。
如果對於文章有任何疑問或錯誤的話,懇請各位不吝指教~~
那我們就下次再見囉!
參考資料:
Python Machine Learning: Machine Learning and Deep Learning(章節2)