Backpropagation(BP) 倒傳遞法 #2 貓貓分類器-2層類神經網路

本篇會介紹在機器學習(machine learning)與深度學習(deep learning)領域裡很流行的倒傳遞法(Back Propagation/ Backpropagation, BP)的演算法流程與實作方法:正向傳遞(Forward pass)、反向傳遞(Backward pass)、邏輯回歸(Logistic regression)。除此之外,本篇會用簡易的2層類神經網路建立一個『貓貓分類器』。

先來GitHub下載這個範例吧!邊執行邊看文章比較好理解 😀
如果有需要更詳細的原理或是有什麼寫錯的,歡迎在文末留言哦!

如果你覺得還是不太懂推導過程可以先來讀這篇:Backpropagation(BP) 倒傳遞法 #1 工作原理與說明;你想要知道該如何優化多層類神經網路可以讀這篇:Backpropagation(BP) 倒傳遞法 #3 貓貓分類器-N層類神經網路

演算法流程

下圖(1)是演算法流程,本文章也會依照這個流程介紹演算法的實作方法。其中『正向傳遞』到『檢查是否結束迭代』之間的4個步驟就是迭代迴圈的所在。

$\\$
$\\$
$\rightarrow$
$\uparrow$
$\uparrow$
$\uparrow$
$\uparrow$
$\uparrow$
$\uparrow$
$\uparrow$
$\leftarrow$
(否)
參數初始化
$\downarrow$
正向傳遞
$\downarrow$
計算成本
$\downarrow$
反向傳遞
$\downarrow$
更新參數
$\downarrow$
檢查是否結束迭代
$\downarrow$(是)
結束

圖(1):倒傳遞法演算法流程

 

前置作業

載入資料集、函式庫

 

資料集

Coursera課程中所使用的資料集為$64\times 64$的彩色圖片,一共有$209$張圖片作為訓練資料集、$50$張圖片為測試資料集。我們可以透過下列程式觀察。

Output

Logistic regression training sample - cat

這段程式可以發現 train_x_orig的維度排列依序是 每一張圖片、長度、寬度、RGB。接下來,我們要對這些圖片資料做前處理,先將每一張圖片壓縮成$12288-by-1$的向量。為什麼是$12288$?因為長x寬xRGB$=64\times64\times3=12288$,如圖(2)所示。

Logistic regression - Image to vector conversion圖(2):圖片轉向量過程示意圖

如下方程式,首先將train_x_orig改變形狀成$12288\times209$,為了加強模型效用與收斂速度再將所有的剛才轉換好的$209$張圖片內的數值做Normalization運算(資料集中每筆數據 $\div$ 資料集中的最大值),這讓所有資料都會介於$0$到$1$之間。相同的做法也需要再對test_x_orig做一次。如此一來,我們就算是把資料集完成前處理了。

Output

 

架構

在開始實作模型所需程式之前,先說明本文的重點2層的邏輯回歸模型架構。下圖(3)是以單張圖片輸入2層類神經網路、2層網路皆僅以1顆神經元的示意圖,而輸入圖片將會是經過上述程序向量化後的圖片。
然而,此架構圖是引用自Coursera課程中的第3週所使用的架構圖,但是對於本文的目標來說還需要在最後加上一個成本函數,這部分會在本節『各層架構』中說明。

記號說明

  • 上標$[1]$代表第1層類神經網路
  • $n^{[1]}$表示的是模型中第1層類神經網路的神經元輸出的數量
  • $a_5^{[1]}$代表第1層類神經網路神經元的第$5+1$筆輸出(因為神經元輸出編號是從$0$開始,所以要$+1$,又因為神經元只有$1$顆所以沒有標記號)
  • $a^{[2]}$表示類神經網路中整個第2層的所有輸出
  • 在圖中還可以發現有個大圓上方標著Linear Relu表示該層網路所採用的激勵函數(activation function)為ReLU,然而本架構所使用的激勵函數分別為第1層為ReLU、第2層為Sigmoid。
  • 各層神經元內部計算則是這樣,第1層的神經元計算以公式(1)、(2)所示
$$Z^{[1]}=w^{[1]}x+b^{[1]}$$ $(1)$
$$a^{[1]}=ReLU(Z^{[1]})$$ $(2)$

 

各層架構

第1層類神經網路中每顆神經元會有$n^{[1]}$個神經元輸出,分別是$a_{0}^{[1]}\cdots a_{(n^{[1]}-1)}$。
第2層類神經網路中每顆神經元會有$1$個神經元輸出。
最後,這張圖還沒加上成本函數,應該要把$0.73$改成$a_0^{[2]}$然後畫一個箭頭指向成本函數$L(y,a^{[2]})$代表輸入成本函數$L$,這邊的$a^{[2]}$少了下標的原因是指整個第2層的輸出。就像這樣:$a_0^{[2]}\rightarrow L(y, a^{[2]})$

Logistic regression - 2-layer artchitecture圖(3):2層邏輯回歸模型架構

成本函數

圖(3)第2層神經元計算出來的$0.73$是輸入成本函數(Cost function)計算之前的數值,僅能算是$a_0^{[2]}$。那成本函數是什麼?成本函數就是用來判斷這些參數對於這個模型好壞的依據。本文所使用的成本函數如公式(3)所示,本公式裡有個變數$m$指的是樣本數,例如:訓練階段有$209$張圖片則$m=209$、測試階段有$50$張圖片則$m=50$。如果看不懂,也可以先忽略$m$的存在。(此處成本函數的$\log$是以$e$為底的Natural log($\ln$),使用Natural log的原因很簡單,因為$\ln$的微分規則比較簡單,而這也算是使用Backpropagation的慣例,很多時候發論文的作者也都不太提了)

$$L(y,a^{[2]})=- \frac{1}{m} \sum\limits_{i = 0}^{m} \large{(} \small y^{(i)}\log\left(a^{[2] (i)}\right) + (1-y^{(i)})\log\left(1- a^{[2] (i)}\right) \large{)} \small$$ $(3)$

 

參數初始化

初始化參數有兩個規則:$w$要用常態分佈亂數初始化、$b$初始值都是$0$。簡單吧!
(這邊使用的np是Numpy的別名)
常態分佈亂數:np.random.randn(維度)
零矩陣:np.zeros([維度])

下列程式傳入三個參數(n_x、n_h、n_y),用途與原理解釋如下:
n_x:要輸入每一張圖片的維度($64\times64\times3$)
n_h:第1層的神經元數量(我們要設計成這部分能夠隨時自訂)
n_y:第二層神經元的數量(第2層固定為$1$顆神經元)

原理是什麼?為何這樣設計?我們可以先看一下圖(4)然後再來看表(1)、表(2)。其設計原理就是要符合矩陣運算時需要注意的形狀變化與計算規則,當然最重要的是模型需求(第1層的神經元數量要可以隨時更改)。可以先從表(1)看到形狀設定值。計算過程可以參考表(2),此表格包括第1、2層類神經網路的操作與每一個步驟對應到的變數形狀,然而$b^{[1]}$、$b^{[1]}$沒在計算過程中寫上形狀的原因是參數$b$的形狀基本上不會影響輸出結果的形狀。

表(1):初始化變數形狀

參數/變數名稱 形狀
train_x($x$) $12288\times209$
W1($w^{[1]}$) n_h$\times12288$
b1($b^{[1]}$)  n_h$\times1$
W1($w^{[2]}$) n_y$\times$n_h
b1($b^{[2]}$) n_y$\times1$

 

表(2):計算過程之形狀變化表

Layer-1 步驟1 $Z^{[1]}=w^{[1]}x+b^{[1]}$
步驟1形狀 $[$n_h$\times12288]\cdot[ 12288\times209 ]+b^{[1]}\Rightarrow[$n_h$\times209]$
步驟2 $a^{[1]}=ReLU(Z^{[1]})$
步驟2形狀 $[$n_h$\times209]$(ReLU輸出形狀不變)
Layer-2 步驟1 $Z^{[2]}=w^{[2]}a^{[1]}+b^{[2]}$
步驟1形狀 $[$n_y$\times$n_h$]\cdot[$n_h$\times209]+b^{[2]}\Rightarrow[$n_y$\times209]$
步驟2 $a^{[2]}=Sigmoid(Z^{[2]})$
步驟2形狀  $[$n_y$\times209]$(Sigmoid輸出形狀不變)

 

 

正向傳遞

正向傳遞(Forward pass)就是從圖片輸入模型開始到計算出成本的過程,但是我們把計算成本的函數獨立出來,所以此函數裡面沒有計算成本的部分。forwardpass這個函數除了會回傳第2層的計算結果($a^{[2]}$)之外,還會回傳一個變數cache,這個變數的用途是反向傳遞計算過程的參數。

 

計算成本

公式(3)這是本次Logistic Regression模型的成本函數,這公式裡面有個討人厭的$\sum$,和一個意味不明的變數$m$。(公式(3)和公式(1)是一樣的公式,為方便閱讀再複製到這)其實$m$是指輸入照片的數量,若是訓練階段$m$就是$209$,測試階段的話$m$則是$50$。公式(4)是為把$\sum$去除掉的作法。其中公式(3)、公式(4)都可以看見變數$m$,要將成本通除以$m$的原因是要取得平均成本。最後,$y$指的又是什麼?$y$是解答,train_y的形狀就是一個$1\times209$的向量、test_y的形狀則是$1\times50$的向量,數值的話就只有$1$和$0$兩種,$1$表示這張圖片是貓,$0$代表不是貓。

$$L(y,a^{[2]})=- \frac{1}{m} \sum\limits_{i = 0}^{m} \large{(} \small y^{(i)}\log\left(a^{[2] (i)}\right) + (1-y^{(i)})\log\left(1- a^{[2] (i)}\right) \large{)} \small$$ $(3)$
$$L(y,a^{[2]})=(ya^{[2]T}-(1-y)(\log{(1-a^{[2]})})^{T})/m$$ $(4)$

 

反向傳遞

反向傳遞(Backward pass),這是整個倒傳遞法最困難的部分!
但是,我們可以參考上一篇中連鎖率的概念最終計算出這幾個參數:$\frac{\partial L}{\partial w^{[1]}}$、$\frac{\partial L}{\partial b^{[1]}}$、$\frac{\partial L}{\partial w^{[2]}}$、$\frac{\partial L}{\partial b^{[2]}}$
概念就是$a^{[2]}$對模型成本偏微分$\rightarrow$對激勵函數(Sigmoid)偏微分$\rightarrow$對線性函數偏微分($w^{[2]}a^{[1]}+b^{[2]}$)$\rightarrow$對激勵函數(ReLU)偏微分$\rightarrow\cdots$

$$\frac{\partial L}{\partial a^{[2]}}=-(\frac{y}{a^{[2]}} – \frac{1-y}{1-a^{[2]}})$$ $(5)$
$$\frac{\partial L}{\partial Z^{[2]}}=\frac{\partial L}{\partial a^{[2]}}(\frac{1}{1+e^{(-Z^{[2]})}})(1-\frac{1}{1+e^{(-Z^{[2]})}})$$ $(6)$
$$\frac{\partial L}{\partial w^{[2]}}=(\frac{\partial L}{\partial Z^{[2]}}a^{[1]T})/m$$ $(7)$
$$\frac{\partial L}{\partial b^{[2]}}=(\frac{\partial L}{\partial Z^{[2]}}a^{[1]T})/m$$ $(8)$
$$\frac{\partial L}{\partial a^{[1]}}=w^{[2]T}\frac{\partial L}{\partial Z^{[2]}}$$ $(9)$
$$\frac{\partial L}{\partial Z^{[1]}}=$$
$\frac{\partial L}{\partial a^{[1]}}$對應至$Z^{[1]}$相同位置的數值$\leq0$的都改成$0$
$(10)$
$$\frac{\partial L}{\partial w^{[1]}}=\frac{\partial L}{\partial Z^{[1]}}x^{T}/m$$ $(11)$
$$\frac{\partial L}{\partial b^{[1]}}=\frac{\partial L}{\partial Z^{[1]}}/m$$ $(12)$

 

更新參數

參數更新只有一個原則,就是現在的參數減掉Backward pass計算出來的梯度值乘上學習速率(Learning rate)

$$w^{[1]}=w^{[1]}-\alpha(\frac{\partial L}{\partial w^{[1]}})$$ $(13)$
$$b^{[1]}=b^{[1]}-\alpha(\frac{\partial L}{\partial b^{[1]}})$$ $(14)$
$$w^{[2]}=w^{[2]}-\alpha(\frac{\partial L}{\partial w^{[2]}})$$ $(15)$
$$b^{[2]}=b^{[2]}-\alpha(\frac{\partial L}{\partial b^{[2]}})$$ $(16)$

 

 

主程式

主程式最主要就是要可以讓人方便操作,透過簡單的給予幾個重要參數就可以開始訓練參數。
nn_model的輸入值X就是被向量化的圖片,每一張圖片的維度是$12288\times1$,以訓練階段來說X一共有$209$張圖片,而Y就是這$209$張圖片相對應的分類(class)數值則分為貓或非貓($1$、$0$)。

 

判斷準確度

判斷準確度的函數是要利用正向傳遞(Forward pass)協助完成,做法是把訓練好的參數(parameters)和向量化的圖片(每張圖的維度是$12288\times1$)丟進forwardpass,回傳值則是probas($a^{[2]}$)和cache(cache在預測精準度時沒有用到)。
判斷規則是probas$>0.5$判斷為貓,反之為非貓~

 

怎麼使用

訓練模型

模型怎麼訓練啊?
直接傳入向量化的圖片train_x、解答train_y、第1層神經網路的神經元數量12、迭代次數num_iterations、學習速率learning_rate、是否要每隔500代印一次目前成本print_cost,然後用一個變數來收nn_model訓練結束所回傳的參數,本範例用的是parameters。

Output

logistic regression learning curve

 

準確度判斷

判斷準確度的工作就交給函數predict囉~這應該不需要多解釋了 🙂

Output

 

自己找一張圖測試

我們可以丟一張自己準備的圖片進模型使用剛才訓練完的參數做測試,下列程式第9行有個變數num_px是在最一開始查看『資料集』時存下來的變數,意思是訓練階段與測試階段的圖片長、寬。

Output

logistic regression test results

 

References
  1. Andrew Ng – Neural Networks & Deep Learning in Coursera
  2. (paper) Learning representations by back-propagation errors



Andy Wang

站在巨人的肩膀上仍須戰戰兢兢!

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *