天天看點

Coursera吳恩達《神經網絡與深度學習》課程筆記(3)-- 神經網絡基礎之Python與向量化

上節課我們主要介紹了邏輯回歸,以輸出機率的形式來處理二分類問題。我們介紹了邏輯回歸的Cost function表達式,并使用梯度下降算法來計算最小化Cost function時對應的參數w和b。通過計算圖的方式來講述了神經網絡的正向傳播和反向傳播兩個過程。本節課我們将來探讨Python和向量化的相關知識。

深度學習算法中,資料量很大,在程式中應該盡量減少使用loop循環語句,而可以使用向量運算來提高程式運作速度。

向量化(Vectorization)就是利用矩陣運算的思想,大大提高運算速度。例如下面所示在Python中使用向量化要比使用循環計算速度快得多。

輸出結果類似于:

從程式運作結果上來看,該例子使用for循環運作時間是使用向量運算運作時間的約300倍。是以,深度學習算法中,使用向量化矩陣運算的效率要高得多。

為了加快深度學習神經網絡運算速度,可以使用比CPU運算能力更強大的GPU。事實上,GPU和CPU都有并行指令(parallelization instructions),稱為Single Instruction Multiple Data(SIMD)。SIMD是單指令多資料流,能夠複制多個操作數,并把它們打包在大型寄存器的一組指令集。SIMD能夠大大提高程式運作速度,例如python的numpy庫中的内建函數(built-in function)就是使用了SIMD指令。相比而言,GPU的SIMD要比CPU更強大一些。

上一部分我們講了應該盡量避免使用for循環而使用向量化矩陣運算。在python的numpy庫中,我們通常使用np.dot()函數來進行矩陣運算。

我們将向量化的思想使用在邏輯回歸算法上,盡可能減少for循環,而隻使用矩陣運算。值得注意的是,算法最頂層的疊代訓練的for循環是不能替換的。而每次疊代過程對J,dw,b的計算是可以直接使用矩陣運算。

在《神經網絡與深度學習》課程筆記(2)中我們介紹過,整個訓練樣本構成的輸入矩陣X的次元是(n_x,m),權重矩陣w的次元是(n_x,1),b是一個常數值,而整個訓練樣本構成的輸出矩陣Y的次元為(1,m)。利用向量化的思想,所有m個樣本的線性輸出Z可以用矩陣表示:

Z=w^TX+b

在python的numpy庫中可以表示為:

其中,w.T表示w的轉置。

這樣,我們就能夠使用向量化矩陣運算代替for循環,對所有m個樣本同時運算,大大提高了運算速度。

再來看邏輯回歸中的梯度下降算法如何轉化為向量化的矩陣形式。對于所有m個樣本,dZ的次元是(1,m),可表示為:

dZ=A-Y

db可表示為:

db=\frac1m \sum_{i=1}^mdz^{(i)}

對應的程式為:

dw可表示為:

dw=\frac1m X\cdot dZ^T

這樣,我們把整個邏輯回歸中的for循環盡可能用矩陣運算代替,對于單次疊代,梯度下降算法流程如下所示:

其中,alpha是學習因子,決定w和b的更新速度。上述代碼隻是對單次訓練更新而言的,外層還需要一個for循環,表示疊代次數。

下面介紹使用python的另一種技巧:廣播(Broadcasting)。python中的廣播機制可由下面四條表示:

讓所有輸入數組都向其中shape最長的數組看齊,shape中不足的部分都通過在前面加1補齊

輸出數組的shape是輸入數組shape的各個軸上的最大值

如果輸入數組的某個軸和輸出數組的對應軸的長度相同或者其長度為1時,這個數組能夠用來計算,否則出錯

當輸入數組的某個軸的長度為1時,沿着此軸運算時都用此軸上的第一組值

簡而言之,就是python中可以對不同次元的矩陣進行四則混合運算,但至少保證有一個次元是相同的。下面給出幾個廣播的例子,具體細節可參閱python的相關手冊,這裡就不贅述了。

Coursera吳恩達《神經網絡與深度學習》課程筆記(3)-- 神經網絡基礎之Python與向量化

值得一提的是,在python程式中為了保證矩陣運算正确,可以使用reshape()函數來對矩陣設定所需的次元。這是一個很好且有用的習慣。

接下來我們将總結一些python的小技巧,避免不必要的code bug。

python中,如果我們用下列語句來定義一個向量:

這條語句生成的a的次元是(5,)。它既不是行向量也不是列向量,我們把a叫做rank 1 array。這種定義會帶來一些問題。例如我們對a進行轉置,還是會得到a本身。是以,如果我們要定義(5,1)的列向量或者(1,5)的行向量,最好使用下來标準語句,避免使用rank 1 array。

除此之外,我們還可以使用assert語句對向量或數組的次元進行判斷,例如:

assert會對内嵌語句進行判斷,即判斷a的次元是不是(5,1)的。如果不是,則程式在此處停止。使用assert語句也是一種很好的習慣,能夠幫助我們及時檢查、發現語句是否正确。

另外,還可以使用reshape函數對數組設定所需的次元:

Jupyter notebook(又稱IPython notebook)是一個互動式的筆記本,支援運作超過40種程式設計語言。本課程所有的程式設計練習題都将在Jupyter notebook上進行,使用的語言是python。

關于Jupyter notebook的簡介和使用方法可以看我的另外兩篇部落格:

Jupyter notebook入門教程(上)

Jupyter notebook入門教程(下)

在上一節課的筆記中,我們介紹過邏輯回歸的Cost function。接下來我們将簡要解釋這個Cost function是怎麼來的。

首先,預測輸出\hat y的表達式可以寫成:

\hat y=\sigma(w^Tx+b)

其中,\sigma(z)=\frac{1}{1+exp(-z)}。\hat y可以看成是預測輸出為正類(+1)的機率:

\hat y=P(y=1|x)

那麼,當y=1時:

p(y|x)=\hat y

當y=0時:

p(y|x)=1-\hat y

我們把上面兩個式子整合到一個式子中,得到:

P(y|x)=\hat y^y(1-\hat y)^{(1-y)}

由于log函數的單調性,可以對上式P(y|x)進行log處理:

log\ P(y|x)=log\ \hat y^y(1-\hat y)^{(1-y)}=y\ log\ \hat y+(1-y)log(1-\hat y)

我們希望上述機率P(y|x)越大越好,對上式加上負号,則轉化成了單個樣本的Loss function,越小越好,也就得到了我們之前介紹的邏輯回歸的Loss function形式。

L=-(y\ log\ \hat y+(1-y)log(1-\hat y))

如果對于所有m個訓練樣本,假設樣本之間是獨立同分布的(iid),我們希望總的機率越大越好:

max\ \prod_{i=1}^m\ P(y^{(i)}|x^{(i)})

同樣引入log函數,加上負号,将上式轉化為Cost function:

J(w,b)=-\frac1m\sum_{i=1}^mL(\hat y^{(i)},y^{(i)})=-\frac 1m\sum_{i=1}^my^{(i)}\ log\ \hat y^{(i)}+(1-y^{(i)})log(1-\hat y^{(i)})

上式中,\frac1m表示對所有m個樣本的Cost function求平均,是縮放因子。

本節課我們主要介紹了神經網絡基礎——python和向量化。在深度學習程式中,使用向量化和矩陣運算的方法能夠大大提高運作速度,節省時間。以邏輯回歸為例,我們将其算法流程包括梯度下降轉換為向量化的形式。同時,我們也介紹了python的相關程式設計方法和技巧。