神經網絡從大腦的工作原理得到啟發,可用于解決通用的學習問題。神經網絡的基本組成單元是神經元(neuron)。每個神經元具有一個軸突和多個樹突。每個連接配接到本神經元的樹突都是一個輸入,當所有輸入樹突的興奮水準之和超過某一門檻值,神經元就會被激活。激活的神經元會沿着其軸突發射信号,軸突分出數以萬計的樹突連接配接至其他神經元,并将本神經元的輸出并作為其他神經元的輸入。數學上,神經元可以用感覺機的模型表示。
一個神經元的數學模型主要包括以下内容:
名稱
符号
說明
輸入 (input)
$x$
列向量
權值 (weight)
$w$
行向量,次元等于輸入個數
偏置 (bias)
$b$
标量值,是門檻值的相反數
帶權輸入 (weighted input)
$z$
$z=w · x + b$ ,激活函數的輸入值
激活函數 (activation function)
$σ$
接受帶權輸入,給出激活值。
激活值 (activation)
$a$
标量值,$a = σ(vec{w}·vec{x}+b)$
$$
a
= \sigma(
\left[ \begin{matrix}
w_{1} & ⋯ & w_{n} \\
\end{matrix}\right] ·
\left[ \begin{array}{x} x_1 \\ ⋮ \\ ⋮ \\ x_n \end{array}\right] +
b
)
激活函數通常使用s型函數,又稱為sigmoid或者logsig,因為該函數具有良好的特性:光滑可微,形狀接近感覺機所使用的硬極限傳輸函數,函數值與導數值計算友善。
σ(z) = \frac 1 {1+e^{-z}}
σ'(z) = σ(z)(1-σ(z))
也有一些其他的激活函數,例如:硬極限傳輸函數(hardlim),對稱硬極限函數(hardlims),線性函數(purelin) , 對稱飽和線性函數(satlins) ,對數-s形函數(logsig) ,正線性函數(poslin),雙曲正切s形函數(tansig),競争函數(compet),有時候為了學習速度或者其他原因也會使用,表過不提。
可以并行操作的神經元組成的集合,稱為神經網絡的一層。
現在考慮一個具有$n$個輸入,$s$個神經元(輸出)的單層神經網絡,則原來單個神經元的數學模型可擴充如下:
輸入
同層所有神經元共用輸入,故輸入保持不變,仍為$(n×1)$列向量
權值
由$1 × n$行向量,變為$s × n$矩陣,每一行表示一個神經元的權值資訊
偏置
由$1 × 1$标量變為$s × 1$列向量
帶權輸入
激活值
\left[ \begin{array}{a} a_1 \\ ⋮ \\ a_s \end{array}\right]
w_{1,1} & ⋯ & w_{1,n} \\
⋮ & ⋱ & ⋮ \\
w_{s,1} & ⋯ & w_{s,n} \\
\left[ \begin{array}{b} b_1 \\ ⋮ \\ b_s \end{array}\right]
單層神經網絡能力有限,通常都會将多個單層神經網絡的輸出和輸入相連,組成多層神經網絡。
多層神經網絡的層數從1開始計數,第一層為輸入層,第$l$層為輸出層,其它的層稱為隐含層。
每一層神經網絡都有自己的參數$w,b,z,a,⋯$,為了差別,使用上标區分:$w^2,w^3,⋯$。
整個多層網絡的輸入,即為輸入層的激活值$x=a^1$,整個網絡的輸出,即為輸出層的激活值:$y'=a^l$。
因為輸入層沒有神經元,是以該層所有參數中隻有激活值$a^1$作為網絡輸入值而存在,沒有$w^1,b^1,z^1$等。
現在考慮一個$l$層的神經網絡,其各層神經元個數依次為:$d_1,d_2,⋯,d_l$。則該網絡的數學模型可擴充如下:
輸入仍然保持不變,為$(d_1×1)$列向量
由$s × n$矩陣擴充為$l-1$個矩陣組成的清單:$w^2_{d_2 × d_1},⋯,w^l_{d_l × d_{l-1}}$
由$s × 1$列向量擴充為$l-1$個列向量組成的清單:$b^2_{d_2},⋯,b^l_{d_l}$
由$s × 1$列向量擴充為$l-1$個列向量組成的清單:$z^2_{d_2},⋯,z^l_{d_l}$
由$s × 1$列向量擴充為$l$個列向量組成的清單:$a^1_{d_1},a^2_{d_2},⋯,a^l_{d_l}$
\left[ \begin{array}{a} a^l_1 \\ ⋮ \\ a^l_{d_l} \end{array}\right]
w^l_{1,1} & ⋯ & w^l_{1,d_{l-1}} \\
w^l_{d_l,1} & ⋯ & w^l_{d_l,d_{l-1}} \\
\left[ \begin{array}{x} a^{l-1}_1 \\ ⋮ \\ ⋮ \\ a^{l-1}_{d_{l-1}} \end{array}\right] +
\left[ \begin{array}{b} b^l_1 \\ ⋮ \\ b^l_{d_l} \end{array}\right])
多層神經網絡的權值由一系列權值矩陣表示
第$l$層網絡的權值矩陣可記作$w^l$,表示前一層($l-1$)到本層($l$ )的連接配接權重
$w^l$的第$j$行可記作$w^l_{j*}$ ,表示從$l-1$層所有$d_{l-1}$個神經元出發,到達$l$ 層$j$号神經元的連接配接權重
$w^l$的第$k$列可記作$w^l_{*k}$ ,表示從$l-1$層第$k$号神經元出發,到達$l$ 層所有$d_l$個神經元的連接配接權重
$w^l$的$j$行$k$列可記作$w^l_{jk}$,表示從$l-1$層$k$号神經元出發,到達$l$ 層$j$神經元的連接配接權重
如圖,$w^3_{24}$表示從2層4号神經元到3層2号神經元的連接配接權值:
隻要記住,權值矩陣$w$的行标表示本層神經元的标号,列标表示上層神經元的标号即可。
前饋(feed forward)是指神經網絡接受輸入,産生輸出的一次計算過程。又稱為一次推斷(inference)。
計算過程如下:
\begin{align}
a^1 &= x \\
a^2 &= σ(w^2a^1 + b^2) \\
a^3 &= σ(w^3a^2 + b^3) \\
⋯ \\
a^l &= σ(w^la^{l-1} + b^l) \\
y &= a^l \\
\end{align}
推斷實際上就是一系列矩陣乘法與向量運算,一個訓練好的神經網絡可以高效地使用各種語言實作。神經網絡的功能是通過推斷而展現的。推斷實作起來很簡單,但如何訓練神經網絡才是真正的難點。
神經網絡的訓練,是調整網絡中的權值參數與偏置參數,進而提高網絡工作效果的過程。
通常使用梯度下降(gradient descent)的方法來調整神經網絡的參數,首先要定義一個代價函數(cost function)用以衡量神經網絡的誤差,然後通過梯度下降方法計算合适的參數修正量,進而最小化網絡誤差。
代價函數是用于衡量神經網絡工作效果的函數,是定義在一個或多個樣本上的實值函數,通常應滿足以下條件:
誤差是非負的,神經網絡效果越好,誤差越小
代價可以寫成神經網絡輸出的函數
總體代價等于個體樣本代價的均值:$c=\frac{1}{n} \sum_x c_x$
最常用的一個簡單的代價函數是:二次代價函數,又稱為均方誤差(meansquareerror)
c(w,b) = \frac{1}{2n} \sum_x{{\|y(x)-a\|}^2}
前面的系數$\frac 1 2$是為了求導後簡潔的形式而添加的,$n$是使用樣本的數量,這裡$y$和$x$都是已知的樣本資料。
理論上任何可以反映網絡工作效果的名額都可以作為代價函數。但之是以使用mse,而不是諸如“正确分類圖像個數”的名額,是因為隻有一個光滑可導的代價函數才可以使用梯度下降(gradient descent)調整參數。
代價函數的計算需要一個或多個訓練樣本。當訓練樣本非常多時,如果每輪訓練都要重新計算網絡整個訓練集上所有樣本的誤差函數,開銷非常大,速度難以接受。若隻使用總體的一小部分,計算就能快很多。不過這樣做依賴一個假設:随機樣本的代價,近似等于總體的代價。
按照使用樣本的方式,梯度下降又分為:
批量梯度下降法(batch gd):最原始的形式,更新每一參數都使用所有樣本。可以得到全局最優解,易于并行實作,但當樣本數量很多時,訓練速度極慢。
随機梯度下降法(stochastic gd):解決bgd訓練慢的問題,每次随機使用一個樣本。訓練速度快,但準确度下降,且并不是全局最優,也不易于并行實作。
小批量梯度下降法(minibatch gd):在每次更新參數時使用b個樣本(例如每次10個樣本),在bgd與sgd中取得折中。
每次隻使用一個樣本時,又稱為線上學習或遞增學習。
當訓練集的所有樣本都被使用過一輪,稱為完成一輪疊代。
若希望通過調整神經網絡中的某個參數來減小整體代價,則可以考慮微分的方法。因為每層的激活函數,以及最終的代價函數都是光滑可導的。是以最終的代價函數$c$對于某個我們感興趣的參數$w,b$也是光滑可導的。輕微撥動某個參數的值,最終的誤內插補點也會發生連續的輕微的變化。不斷地沿着參數的梯度方向,輕微調整每個參數的值,使得總誤內插補點向下降的方向前進,最終達到極值點。就是梯度下降法的核心思想。
現在假設代價函數$c$為兩個變量$v_1,v_2$的可微函數,梯度下降實際上就是選擇合适的$Δv$,使得$Δc$為負。由微積分可知:
Δc ≈ \frac{∂c}{∂v_1} Δv_1 + \frac{∂c}{∂v_2} Δv_2
這裡$Δv$是向量:$Δv = left[ begin{array}{v} Δv_1 \ Δv_2 end{array}right]$,$Δc$是梯度向量$left[ begin{array}{c} frac{∂c}{∂v_1} \ frac{∂c}{∂v_2} end{array} right]$,于是上式可重寫為
Δc ≈ ∇c \cdot Δv
怎樣的$Δv$才能令代價函數的變化量為負呢?一種簡單辦法是令即$Δv$取一個與梯度$∇c$共線反向的小向量,此時$Δv = -η∇c$ ,則損失函數變化量$Δc ≈ -η{∇c}^2$,可以確定為負值。按照這種方法,通過不斷調整$v$:$v → v' = v -η∇c$,使得$c$最終達到極小值點。
這即梯度下降的涵義所在:所有參數都會沿着自己的梯度(導數)方向不斷進行輕微下降,使得總誤差到達極值點。
對于神經網絡,學習的參數實際上是權重$w$與偏置量$b$。原理是一樣的,不過這裡的$w,b$數目非常巨大
w →w' = w-η\frac{∂c}{∂w} \\
b → b' = b-η\frac{∂c}{∂b}
真正棘手的問題在于梯度$∇c_w,∇c_b$的計算方式。如果使用微分的方法,通過$frac {c(p+ε)-c} {ε}$來求參數的梯度,那麼網絡中的每一個參數都需要進行一次前饋和一次$c(p+ε)$的計算,在神經網絡汪洋大海般的參數面前,這樣的辦法是行不通的。
反向傳播(back propagation)算法可以解決這一問題。通過巧妙的簡化, 可以在一次前饋與一次反傳中,高效地計算整個網絡中所有參數梯度。
反向傳播算法接受一個打标樣本$(x,y)$作為輸入,給出網絡中所有參數$(w,b)$的梯度。
反向傳播算法需要引入一個新的概念:誤差$δ$。誤差的定義源于這樣一種樸素的思想:如果輕微修改某個神經元的帶權輸入$z$,而最終代價$c$已不再變化,則可認為$z$已經到達極值點,調整的很好了。于是損失函數$c$對某神經元帶權輸入$z$的偏導$frac {∂c}{∂z}$可以作為該神經元上誤差$δ$的度量。故定義第$l$層的第$j^{th}$個神經元上的誤差$δ^l_j$為:
δ^l_j ≡ \frac{∂c}{∂z^l_j}
與激活值$a$,帶權輸入$z$一樣,誤差也可以寫作向量。第$l$層的誤差向量記作$δ^l$。雖然看上去差不多,但之是以使用帶權輸入$z$而不是激活值輸出$a$來定義本層的誤差,有着形式上巧妙的設計。
引入反向傳播誤差的概念,是為了通過誤差向量來計算梯度$∇c_w,∇c_b$。
反向傳播算法一言蔽之:計算出輸出層誤差,通過遞推方程逐層回算出每一層的誤差,再由每一層的誤差算出本層的權值梯度與偏置梯度。
這需要解決四個問題:
遞推首項:如何計算輸出層的誤差:$δ^l$
遞推方程:如何根據後一層的誤差$δ^{l+1}$計算前一層誤差$δ^l$
權值梯度:如何根據本層誤差$δ^l$計算本層權值梯度$∇w^l$
偏置梯度:如何根據本層誤差$δ^l$計算本層偏置梯度$∇b^l$
這四個問題,可以通過四個反向傳播方程得到解決。
方程
編号
$δ^l = ∇c_a ⊙ σ'(z^l)$
輸出層誤差計算公式
bp1
$δ^l = (w^{l+1})^t δ^{l+1} ⊙ σ'(z^l)$
誤差傳遞公式
bp2
$∇c_{w^l} = δ^l × {(a^{l-1})}^t $
權值梯度計算公式
bp3
$∇c_b = δ^l$
偏置梯度計算公式
bp4
當誤差函數取mse:$c = \frac 1 2 \|\vec{y} -\vec{a}\|^2= \frac 1 2 [(y_1 - a_1)^2 + \cdots + (y_{d_l} - a_{d_l})^2]$,激活函數取sigmoid時:
計算方程
$δ^l = (a^l - y) ⊙(1-a^l)⊙ a^l$
輸出層誤差需要$a^l$和$y$
$δ^l = (w^{l+1})^t δ^{l+1} ⊙(1-a^l)⊙ a^l $
本層誤差需要:後層權值$w^{l+1}$,後層誤差$δ^{l+1}$,本層輸出$a^l$
權值梯度需要:本層誤差$δ^l$,前層輸出$a^{l-1}$
偏置梯度需要:本層誤差$δ^l$
輸出層誤差方程給出了根據網絡輸出$a^l$與标記結果$y$計算輸出層誤差$δ$的方法:
δ^l = (a^l - y) ⊙(1-a^l)⊙ a^l
因為$a^l = σ(z^l)$,本方程可以直接從反向傳播誤差的定義,通過$a^l$作為中間變量鍊式求導推導得出:
\frac{∂c}{∂z^l} = \frac{∂c}{∂a^l} \frac{∂a^l}{∂z^l} = ∇c_a σ'(z^l)
而因為誤差函數$c = frac 1 2 |vec{y} -vec{a}|^2= frac 1 2 [(y_1 - a_1)^2 + ⋯ + (y_{d_l} - a_{d_l})^2]$,方程兩側對某個$a_j$取偏導則有:
\frac {∂c}{∂a^l_j} = (a^l_j-y_j)
因為誤差函數中,其他神經元的輸出不會影響到誤差函數對神經元$j$輸出的偏導,系數也正好平掉了。寫作向量形式即為:$ (a^l - y) $。另一方面,易證$σ'(z^l) = (1-a^l)⊙ a^l$。
qed
誤差傳遞方程給出了根據後一層誤差計算前一層誤差的方法:
δ^l = (w^{l+1})^t δ^{l+1} ⊙ σ'(z^l)
本方程可以直接從反向傳播誤差的定義,以後一層所有神經元的帶權輸入$z^{l+1}$作為中間變量進行鍊式求導推導出:
δ^l_j = \frac {∂c}{∂z^l_j}
= \sum_{k=1}^{d_{l+1}} \frac{∂c}{∂z^{l+1}_k} \frac{∂z^{l+1}_k}{∂z^{l}_j}
= \sum_{k=1}^{d_{l+1}} (δ^{l+1}_k \frac{∂z^{l+1}_k}{∂z^{l}_j})
通過鍊式求導,引入後一層帶權輸入作為中間變量,進而在方程右側引入後一層誤差的表達形式。現在要解決的就是$frac{∂z^{l+1}_k}{∂z^{l}_j}$ 是什麼的問題。由帶權輸入的定義$z = wx + b$可知:
z^{l+1}_k = w^{l+1}_{k,*} ·a^l + b^{l+1}_k = w^{l+1}_{k,*} · σ(z^l) + b^{l+1}_k
= \sum_{j=1}^{d_{l}}(w_{kj}^{l+1} σ(z^l_j)) + b^{l+1}_k
兩邊同時對$z^{l}_j$求導可以得到:
\frac{∂z^{l+1}_k}{∂z^{l}_j} = w^{l+1}_{kj} σ'(z^l)
回代則有:
δ^l_j & = \sum_{k=1}^{d_{l+1}} (δ^{l+1}_k \frac{∂z^{l+1}_k}{∂z^{l}_j}) \\
& = σ'(z^l) \sum_{k=1}^{d_{l+1}} (δ^{l+1}_k w^{l+1}_{kj}) \\
& = σ'(z^l) ⊙ [(δ^{l+1}) · w^{l+1}_{*.j}] \\
& = σ'(z^l) ⊙ [(w^{l+1})^t_{j,*} · (δ^{l+1}) ]\\
這裡,對後一層所有神經元的誤差權值之積求和,可以改寫為兩個向量的點積:
後一層$k$個神經元的誤差向量
後一層權值矩陣的第$j$列,即所有從本層$j$神經元出發前往下一層所有$k$個神經元的權值。
又因為向量點積可以改寫為矩陣乘法:以行向量乘以列向量的方式進行,是以将權值矩陣轉置,原來拿的是列,現在則拿出了行向量。這時候再改寫回向量形式為:
δ^l = σ'(z^l) ⊙ (w^{l+1})^tδ^{l+1}
每一層的權值梯度$∇c_{w^l}$可以根據本層的誤差向量(列向量),與上層的輸出向量(行向量)的外積得出。
∇c_{w^l} = δ^l × {(a^{l-1})}^t
由誤差的定義,以$w^l_{jk}$作為中間變量求偏導可得:
δ^l_j & = \frac{∂c}{∂z^l_j}
= \frac{∂c}{∂w^l_{jk}} \frac{∂ w_{jk}}{∂ z^l_j}
= ∇c_{w^l_{jk}} \frac{∂w_{jk}}{∂ z^l_j}
由定義可得,第$l$層第$j$個神經元的帶權輸入$z^l_j$:
z^l_j = \sum_k w^l_{jk} a^{l-1}_k + b^l_j
兩側對$w_{jk}^l$求導得到:
\frac{\partial z_j}{\partial w^l_{jk}} = a^{l-1}_k
代回則有:
∇c_{w^l_{jk}} = δ^l_j \frac{∂ z^l_j}{∂w_{jk}} = δ^l_j a^{l-1}_k
觀察可知,向量形式是一個外積:
本層誤差行向量:$δ^l$,次元為($d_l \times 1$)
上層激活列向量:$(a^{l-1})^t$,次元為($1 times d_{l-1}$)
∇c_b = δ^l
由定義可知:
δ^l_j = \frac{∂c}{∂z^l_j}
= \frac{∂c}{∂b^l_j} \frac{∂b_j}{∂z^l_j}
= ∇c_{b^l_{j}} \frac{∂b_j}{∂z^l_j}
因為$z^l_j = w^l_{*,j} \cdot a^{l-1} + b^l_j$,兩側對$z_j^l$求導得到$1=frac{∂b_j}{∂z^l_j}$。于是回代得到:$∇c_{b^l_{j}} =δ^l_j $ ,
至此,四個方程均已證畢。隻要将其轉換為代碼即可工作。
作為概念驗證,這裡給出了mnist手寫數字分類神經網絡的python實作。
一輪疊代後,網絡在測試集上的分類準确率就達到90%,最終收斂至96%左右。
對于五十行代碼,這個效果是值得驚歎的。然而96%的準确率在實際生産中恐怕仍然是無法接受的。想要達到更好的效果,就需要對神經網絡進行優化。
神經網絡的基礎知識也就這麼多,但改善其表現卻是一個無盡的挑戰。每一種優化的手段,都可以當做一個進階的topic深入研究。優化手段也是八仙過海,有數學,有科學,有工程學,也有哲學,還有玄學……
改進神經網絡的學習效果有幾種主要的方法:
選取更好的代價函數:例如交叉熵(cross-entropy)
規範化(regularization):l2規範化、棄權、l1規範化
采用其他的激活神經元:線性修正神經元(relu),雙曲正切神經元(tansig)
修改神經網絡的輸出層:柔性最大值(softmax)
修改神經網絡輸入的組織方式:遞歸神經網絡(recurrent nn),卷積神經網絡(convolutional nn)。
添加層數:深度神經網絡(deep nn)
通過嘗試,選擇合适的超參數(hyper-parameters),按照疊代輪數或評估效果動态調整超參數。
采用其他的梯度下降方法:基于動量的梯度下降
使用更好的初始化權重
人為擴充已有訓練資料集
這裡介紹兩種方法,交叉熵代價函數與l2規範化。因為它們:
實作簡單,修改一行代碼即可實作,還減小了計算開銷。
效果立竿見影,将分類錯誤率從4%降低到2%以下。
mse是一個不錯的代價函數,然而它存在一個很尴尬的問題:學習速度。
mse輸出層誤差的計算公式為:
δ^l = (a^l - y)σ'(z^l)
sigmoid又稱為邏輯斯蒂曲線,其導數$σ'$是一個鐘形曲線。是以當帶權輸入$z$從大到小或從小到大時,梯度的變化會經曆一個“小,大,小”的過程。學習的速度也會被導數項拖累,存在一個“慢,快,慢”的過程。
mse
cross entropy
若采用交叉熵(cross entropy)誤差函數:
c = - \frac 1 n \sum_x [ y ln(a) + (1-y)ln(1-a)]
對于單個樣本,即
c = - [ y ln(a) + (1-y)ln(1-a)]
雖然看起來很複雜,但輸出層的誤差公式變得異常簡單,變為:$δ^l = a^l - y$
比起mse少掉了導數因子,是以誤差直接和(預測值-實際值)成正比,不會遇到學習速度被激活函數的導數拖慢的問題,而且計算起來更簡單了!
$c$對網絡輸出值$a$求導,則有:
∇c_a = \frac {∂c} {∂a^l} = - [ \frac y a - \frac {(1-y)} {1-a}] = \frac {a - y} {a (1-a)}
反向傳播的四個基本方程裡,與誤差函數$c$相關的隻有bp1:即輸出層誤差的計算方式。
δ^l = ∇c_a ⊙ σ'(z^l)
現在$c$換了計算方式,将新的誤差函數$c$對輸出值$a^l$的梯度$frac {∂c} {∂a^l}$帶回bp1,即有:
δ^l = \frac {a - y} {a (1-a)}× a(1-a) = a-y
擁有大量的自由參數的模型能夠描述特别神奇的現象。
費米說:"with four parameters i can fit an elephant, and with five i can make him wiggle his trunk"。神經網絡這種動辄百萬的參數的模型能拟合出什麼奇妙的東西是難以想象的。
一個模型能夠很好的拟合已有的資料,可能隻是因為模型中足夠的自由度,使得它可以描述幾乎所有給定大小的資料集,而不是真正洞察資料集背後的本質。發生這種情形時,模型對已有的資料表現的很好,但是對新的資料很難泛化。這種情況稱為過拟合(overfitting)。
例如用3階多項式拟合一個帶随機噪聲的正弦函數,看上去就還不錯;而10階多項式,雖然完美拟合了資料集中的所有點,但實際預測能力就很離譜了。它拟合的更多地是資料集中的噪聲,而非資料集背後的潛在規律。
3階多項式
10階多項式
一個模型真正的測驗标準,是它對沒有見過的場景的預測能力,稱為泛化能力(generalize)。
如何避免過拟合?按照奧卡姆剃刀原理:兩個效果相同的解釋,選擇簡單的那一個。
當然這個原理隻是我們抱有的一種信念,并不是真正的定理鐵律:這些資料點真的由拟合出的十階多項式産生,也不能否認這種可能…
總之,如果出現非常大的權重參數,通常就意味着過拟合。例如拟合所得十階多項式系數就非常畸形:
通過添權重重衰減項,可以有效遏制過拟合。例如$l2$規範化為損失函數添加了一個$frac λ 2 w^2$的懲罰項:
c = -\frac{1}{n} \sum_{xj} \left[ y_j \ln a^l_j+(1-y_j) \ln
(1-a^l_j)\right] + \frac{\lambda}{2n} \sum_w w^2
是以,權重越大,損失值越大,這就避免神經網絡了向拟合出畸形參數的方向發展。
這裡使用的是交叉熵損失函數。但無論哪種損失函數,都可以寫成:
c = c_0 + \frac {λ}{2n} \sum_w {w^2}
其中原始的代價函數為$c_0$。那麼,原來損失函數對權值的偏導,就可以寫成:
\frac{∂c}{∂w} = \frac{ ∂c_0}{∂w}+\frac{λ}{n} w
是以,引入$l2$規範化懲罰項在計算上的唯一變化,就是在處理權值梯度時首先要乘一個衰減系數:
w → w' = w\left(1 - \frac{ηλ}{n} \right)- η\frac{∂c_0}{∂ w}
注意這裡的$n$是所有的訓練樣本數,而不是一個小批次使用的訓練樣本數。
可見隻是簡單的變更,就使準确率有了顯著提高,最終收斂至98%。
修改size為<code>[784,128,64,10]</code>添加一層隐藏層,可以進一步提升測試集準确率至98.33%,驗證集至98.24%。