---
tags: Knock Knock! Deep Learning
---
Day 3 / Deep Learning 簡介 / 細解 Deep Learning(二) —— Training
===
前面提到了訓練一個 Neural Network 包含 prediction 和 training 兩大步。這篇會深入介紹一下 training 這一步。
本篇數學偏難,但實際應用並不需要完全理解,所以不需擔心看不懂喔。這邊撐過去後面好玩多了!
## Training
在取得 prediction 之後,我們會計算這個預測值跟實際答案的誤差,並反向回饋給 network 裡的 parameters。後面這步也稱 **backpropagation**。訓練步驟大致如下:
1. 用 loss / error function 計算誤差程度
2. 把 loss 從 network 最後一層往前傳,每個 parameter 會計算自己對這個 loss 有多少「貢獻」,並且修正自己
### Loss Function
Loss function 決定這個 network 是怎麼衡量誤差的,因此會根據資料屬性不同選擇不同的 loss function。
我們通常用 $\hat{y}$ 代表 prediction,$y$ 代表 label。以下介紹兩種常見 loss function 和應用場合:
|| Mean Squared Error (MSE) | Cross-Entropy Loss |
|------| -------- | -------- |
|Function| $L = (y - \hat{y})^2$ | $L = -\sum^C_{i} y_i \log \hat{y}_i$ |
|應用場合|Regression|Multiclass classification|
注意式子都是針對單一 data sample。
MSE 適用預測一個數值的 regression ,因此 $y$ 和 $\hat{y}$ 都是 scalar value(純量)。
Cross-Entropy 則適用預測種類的 multiclass classification,前篇有提到在做 multiclass classification 最後 output 會是 $C$ 個機率值($C$ 為種類數),所以這裡 $y$ 和 $\hat{y}$ 是大小為 $C$ 的 vector,$y_i$ 和 $\hat{y}_i$ 則是 vector 的第 $i$ 個值。而 cross-entropy loss 就是每個種類計算 $y_i \log(\hat{y}_i)$ 並加總。
這邊注意的是 $y$ 其實是 **one-hot vector**,也就是整個 vector 只有一個位置是 $1$ 其餘為 $0$,而 $1$ 就在正確種類的位置。所以說雖然在做加總,實際上只會有一個 $y_i = 1$,所以式子可以簡化為 $L = -\log(\hat{y}_c)$,$c$ 為正確種類的位置。是不是簡單很多?
> 在 multiclass classification 有時候 $y$ 也可以是 scalar value,代表正確種類的位置。不管是數學式子還是寫 code 時用到的 loss function,都應該依照前後文判斷 $y$ 是 scalar 還是 vector。
> 對 Cross-Entropy 這個式子感到恐懼的我理解你,這是在 information theory 裡衡量兩個機率分佈有多不一樣的一個方法,deep learning 新手就使用就好,阿密陀佛。
### Backpropagation
要來到重頭戲了。切記先複習一下 matrix differentiation(矩陣微分),以及 partial differentiation(偏微分)的概念。
這邊有很多數學,所以先來張圖比較好講解:

*—— Two hidden layer network for binary classification。[1]*
這邊我們用 $[\ell]$ 來表示第 $\ell$ 層,$(i)$ 來表示第 $i$ 筆資料。$\mathbf{W}$、$\mathbf{b}$、$\mathbf{a}$、$\mathbf{z}$ 都參照前篇介紹的表示法。
好,我們在右端計算了 loss $L$,現在要從右到左告知 network 裡的所有 parameters 他們做得有多差,請他們修正自己以減少下次的 loss。
那要怎麼知道需要往哪裡修正多少?這就跟 **Gradient Descent(梯度下降法)** 有關了。
#### Gradient Descent

*—— Sample loss function visualization。[2]*
先來視覺化一下 loss function。圖中 $\theta$ 是一個 vector,$\theta_i$ 為第 $i$ 個 parameter,這個簡單的 model (跟前面圖的 model 不同)總共有兩個 parameter,而 $L(\mathbf{\theta})$ 是 loss 值。
目前我們 model 的 parameter 在紅點點那邊,造成的 loss 很高,可以說是表現很差。而綠點點是 model 能得到最好的表現,因為誤差最小。我們希望可以讓 parameter 的值往綠點點的方向移動。
這聽起來很簡單。但在現實世界裡,parameters 可不只兩個,維度一高圖形可就沒那麼簡單,要知道綠點的準確位置一點都不實際。但有個辦法:就往低處走吧?水往低處流,雖然不一定會走在捷徑上,總有一天也會到谷底。
也就是找出橘色的向量。仔細一看,他好像是⋯⋯紅點在曲面上的切線?
還記得怎麼在二維平面找出一條切線的斜率嗎?沒錯,取 derivative $\frac{d f(x)}{d x}$。那麼在高維空間找切線呢?那肯定就是取 gradient 了。
Gradient 可以說是多維度的 derivative,基本上就是幫 vector 裡的所有值取 partial derivative。以這張圖為例,對 parameters 取 gradient 為:
$$
\nabla L(\theta) = \begin{bmatrix}
\frac{\partial L(\theta)}{\partial \theta_1} \\
\frac{\partial L(\theta)}{\partial \theta_2}
\end{bmatrix}
$$
> Partial derivative (偏微分)很簡單啦,就是針對一個維度取微分。方法跟微分一樣,但把其他維度的值當成常數即可。
所謂 descent 就是下降,所以 **gradient descent 就是找出並沿著切線,一路盲目往低處走,以尋找最佳解**。
#### Finding Gradients for Model Parameters
介紹完 gradient descent,回到原本的 model,我們是要讓 parameters 知道自己要往哪個方向修正對吧。沒錯,就是計算 $L$ 對 $\mathbf{W}^{[1]}, \mathbf{W}^{[2]}, \mathbf{W}^{[3]}, \mathbf{b}^{[1]}, \mathbf{b}^{[2]}, \mathbf{b}^{[3]}$ 的 gradient。
因為是做分類問題,我們用 cross-entropy 當作 loss function:
$$
L = -[(1 - y) \log (1 - \hat{y}) + y \log \hat{y}]
$$
> 這裡因為是 binary classification,$y$ 是 scalar value 1 或 0。
所以有以下 6 組 gradient 要算:
$$
\frac{\partial L}{\partial \mathbf{W}^{[\ell]}} \text{ for } \ell = 1, 2, 3 \\
\frac{\partial L}{\partial \mathbf{b}^{[\ell]}} \text{ for } \ell = 1, 2, 3
$$
相信到這邊大家一定腦袋空白。好前面我都懂,但課本讀完讀題目怎麼像之前什麼都沒讀過?完全沒有頭緒。
總之,我們先從最後一層看起。我們會看到如果一層一層往前算,搭配微積分裡的 **Chain Rule**,計算方法會簡化許多。
> 先複習一下 chain rule。他是用來取 composite function $f(g(x))$ 的微分的:
>
> $$
> \frac{df(g(x))}{dx} = \frac{df(z)}{dx} = \frac{df(z)}{dz} \frac{dz}{dx} = \frac{df(z)}{dz} \frac{dg(x)}{dx}
> $$
>
> where $z = g(x)$。
##### Gradients for the Last Layer

我們先看一下最後一層,$\hat{y}$ 是怎麼計算出來的:
$$
\hat{y} = \mathbf{a}^{[3]} = g(\mathbf{z}^{[3]}) = g(\mathbf{W}^{[3]}\mathbf{a}^{[2]} + \mathbf{b}^{[3]})
$$
這邊因為是 binary classification,$g$ 為 sigmoid function。
這一層有兩組 parameters: $\mathbf{W}^{[3]}$ 和 $\mathbf{b}^{[3]}$。我們示範 $\mathbf{W}^{[3]}$ 就好。如果要硬幹他的 gradient 的話,結合前幾個式子,可以得到:
$$
\frac{\partial L}{\partial \mathbf{W}^{[3]}}
= -\frac{\partial}{\partial \mathbf{W}^{[3]}}[(1 - y) \log (1 - \hat{y}) + y \log \hat{y}] \\
= -\frac{\partial}{\partial \mathbf{W}^{[3]}}[(1 - y) \log (1 - g(\mathbf{W}^{[3]}\mathbf{a}^{[2]} + \mathbf{b}^{[3]})) + y \log g(\mathbf{W}^{[3]}\mathbf{a}^{[2]} + \mathbf{b}^{[3]})]
$$
喂等等先不要離開啊!我們沒有要嘗試化簡這個式子的意思。雖然現在上下有 $\mathbf{W}^{[3]}$ 可以開始手算,但實在太複雜,而且對 engineering 來說也很不實際。總不會寫一個 network 就要把這些式子爆開 code 進去吧?
這時候我們應用 chain rule,優雅的簡化成三步驟:
$$
\frac{\partial L}{\partial \mathbf{z}^{[3]}}
= -\frac{\partial}{\partial \mathbf{z}^{[3]}} [(1 - y) \log (1 - \hat{y}) + y \log \hat{y}]
= \mathbf{a}^{[3]} - y \\
\frac{\partial \mathbf{z}^{[3]}}{\partial \mathbf{W}^{[3]}}
= \mathbf{a}^{[2]T} \\
\Rightarrow \frac{\partial L}{\partial \mathbf{W}^{[3]}}
= \frac{\partial L}{\partial \mathbf{z}^{[3]}}\frac{\partial \mathbf{z}^{[3]}}{\partial \mathbf{W}^{[3]}} = (\mathbf{a}^{[3]} - y)\mathbf{a}^{[2]T}
$$
不只數學計算簡單多了,在寫程式的時候,也可以把這些步驟分開來,並針對不同 loss 或 activation function 寫 gradient,分別計算後乘在一起就行。
> 詳細數學推導請見 [1] p.11-12,或自己練習。
> $\frac{\partial \mathbf{z}^{[3]}}{\partial \mathbf{W}^{[3]}} = \mathbf{a}^{[2]T}$ 是怎麼來的?
>
> 首先 $\mathbf{z}^{[3]} = \mathbf{W}^{[3]}\mathbf{a}^{[2]} + \mathbf{b}^{[3]}$,因為取偏微分所以 $\mathbf{b}^{[3]}$ 當常數微掉變 0,$\mathbf{W}^{[3]}\mathbf{a}^{[2]}$ 也可以想像成 $x \cdot c$ 對 $x$ 微分剩 $c$,所以剩 $\mathbf{a}^{[2]}$。
>
> 那為什麼要取 transpose 呢?因為對 matrix $A$ 微分的結果必然是 $A$ 的形狀。$\mathbf{W}^{[3]}$ 的形狀是 $1 \times 2$,$\mathbf{a}^{[2]}$ 是 $2 \times 1$,所以要取 transpose 才符合 $\mathbf{W}^{[3]}$ 的形狀!
> 蛤你又問為什麼知道 $\mathbf{W}^{[3]}$ 和 $\mathbf{a}^{[2]}$ 的形狀?
>
> 第二層有兩個 node 所以 $\mathbf{a}^{[2]}$ 是 $2 \times 1$,而第三層有幾個 node 就有幾個 bias,所以 $\mathbf{b}^{[3]}$ 是 $1 \times 1$。最後 $\mathbf{W}^{[3]}\mathbf{a}^{[2]} + \mathbf{b}^{[3]}$ 的結果取決於第三層有幾個 node 所以是 $1 \times 1$,所以 $\mathbf{W}^{[3]}\mathbf{a}^{[2]}$ 會是 $1 \times 1$,那 $\mathbf{W}$ 自然是 $1 \times 2$。
>
> 更直觀的看法就是 $W^{[i]}$ 會是 $n_{i} \times n_{i-1}$,$n_i$ 代表第 $i$ 層有幾個 node。
> 好了小秘訣都說完了,不可以再抱怨太複雜因為很多資料連小秘訣都沒有。
##### Gradients for Previous Layers

運用 chain rule,先把 forward propagation 的式子列出來,再由後往前找出對中間值的 gradient,就能依樣畫葫蘆找出其他 $\frac{\partial L}{\partial \mathbf{W}^{[\ell]}}$ 和 $\frac{\partial L}{\partial \mathbf{b}^{[\ell]}}$ 了。
也因為要先從後面的 layer 開始計算,並把結果往前送,這個過程才被稱為 **backpropagation**。
那就試著自己找出前面幾個 parameter 的 gradient 吧。還是不熟悉的可以參考 [1] p.11-12!
上面取 gradient 的部分應該是全系列最數學的地方,我也盡量提供一些訣竅幫助理解。如果反覆看幾次還是如在霧裡,那我跟你說沒關係,應用方面需要理解的數學不會這麼深!
#### Parameter Update
好的,那還記得我們取 gradient 是尬麻嗎?是要找出往低處走的方向。找出來以後,我們要實際讓這些 parameters 邁出步伐,修正自己。
修正的方式很簡單:
$$
\mathbf{\theta}^{[\ell]} = \mathbf{\theta}^{[\ell]} - \alpha \frac{\partial L}{\partial \mathbf{\theta}^{[\ell]}}
$$
這邊我們統稱 parameters 為 $\theta$,就是 $\mathbf{W}$ 和 $\mathbf{b}$ 啦。
我們知道剛剛讓人困擾終於搞懂的 $\frac{\partial L}{\partial \theta^{[\ell]}}$ 是我們要前進的方向,那 $\alpha$ 就是步伐大小了。我們稱之為 **learning rate**,也就是學習速率。減號是因為是要減小 $L$ 的值,所以是走 $L$ 的負方向。用此方式 update,parameters 就會往低處前進了。
那老師,為什麼不就走很大步就好呢?這樣不就學很快?
我們來看看這張圖:

*—— Learning rate 影響學習成果。[4]*
Learning rate 太低的話,training 會很慢;但太高的話,又容易走過頭。因此選擇適當的 learning rate 其實是一門藝術!後面也會講到怎麼依據學習情況自動調節 learning rate。
## Checkpoint
- MSE 和 cross-entropy loss 分別適用於哪些情況?
- Gradient descent 的目的是什麼?為什麼會被用在 neural network 的訓練中?
- 在 neural network 裡,我們具體要找出什麼的 gradient?
- 利用 chain rule 計算 gradient 有什麼好處?
- 為什麼 parameter 要由後往前 update(為什麼是 backpropagation)?
- Learing rate 的大小會怎麼影響訓練?
## 參考資料
1. [👍 CS229 Lecture Notes - Deep Learning](http://cs229.stanford.edu/summer2020/cs229-notes-deep_learning.pdf)
2. [梯度下降法及反向传播小结](https://zhuanlan.zhihu.com/p/37065664)
3. [Khan Academy - Chain rule](https://www.khanacademy.org/math/ap-calculus-ab/ab-differentiation-2-new/ab-3-1a/a/chain-rule-review)
4. [Setting the learning rate of your neural network.](https://www.jeremyjordan.me/nn-learning-rate/)
## 延伸閱讀
1. [CS224n Readings - Review of differential calculus theory](http://web.stanford.edu/class/cs224n/readings/review-differential-calculus.pdf)
2. [CS231n Handouts - Derivatives, Backpropagation, and Vectorization](http://cs231n.stanford.edu/handouts/derivatives.pdf)
3. [CS224n Readings - Computing Neural Network Gradients](http://web.stanford.edu/class/cs224n/readings/gradient-notes.pdf)