Theano深度學習結構分析

原文鏈接

Reference:Theano入門三部曲

http://deeplearning.net/tutorial/logreg.html (Softmax迴歸)

http://deeplearning.net/tutorial/mlp.html (MLP多層感知器)

http://deeplearning.net/tutorial/lenet.html (簡易LeNet卷積神經網絡)

爲什麼要使用Theano?

深度學習最好使用一些庫,比如Theano。主要是因爲反向傳播調整參數時,需要求導。鏈式求導本身沒有難處。

但是深度學習的神經網絡架構設計的比較複雜,層數又多(15層不是夢)。

在基本BP網絡的三層結構裏,鏈式的長度已經到了5,推導公式已經不忍直視,人工求導顯然不是明智的。

Theano提供了grad梯度函數,自動根據表達式求一階導數,grad(cost,param),其中cost函數可以是一個超長超長的表達式。

param則可以是一個超大超大的數組或是矩陣。

顯然,有了grad函數,我們可以專心設計正向傳播的I/O,反向傳播只要一個grad函數即可。省去了複雜的公式推導。

Theano是深度學習較早的庫之一,由深度學習三大先驅(Geoffrey Hinton(Google)、Yann LeCun(Facebook))的Yoshua Bengio構建。

使用Python組織邏輯,C編譯執行,CUDA並行加速計算,是非常好的實驗平臺。

它的庫源碼中包含大量註釋,並且提供深度學習的幾個基本模型的代碼實現文檔。

每篇文檔都採用paper的形式,集中了許多大牛的論文的精華、各種小trick,也給出了論文的具體引用,方便按圖索驥。

Theano的一般結構

Theano基於Python的面向對象,所以它的神經網絡也是基於面向對象的思路去寫的。

【對象】

它認爲,淺層網絡的中分類器,深度網絡中的每個層,都是一個對象。

在這個對象裏,你被指定了輸入格式,你只需要做兩件事:

根據格式,定義參數、定義輸出。

【數據讀入/處理】

從文件讀入數據,並且對數據進行全局分享處理(shared)

Theano中搞了一個奇怪的shared類型,Python的普通類型可以由theano.shared()方法轉換。

Shared區是供GPU、C代碼使用的內存區,與Python的內存區獨立,但是由Tensor變量聯繫着。

這裏就不得不提Theano的函數機制。theano.tensor中封裝的着大量的惰性函數。

這些惰性函數,在Python裏是不會執行的。需要在theano.function()裏執行。

theano.function()有四大區:

inputs=[], 如果只是一個普通的列表,就把輸入放在這個參數。如果輸入有很多,應該放在givens區裏。inputs區不支持shared變量,所以也要挪到givens區。

inputs在寫function時基本是留空的,inputs=[],這個位置接受的是在線傳入的值,如果是離線值,應當放到givens區裏。

outputs=普通函數or惰性函數,就是指定工作函數。

這裏有個trick,就是如何print出Tensor表達式的量(因爲該量的值只會在執行時確定,不能使用get_value)。以取出Softmax的預測值y_pred爲例。

只要寫這樣一個function就行了,function(inputs=[],outputs=classifier.y_pred,givens={….自己指定範圍…})。

updates=參數更新的列表,格式[(原,新),(原,新)….],Shared區的變量只能在updates裏更新,Python的中賦值只會讓變量留在Python的內存區。

但是在function的內存區和Python一點關係也每有。如果Python裏設置一個Tensor關聯一些Shared變量的話,Shared區的updates會波及到Python區的值。

如CNN教程裏的,params這個Tensor,明明在Python的全局內存區,但是每次update之後,都會被改變。

也就是說Shared區能影響Python區,但是Python區無法動Shread區一根汗毛。

givens={x:List1[:],y:List2[:],…..},其中x和y是outputs函數裏使用的變量的名字,一定要對應,下面會講爲什麼。

theano.function()不是以Python的方式執行,而是迅速編譯成C代碼執行,相當於每個function都是一個獨立的子程序,所以這四大區是必要的。

由於是獨立子程序,Python中的普通變量顯然不能很好工作。所以一般都設成shared類型。

實際上,tensor的不少惰性函數都需要在Python狀態下的shared變量才能定義。原理未知。比如T.dot就不要求shared變量,但是grad的param一定要求是shared。

由於Theano的大部分計算都在function裏,而function又是以C執行,所以Theano具有不輸於C的速度,同時兼具Python的靈活性。

【主過程:前向傳播構建&反向傳播迭代】

創建各個神經網絡層、分類器的實例對象,由I/O首尾相連,最後利用分類器構建cost函數,完成前向傳播。

利用各個層對象的參數、cost函數,構建梯度表達式,以及updates列表。

爲訓練集、驗證集、測試集創建以theano.function()爲殼的模型。

使用mini-batch梯度法分批訓練訓練集,測試驗證集&測試集。

【mini-batch梯度法與驗證集收斂】

深度學習中的梯度法應當使用mini-batch。

隨機梯度(Stochastic Gradient Descent)雖然快,但是不利於收斂。

批梯度(Batch Gradient Descent)太慢,但是收斂很好。

mini-batch做了個折中,它把數據集分成好多小batch,每個batch有統一的batchsize。

對小部分數據進行BGD,這樣兼顧了速度和收斂。

每個小batch即算一次iter迭代,做完全部batch,算一次epoch。

同時引入了驗證集,由原訓練集切割而成。驗證集在小數據集裏不會出現。但是在大數據集裏一定是要有的。

原因是大數據集的cost函數,你很難去評估什麼值纔算是勉強收斂。所以採用訓練、驗證交叉的方法替代傳統的看值收斂。

驗證集訓練法有幾個參數,patience(耐力)、patience_increase(耐力增長係數)、improvement_threshold(耐力增長(模型繼續迭代改善)閾值)

validation_frequency(驗證集評估頻率)、best_validation_loss(當前最低錯誤率)。

驗證集的算法:

while(epoch++)

 訓練每個小batch

     計算當前小batch的iter

     滿足評估頻率?開始評估!

     若評估loss<最好loss

         若評估loss<最好loss*閾值:patience=max(patience,iter*增長係數)

         更新最好loss

     (選擇):評估測試集

iter >=patience: 總迭代結束

一旦長時間評估loss沒有刷新patience,很快iter就會超過patience而結束迭代。

否則,則一直訓練,不停創造更好的loss。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章