UFLDL 是史丹佛大學 CS294A課程 的教學 wiki。課程設定很科學,循序漸進,每次課程都是在上次的基礎上增添一些東西,還有作業可以讓你直觀地感受所學內容。雖然沒有涉及 RNN (迴圈神經網路),但作為 CNN(卷積神經網路)的基礎課程還是很不錯的。 如果你對 監督學習、邏輯迴歸、梯度下降 等基礎概念並不熟悉,可以先學習 之前的課程。 關於課程作業的 Python 程式碼已經放到了 Github 上,點選 課程程式碼 就能去 Github 檢視,程式碼中的錯誤和改進歡迎大家指出。
稀疏自編碼器
大家知道現在深度學習在計算機視覺領域全面開花結果,得到了許多之前無法想象的好結果。而就在這之前大家還要花費很大的精力來人工設計特徵。這部分學習的 稀疏自編碼器 正是向自動學習特徵邁出的第一步,也是這門課程的基礎。( 下圖為作業中的神經網路,左圖為輸入影像,右圖為訓練後的輸出影像 )


向量化
向量化 是在程式碼中竟可能地使用向量運算來代替原有 For 迴圈。由於能夠使用向量運算的庫通常對向量運算進行過優化,所以可以大大加速程式碼的執行速度。
舉一段 反向傳播 演算法中的例子,它的作用是對於每一組資料執行反向傳播並累計誤差。
for i in range(m):
d3 = (a3[i] - data[i]) * a3[i] * (1.0 - a3[i])
d2 = (np.dot(d3,Theta2)[1:] + beta * sparsity_delta) * a2[i][1:] * (1.0 - a2[i][1:])
delta1 = delta1 + np.dot(d2.reshape(-1,1),a1[[i]])
delta2 = delta2 + np.dot(d3.reshape(-1,1),a2[[i]])
複製程式碼
wiki 中有建議將這段程式碼向量化,不過沒有給出具體的虛擬碼。筆者原以為最後只剩這部分沒改的話對效率也不會有十分大的影響,但事實是向量化之後,學習速度得到了明顯的提升 Orz。( 這個章節對於後面的課程可以說是必須的,因為最痛苦的事莫過於學習速度很慢,你的程式碼又有問題需要重新學習 )
d3 = (a3 - data) * a3 * (1.0 - a3)
d2 = (np.dot(d3, Theta2)[:,1:] + beta * sparsity_delta) * a2[:,1:] * (1.0 - a2[:,1:])
delta1 = np.dot(d2.T, a1)
delta2 = np.dot(d3.T, a2)
複製程式碼
作業將 稀疏自編碼器 使用在 MNIST 資料集上,學習到了很有意思的邊緣特徵。

預處理
課程中使用的預處理為 ZCA Whitening,它的想法是去除輸入特徵的相關性。首先將特徵變換到無相關性的座標下,通過相關性係數拉伸,再變換到原先的座標系,使得特徵在原先座標系下不再相關。( 對於二維特徵,整個過程如下圖 )


Softmax
在 Softmax 這部分,我們使用它來為 稀疏自編碼器 自學習到的特徵來分類,它的特點是輸出向量是歸一化的( 和為一 )。不過在之前 MNIST分類問題 中,我們對每個輸出層的神經元使用了邏輯迴歸( 每個輸出都是二元分類 )。這就產生了一個問題,什麼時候該使用 Softmax,什麼時候使用邏輯迴歸呢?
Ng 告訴我們問題的關鍵在於類別之間是否互斥。比如我們的手寫字元識別問題,每個數字類別是互斥的,你寫的數字不可能既是 1 又是 2。如果你的資料可能既屬於分類 A 又 屬於分類 B,這時候你就需要使用邏輯迴歸了。
增加深度
這時課程開始漸入正題,Ng 告訴我們 稀疏自編碼器 能夠自己學習到區域性影像的邊緣特徵,如果使用中間層的輸出作為特徵再訓練一個稀疏自編碼器,這時的隱含層會學習如何去組合邊,從而構成輪廓、角等更高階的特徵。再加上稀疏自編碼器是無監督學習,所以我們可以反覆使用這種方式來構建更深的網路,並在最後對整個網路進行 微調 來高效地完成深層網路的訓練。

- 使用輸入影像訓練稀疏自編碼器,獲得隱含層的權值
- 將隱含層的輸出作為特徵訓練第二層稀疏自編碼器
- 將第二層稀疏自編碼器隱含層的輸出作為特徵,原資料的結果目標值,訓練 Softmax 分類器
- 微調 整個網路的權值,完成網路的訓練
大影像處理
在先前的網路中,隱含層的每個神經元連線了所有輸入層的神經元。當訓練圖片增大時,所要學習的權值也不斷增多,以至於訓練速度慢到不可接受。受 視覺皮層的神經元只感受區域性接受資訊 的啟發( 同時也是自然影像有其固有特性,也就是說,影像的一部分的統計特性與其他部分是一樣的 ),我們可以讓隱含層只連線一部分的輸入單元來提取特徵。
比如輸入資料是 96x96 的圖片,我們先隨機取這些圖片中 8x8 的區域性影像,用 稀疏自編碼器 學習 100 個特徵( 隱含層單元及輸入的權值,作業中學習到的特徵如下圖 )。


不難發現,當我在原圖上通過卷積提取特徵的時候,只有某些位置的啟用是最強烈的,所以我們使用 池化 來減小冗餘。池化 就是在卷積輸出的每個區域,使用均值或者最大值來代替原來的輸出,它帶來的一個好處是提取的特徵對影像的平移不敏感。

後續
通過 Coursera 課程,我們學習了一些基本的 機器學習 演算法,對整個領域有了一個大體的認識。UFLDL 課程在它的基礎上更近一步,介紹了深度學習中 CNN 的網路架構和學習方法。有了這些基礎就不難理解由 CNN 架構演化而來的各種網路( CNN 架構的演進 )。
對於之後要學習的深度學習知識點,一方面考慮學習一下 RNN( 迴圈神經網路 ),以及基於這個架構演化的用來處理序列的網路;另一方面考慮學習不同的學習方法,比如 強化學習。