[筆記] 機器學習 神經網路 - 進階學習
代價函數與反向傳播算法 ( Backpropagation )
符號定義 :
L: 神經網路中擁有的層數sₗ: 第 l 層中的單元個數K: 輸出的單元 ( 分類 ) 個數
神經網路的代價函數

神經網路中的代價函數
- 過往的正規化就是計算輸出層中的每個單元
 - 而在神經網路則是機算整個網路中的所有單元
 - 此 i ( 後者 ) 並非訓練資料的 i ( 前者 )
 
反向傳播算法 ( Backpropagation )
是一種訓練神經網路的常見方法,與梯度下降結合使用,目的是找到一組能最大限度地減小誤差的權重
演算法 :
假設有訓練資料 {(x⁽¹⁾, y⁽¹⁾) ... (x⁽ᵐ⁾, y⁽ᵐ⁾)}
設定 Δᵢⱼ⁽ˡ⁾ := 0 ( for all l, i, j )
For i = 1 to m :
- 設定 
a⁽¹⁾ := x⁽ⁱ⁾ - 計算 
a⁽ˡ⁾ ( for l = 2, 3, ..., L ) - 使用 
y⁽ⁱ⁾計算δ⁽ᴸ⁾ = a⁽ᴸ⁾ - y⁽ⁱ⁾,L 代表 output layer 使用
δ⁽ˡ⁾ = ((Θ⁽ˡ⁾)ᵀδ⁽ˡ⁺¹⁾) .* a⁽ˡ⁾ .* (1 - a⁽ˡ⁾)計算δ⁽ᴸ⁻¹⁾, δ⁽ᴸ⁻²⁾, ..., δ⁽²⁾- 激勵函數的導函數 : 
g'(z⁽ˡ⁾) = a⁽ˡ⁾ .* (1 - a⁽ˡ⁾) 
- 激勵函數的導函數 : 
 Δᵢⱼ⁽ˡ⁾ := Δᵢⱼ⁽ˡ⁾ + aⱼ⁽ˡ⁾δᵢ⁽ˡ⁺¹⁾,向量化 :Δ⁽ˡ⁾ := Δ⁽ˡ⁾ + δ⁽ˡ⁺¹⁾(a⁽ˡ⁾)ᵀDᵢⱼ⁽ˡ⁾ := (1 / m)(Δᵢⱼ⁽ˡ⁾ + λΘᵢⱼ⁽ˡ⁾),if j ≠ 0Dᵢⱼ⁽ˡ⁾ := (1 / m) Δᵢⱼ⁽ˡ⁾,if j = 0
1  | function [J grad] = nnCostFunction(nn_params, input_layer_size, hidden_layer_size, num_labels, X, y, lambda)  | 
- 在 Octave 上的前向傳播與反向傳播
 
1  | function g = sigmoidGradient(z)  | 
在 Octave 上的激勵函數的導函數
δⱼ⁽ˡ⁾就是aⱼ⁽ˡ⁾的偏差,也是代價函數的導數

δ₁⁽⁴⁾ = a₁⁽⁴⁾ - y⁽ⁱ⁾δ₂⁽³⁾ = Θ₁₂⁽³⁾ * δ₁⁽⁴⁾δ₂⁽²⁾ = Θ₁₂⁽²⁾ * δ₁⁽³⁾ + Θ₂₂⁽²⁾ * δ₂⁽³⁾
實作反向傳播算法
矩陣展開成向量與還原
- 在 
fminunc()的高級優化算法中,通常都需要傳入向量,這時我們就需要將矩陣展開成向量 
1  | thetaVector = [Theta1(:); Theta2(:); Theta3(:);]  | 
- 假設有 Θ⁽¹⁾、Θ⁽²⁾、Θ⁽³⁾,D⁽¹⁾、D⁽²⁾、D⁽³⁾,展開成向量
 
1  | Theta1 = reshape(thetaVector(1:110), 10, 11)  | 
- 假設 Θ⁽¹⁾ 為 10 11 矩陣、Θ⁽²⁾ 為 10 11 矩陣、Θ⁽³⁾ 為 1 * 11 矩陣,將他們還原
 
應用
1  | 創建初始化的 Θ⁽¹⁾、Θ⁽²⁾、Θ⁽³⁾  | 
- 使用 
fminunc() 
1  | function [jval, gradientVec] = costFunction(thetaVec)  | 
costFunction()寫法
梯度驗證 ( Gradient Checking )
- 通常使用反向傳播算法可能會出現許多 BUG,梯度驗證可以確保我們的反向傳播算法是如預期地工作的
 - 算式 :
 

- 有多個 Θ 矩陣時 :
 

- 通常 
ϵ設定為 10⁻⁴,如果太小會導致數值問題 
1  | epsilon = 1e-4;  | 
- 在 Octave 上的梯度驗證
 - 驗證 
gradApprox ≈ deltaVector,確定反向傳播算法沒有錯誤後,就必須把梯度驗證關掉了,因為梯度驗證會導致程式執行非常的慢 
隨機初始化 ( Random Initialization )
- 在神經網路中,將 Θ 的所有權重初始化為 0 是不適合的
 - 這樣會因為對稱而造成所有節點更新為相同的值
 - 所以我們需要使用下面方法來隨機初始化 ( 打破對稱 Symmetry breaking ) Θ 的權重 :
 

- 將每個 
Θᵢⱼ⁽ˡ⁾初始化為[−ϵ, ϵ]之間的隨機值,此ϵ並非梯度驗證的ϵ 
1  | %If the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11.  | 
- 在 Octave 上的隨機初始化概念
 
1  | function W = randInitializeWeights(L_in, L_out)  | 
- 在 Octave 上的隨機初始化
 
總結
神經網路的布局
- input 單元數 = 特徵數 ( x )
 - output 單元數 = 類別數 ( y )
 - hidden 單元數通常越多越好,但計算的成本通常會隨之增加,必須取得平衡
 潛規則 :
- 至少有一層 hidden layer
 - 有兩層以上的 hidden layer,則建議每層單元數都相同
 
訓練神經網路
- 隨機初始化權重 ( Θ )
 - 實現向前傳播取得 hΘ(x⁽ⁱ⁾)
 - 實現代價函數
 實現反向傳播算法以計算導數

1
2
3
4
5
6for i = 1:m,
使用 (x⁽ⁱ⁾, y⁽ⁱ⁾) 執行向前傳播與反向傳播
取得 a⁽ˡ⁾ 與 delta d⁽ˡ⁾ ( l = 2, ..., L )
end;使用梯度驗證確認反向傳播算法是否正確,確認後關閉
- 使用梯度下降或其他最優化功能計算代價函數最小值,並獲得 Θ 的權重
 

