caffe+報錯︱深度學習參數調優雜記+caffe訓練時的問題+dropout/batch Normalization

目錄(?)[-]

  1. 一深度學習中常用的調節參數
    1. 學習率
    2. 權重
    3. 層數
    4. 過擬合
    5. Loss設計與觀察
    6. 初始化
    7. weight decay權值衰減
    8. momentum
    9. 訓練時間 Early stopping
    10. 增加噪聲 Noise
  2. 二caffe訓練時Loss變爲nan的原因
    1. 梯度爆炸
    2. 不當的損失函數
    3. 不當的輸入
    4. 池化層中步長比核的尺寸大
  3. 三一些訓練時候出現的問題
    1. 爲啥label需要從0開始
    2. 爲什麼Caffe中引入了這個inner_numinner_num等於什麼
    3. 在標籤正確的前提下如果倒數第一個全連接層num_output 實際的類別數Caffe的訓練是否會報錯
    4. BN中的use_global_status
    5. BatchNorm層是否支持in place運算爲什麼
  4. 四過擬合解決dropoutbatch Normalization
    1. dropout另類Bagging類似隨機森林RF
    2. batch Normalization
    3. 延伸一Check failed error cudaSuccess 2 vs 0 out of memory
    4. 延伸二softmax出現的問題與解決
    5. 延伸三caffe中layer與layers的差別
    6. 延伸四深度學習中jpg圖像讀取失敗原因
    7. 延伸五caffe_pb2NetParameter網絡層打印
    8. 延伸六如何成爲一名成功的煉丹師DL訓練技巧

一、深度學習中常用的調節參數

本節爲筆者上課筆記(CDA深度學習實戰課程第一期)

1、學習率

步長的選擇:你走的距離長短,越短當然不會錯過,但是耗時間。步長的選擇比較麻煩。步長越小,越容易得到局部最優化(到了比較大的山谷,就出不去了),而大了會全局最優

一般來說,前1000步,很大,0.1;到了後面,迭代次數增高,下降0.01,再多,然後再小一些。 
這裏寫圖片描述

2、權重

梯度消失的情況,就是當數值接近於正向∞,求導之後就更小的,約等於0,偏導爲0 
梯度爆炸,數值無限大

對於梯度消失現象:激活函數 
Sigmoid會發生梯度消失的情況,所以激活函數一般不用,收斂不了了。Tanh(x),沒解決梯度消失的問題。 
ReLu Max(0,x),比較好,代表Max門單元,解決了梯度消失的問題,而且起到了降維

權重初始化,可以隨機也可以一開始設置一定的圖形分佈,用高斯初始化

3、層數

越多,靈敏度越好,收斂地更好,激活函數也越多,曲線的性能也更好 
但是,神經元過擬合,並且計算量較大層數越多。在節點多的情況下一般會考慮:Drop-out 
節點太多也不好,所以需要刪除一些無效的節點 
但是去掉節點,這裏卻是隨機的,隨機去掉(30%-60%)的節點 
注意:隨機的選擇,去掉一些節點。但是drop-out也不一定是避免過擬合 
很常見。一般不drop-out一定會過擬合,有drop-out概率低一些

4、過擬合

上面的drop-out就算一種。其他過擬合可能也會使用:BN,batch normalization(歸一化)

在caffe操作時候,模型訓練中如何解決過擬合現象?

看到驗證集的數據趨於平穩,譬如第1000次之後,驗證集的loss平穩了,那麼就截取1000次,把學習率降低爲原來的0.1,拿來第10000次結果,修改文件,繼續訓練。 
.

5、Loss設計與觀察

一般來說分類就是Softmax, 迴歸就是L2的loss. 但是要注意loss的錯誤範圍(主要是迴歸), 你預測一個label是10000的值, 模型輸出0, 你算算這loss多大, 這還是單變量的情況下. 一般結果都是nan. 所以不僅僅輸入要做normalization, 輸出也要。 
準確率雖然是評測指標, 但是訓練過程中還是要注意loss的. 你會發現有些情況下, 準確率是突變的, 原來一直是0, 可能保持上千迭代, 然後突然變1. 要是因爲這個你提前中斷訓練了, 只有老天替你惋惜了. 而loss是不會有這麼詭異的情況發生的, 畢竟優化目標是loss. 
對比訓練集和驗證集的loss。 判斷過擬合, 訓練是否足夠, 是否需要early stop的依據 
.

6、初始化

一次慘痛的教訓是用normal初始化cnn的參數,最後acc只能到70%多,僅僅改成xavier,acc可以到98%。還有一次給word embedding初始化,最開始使用了TensorFlow中默認的initializer(即glorot_uniform_initializer,也就是大家經常說的無腦使用xavier),訓練速度慢不說,結果也不好。改爲uniform,訓練速度飆升,結果也飆升。所以,初始化就跟黑科技一樣,用對了超參都不用調;沒用對,跑出來的結果就跟模型有bug一樣不忍直視。

經驗來源:https://www.zhihu.com/question/25097993/answer/153674495 
.

7、weight decay(權值衰減)

的使用既不是爲了提高你所說的收斂精確度也不是爲了提高收斂速度,其最終目的是防止過擬合。在損失函數中,weight decay是放在正則項(regularization)前面的一個係數,正則項一般指示模型的複雜度,所以weight decay的作用是調節模型複雜度對損失函數的影響,若weight decay很大,則複雜的模型損失函數的值也就大。 
.

8、momentum

是梯度下降法中一種常用的加速技術。 
即momentum係數,通俗的理解上面式子就是,如果上一次的momentum與這一次的負梯度方向是相同的,那這次下降的幅度就會加大,所以這樣做能夠達到加速收斂的過程 
.

9、訓練時間 Early stopping

對於每個神經元而言,其激活函數在不同區間的性能是不同的: 
這裏寫圖片描述

當網絡權值較小時,神經元的激活函數工作在線性區,此時神經元的擬合能力較弱(類似線性神經元)。

有了上述共識之後,我們就可以解釋爲什麼限制訓練時間(early stopping)有用:因爲我們在初始化網絡的時候一般都是初始爲較小的權值。訓練時間越長,部分網絡權值可能越大。如果我們在合適時間停止訓練,就可以將網絡的能力限制在一定範圍內。 
.

10、增加噪聲 Noise

給網絡加噪聲也有很多方法:

在輸入中加噪聲:噪聲會隨着網絡傳播,按照權值的平方放大,並傳播到輸出層,對誤差 Cost 產生影響。 
在權值上加噪聲:在初始化網絡的時候,用 0 均值的高斯分佈作爲初始化。Alex Graves 的手寫識別 RNN 就是用了這個方法 
對網絡的響應加噪聲:如在前向傳播過程中,讓默寫神經元的輸出變爲 binary 或 random。顯然,這種有點亂來的做法會打亂網絡的訓練過程,讓訓練更慢,但據 Hinton 說,在測試集上效果會有顯著提升 (But it does significantly better on the test set!)。


二、caffe訓練時Loss變爲nan的原因

本節轉載於公衆號平臺:極市平臺

1、梯度爆炸

原因:梯度變得非常大,使得學習過程難以繼續

現象:觀察log,注意每一輪迭代後的loss。loss隨着每輪迭代越來越大,最終超過了浮點型表示的範圍,就變成了NaN。 
措施: 
1. 減小solver.prototxt中的base_lr,至少減小一個數量級。如果有多個loss layer,需要找出哪個損失層導致了梯度爆炸,並在train_val.prototxt中減小該層的loss_weight,而非是減小通用的base_lr。 
2. 設置clip gradient,用於限制過大的diff

2、不當的損失函數

原因:有時候損失層中loss的計算可能導致NaN的出現。比如,給InfogainLoss層(信息熵損失)輸入沒有歸一化的值,使用帶有bug的自定義損失層等等。

現象:觀測訓練產生的log時一開始並不能看到異常,loss也在逐步的降低,但突然之間NaN就出現了。 
措施:看看你是否能重現這個錯誤,在loss layer中加入一些輸出以進行調試。 
示例:有一次我使用的loss歸一化了batch中label錯誤的次數。如果某個label從未在batch中出現過,loss就會變成NaN。在這種情況下,可以用足夠大的batch來儘量避免這個錯誤。

3、不當的輸入

原因:輸入中就含有NaN。

現象:每當學習的過程中碰到這個錯誤的輸入,就會變成NaN。觀察log的時候也許不能察覺任何異常,loss逐步的降低,但突然間就變成NaN了。 
措施:重整你的數據集,確保訓練集和驗證集裏面沒有損壞的圖片。調試中你可以使用一個簡單的網絡來讀取輸入層,有一個缺省的loss,並過一遍所有輸入,如果其中有錯誤的輸入,這個缺省的層也會產生NaN。 
案例:有一次公司需要訓練一個模型,把標註好的圖片放在了七牛上,拉下來的時候發生了dns劫持,有一張圖片被換成了淘寶的購物二維碼,且這個二維碼格式與原圖的格式不符合,因此成爲了一張“損壞”圖片。每次訓練遇到這個圖片的時候就會產生NaN。 
良好的習慣是,你有一個檢測性的網絡,每次訓練目標網絡之前把所有的樣本在這個檢測性的網絡裏面過一遍,去掉非法值。

4、池化層中步長比核的尺寸大

如下例所示,當池化層中stride > kernel的時候會在y中產生NaN

    layer {
      name: "faulty_pooling"
      type: "Pooling"
      bottom: "x"
      top: "y"
      pooling_param {
      pool: AVE
      stride: 5
      kernel: 3
      }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

http://stackoverflow.com/questions/33962226/common-causes-of-NaNs-during-training


.

三、一些訓練時候出現的問題

本節轉載於公衆號深度學習大講堂,文章《caffe代碼夜話1》

1、爲啥label需要從0開始?

在使用SoftmaxLoss層作爲損失函數層的單標籤分類問題中,label要求從零開始,例如1000類的ImageNet分類任務,label的範圍是0~999。這個限制來自於Caffe的一個實現機制,label會直接作爲數組的下標使用,具體代碼SoftmaxLoss.cpp中133行和139行的實現代碼。

這裏寫圖片描述

132行第一層for循環中的outer_num等於batch size,對於人臉識別和圖像分類等單標籤分類任務而言,inner_num等於1。如果label從1開始,會導致bottom_diff數組訪問越界。 
.

2、爲什麼Caffe中引入了這個inner_num,inner_num等於什麼

從FCN全卷積網絡的方向去思考。FCN中label標籤長度=圖片尺寸 
caffe引入inner_num使得輸入image的size可以是任意大小,innuer_num大小即爲softmax層輸入的height*width 
.

3、在標籤正確的前提下,如果倒數第一個全連接層num_output > 實際的類別數,Caffe的訓練是否會報錯?

不會報錯且無影響 
.

4、BN中的use_global_status

這裏寫圖片描述 
圖2. ResNet部署階模型Proto文件片段

但是如果直接拿這個Proto用於訓練(基於隨機初始化),則會導致模型不收斂,原因在於在Caffe的batch_norm_layer.cpp實現中,use_global_stats==true時會強制使用模型中存儲的BatchNorm層均值與方差參數,而非基於當前batch內計算均值和方差。

首先看use_global_stats變量是如何計算的: 
這裏寫圖片描述 
圖3. use_global_stats計算

再看這個變量的作用: 
這裏寫圖片描述 
圖4. use_global_stats爲true時的行爲

以下代碼在use_global_stats爲false的時候通過moving average策略計算模型中最終存儲的均值和方差: 
這裏寫圖片描述 
圖5. BatchNorm層均值和方差的moving average

因此,對於隨機初始化訓練BatchNorm層,只需要在Proto文件中移除use_global_stats參數即可,Caffe會根據當前的Phase(TRAIN或者TEST)自動去設置use_global_stats的值。 
.

5、BatchNorm層是否支持in place運算,爲什麼?

BN是對輸入那一層做歸一化操作,要對每個元素-均值/標準差,且輸入輸出規格相當,是可以進行in place。 
標準的ReLU函數爲max(x, 0),而一般爲當x > 0時輸出x,但x <= 0時輸出negative_slope。RELU層支持in-place計算,這意味着bottom的輸出和輸入相同以避免內存的消耗。 

.

四、過擬合解決:dropout、batch Normalization

來源於:https://github.com/exacity/deeplearningbook-chinese/releases/

1、dropout——另類Bagging(類似隨機森林RF)

引用自Dropout作者: 
在標準神經網絡中,每個參數接收的導數表明其應該如何變化才能使最終損失函數降低,並給定所有其它神經網絡單元的狀態。因此神經單元可能以一種可以修正其它神經網絡單元的錯誤的方式進行改變。而這就可能導致複雜的共適應(co-adaptations)。由於這些共適應現象沒有推廣到未見的數據,將導致過擬合。我們假設對每個隱藏層的神經網絡單元,Dropout通過使其它隱藏層神經網絡單元不可靠從而阻止了共適應的發生。因此,一個隱藏層神經元不能依賴其它特定神經元去糾正其錯誤。(來源:賽爾譯文 Dropout分析)

Dropout可以被認爲是集成非常多的大神經 網絡的實用Bagging方法。當每個模型是一個大型神經網絡時,這似乎是不切實際的,因爲訓練和 評估這樣的網絡需要花費很多運行時間和內存。 
Dropout提供了一種廉價的Bagging集成近似,能夠訓練和評估指數級的神經網絡。 
操作方法:將一些單元的輸出乘零就能有效地刪除一個單元。

這裏寫圖片描述

(1)具體工作過程:

Dropout以概率p關閉神經元,相應的,以大小爲q=1-p的概率開啓其他神經元。每個單個神經元有同等概率被關閉。當一個神經元被丟棄時,無論其輸入及相關的學習參數是多少,其輸出都會被置爲0。 
丟棄的神經元在訓練階段的前向傳播和後向傳播階段都不起作用:因爲這個原因,每當一個單一的神經元被丟棄時,訓練階段就好像是在一個新的神經網絡上完成。 
訓練階段,可以使用伯努利隨機變量、二項式隨機變量來對一組神經元上的Dropout進行建模。 
(來源:賽爾譯文 Dropout分析) 
這裏寫圖片描述

(2)dropout類型: 
正向dropout、反向dropout。 
反向Dropout有助於只定義一次模型並且只改變了一個參數(保持/丟棄概率)以使用同一模型進行訓練和測試。相反,直接Dropout,迫使你在測試階段修改網絡。因爲如果你不乘以比例因子q,神經網絡的輸出將產生更高的相對於連續神經元所期望的值(因此神經元可能飽和):這就是爲什麼反向Dropout是更加常見的實現方式。

(3)dropout與其他規則

故反向Dropout應該與限制參數值的其他歸一化技術一起使用,以便簡化學習速率選擇過程

正向Dropout:通常與L2正則化和其它參數約束技術(如Max Norm1)一起使用。正則化有助於保持模型參數值在可控範圍內增長。 
反向Dropout:學習速率被縮放至q的因子,我們將其稱q爲推動因子(boosting factor),因爲它推動了學習速率。此外,我們將r(q)稱爲有效學習速率(effective learning rate)。總之,有效學習速率相對於所選擇的學習速率更高:由於這個原因,限制參數值的正則化可以幫助簡化學習速率選擇過程。 
(來源:賽爾譯文 Dropout分析)

(4)優勢:

  • 看作是對輸入內容的信息高度智能化、自適應破壞的一種形式,而不是 對輸入原始值的破壞。

  • Dropout不僅僅是訓練一個Bagging的集成模型,並且是共享隱藏單元的集成模型。這意味着無論其他隱藏單元是否在模型中,每個隱藏單元必須都能夠表現良好。隱藏單元必須準備好進行模型之間的交換和互換。

  • 計算方便是Dropout的一個優點。訓練過程中使用Dropout產生 n 個隨機二進制 數與狀態相乘,每個樣本每次更新只需 O(n)的計算複雜度。

  • Dropout的另一個顯著優點是不怎麼限制適用的模型或訓練過程。幾乎在所有 使用分佈式表示且可以用隨機梯度下降訓練的模型上都表現很好。包括前饋神經網 絡、概率模型,如受限玻爾茲曼機(Srivastava et al., 2014),以及循環神經網絡(Bayer and Osendorfer, 2014; Pascanu et al., 2014a)。許多其他差不多強大正則化策略對模 型結構的限制更嚴格。

(5)劣勢:

  • Dropout是一個正則化技術,它減少了模型的有效容量。爲了抵消這種影響,我們必須增大模型規模。不出意外的話,使 用Dropout時最佳驗證集的誤差會低很多,但這是以更大的模型和更多訓練算法的迭 
    代次數爲代價換來的。對於非常大的數據集,正則化帶來的泛化誤差減少得很小。在 
    這些情況下,使用Dropout和更大模型的計算代價可能超過正則化帶來的好處。

  • 只有極少的訓練樣本可用時,Dropout不會很有效。在只有不到 5000 的樣本 的Alternative Splicing數據集上 (Xiong et al., 2011),貝葉斯神經網絡 (Neal, 1996)比Dropout表現更好 
    (Srivastava et al., 2014)。當有其他未分類的數據可用時,無監 督特徵學習比Dropout更有優勢。 
    .

2、batch Normalization

batch normalization的主要目的是改善優化,但噪音具有正則化的效果,有時使Dropout變得沒有必要。 
參數訓練過程中多層之間協調更新的問題:在其他層不改變的假設下,梯度用於如何更新每一個參數。但是,一般情況下會同時更新所有層。 這造成了很難選擇一個合適的學習速率,因爲某一層中參數更新的效果很大程度上取決 於其他所有層。 
batch normalization可應用於網絡 的任何輸入層或隱藏層。設 H 是需要標準化的某層的minibatch激勵函數,佈置爲 設計矩陣,每個樣本的激勵出現在矩陣的每一行中。標準化 H,我們替代它爲 
這裏寫圖片描述 
其中 μ 是包含每個單元均值的向量,σ 是包含每個單元標準差的向量。 
反向傳播這些操作,計算均值和標準差,並應用它們於標準化 H。這意味着,梯度不會再簡單地增加 hi 的標準差或均值;標準化操作會 除掉這一操作的影響,歸零其在梯度中的元素。

以前的方法添加代價函數的懲罰,以鼓勵單位標準化激勵統計量,或是 在每個梯度下降步驟之後重新標準化單位統計量。 
前者通常會導致不完全的標準化, 而後者通常會顯著地消耗時間,因爲學習算法會反覆改變均值和方差而標準化步驟 會反覆抵消這種變化。 
batch normalization重新參數化模型,以使一些單元總是被定 義標準化,巧妙地迴避了這兩個問題。


.

延伸一:Check failed: error == cudaSuccess (2 vs. 0) out of memory

參考博客:【caffe跑試驗遇到錯誤:Check failed: error == cudaSuccess (2 vs. 0) out of memory】

明顯是內存不夠, nvidia-smi/watch -n 0.1 nvidia-smi實時查看

發現有top命令無法查看到的進程,將這些進程殺死掉,釋放內存:

殺死進程命令:kill -9 PID

最後重新運行試驗,就可以開始跑了,最後我終於知道爲什麼了:

top是監視CPU的,而 nvidia-smi纔是監視GPU的。 
.

延伸二:softmax出現的問題與解決

caffe中softmax層有兩種方式:softmax和SoftmaxWithLoss。本節內容來源:Caffe 訓練時loss等於87.33的原因及解決方法

layers {
  name: "prob"
  type: “Softmax"
bottom: " ip2"
  top: "prob"
}

layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

softmax,name=top名稱,bottom爲上一層的names。 
softmax計算: 
這裏寫圖片描述 
softmax中Loss的計算: 
這裏寫圖片描述

softmax層會出現的報錯: 
softmax是用指數函數計算的,指數函數的值都是大於零的。因此,我們有理由相信,計算過程中出現了float溢出等異常,出現了inf,nan等異常數值導致softmax輸出爲零 
最後我們發現,當softmax之前的feature值過大時,由於softmax先求指數,會超出float數據範圍,成爲inf。inf與其他任何數值的和都是inf,softmax在做除法時任何正常範圍的數值除以inf都會變爲0。然後求loss時log一下就出現了87.3356這樣的值。

softmax的解決方案: 
1、觀察數據中是否有異常樣本或異常label導致數據讀取異常 
2、調小初始化權重,以便使softmax輸入的feature儘可能變小 
3、降低學習率,這樣就能減小權重參數的波動範圍,從而減小權重變大的可能性。這條也是網上出現較多的方法。 
4、如果有BN(batch normalization)層,finetune時最好不要凍結BN的參數,否則數據分佈不一致時很容易使輸出值變的很大。 
.

延伸三:caffe中layer與layers的差別

報錯:

 Manually switch the definition to 'layer' format to continue.
  • 1
  • 1

來源layer與layers是有差別的,來看看:

#layers層的type需要大寫,且沒有引號
layers {
  bottom: "fc8"
  top: "prob"
  name: "prob"
  type: SOFTMAX
}

#layer層的type帶引號,且小寫
layer {
  name: "prob"
  type: "Softmax"
  bottom: "fc8"
  top: "prob"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

同樣一個輸出softmax層,爲啥呢?網上問答:

之前在caffe裏下載的caffemodel的prototxt網絡構造,裏面的構架是用layer寫的。後來想試一下VGGnet等高端構架,網上下載到的居然是layers模式的,坑了我好久,才找到錯誤根源,原來是layers的參數跟layer有所差異。 
caffe利用google開發的proto工具對自己的prototxt文件進行解析,解析過後生成cpp或者py的代碼。所以雖然layers和layer的構造不同,其實就是參數的大小寫名字之類的有所差異,但是最後有用的代碼是一樣的。儘管如此,我們在同一個prototxt文件中只能使用一種格式,不能layer和layers混用。但是呢,deploy.prototxt和train_val.prototxt之間是可以不同的。 
在layer版本deploy中輸入數據的格式爲:“Input”,這個是有講究的,跟訓練的數據type不同,因爲訓練時用的“Data”,他們的主要差異在於,Data是有label的,而Input就是輸入數據而已,很單純,也就是他們的blobs維數不同,因此在deploy.prototxt中要用Input。我找了半天沒有找到在layers層中Input應該替換爲什麼類型的type,因此我的deploy還是使用的layer結構,不過能夠正常運行。

延伸四:深度學習中.jpg圖像讀取失敗原因

筆者在導入.jpg會出現兩種情況:

  • 1、.jpg導入不了,報錯truncated;
  • 2、圖片尤其是png.(雖然後綴是jpg)格式的圖片會出現,無法轉換爲np.array

情況一(參考鏈接):

ValueError: Could not load ""
Reason: "image file is truncated (2 bytes not processed)"
  • 1
  • 2
  • 1
  • 2

筆者在使用caffe時候,出現以上報錯,明明是一個好的jpg圖像,爲啥讀不進去呢? 
這時候就需要額外導入以下代碼:

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
  • 1
  • 2
  • 1
  • 2

情況二:(參考鏈接

libpng error: Read Error
  • 1
  • 1

以上的解決方法:

import cv2, random
import os
import numpy as np
from PIL import Image
from PIL import ImageFile
import imghdr

ImageFile.LOAD_TRUNCATED_IMAGES = True
if imghdr.what(name) == "png":
    Image.open(name).convert("RGB").save(name)
img = cv2.imread(name)
img = np.array(Image.open(name))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

轉換一下格式爲RGB 
.

延伸五:caffe_pb2.NetParameter網絡層打印

來源於:Caffe學習——使用自己的數據(非圖像)訓練網絡

# load MS COCO model specs
file = open(caffe_root + 'models/VGGNet/coco/SSD_512x512/deploy.prototxt', 'r')
coco_netspec = caffe_pb2.NetParameter()
text_format.Merge(str(file.read()), coco_netspec)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

根據NetParameter打印網絡結構,用於保存deploy和train_test的網絡結構。

import google.protobuf  
def print_network(prototxt_filename, caffemodel_filename):  
    ''''' 
    Draw the ANN architecture 
    '''  
    _net = caffe.proto.caffe_pb2.NetParameter()  
    f = open(prototxt_filename)  
    google.protobuf.text_format.Merge(f.read(), _net)  
    caffe.draw.draw_net_to_file(_net, prototxt_filename + '.png' )  
    print('Draw ANN done!')  

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

這裏寫圖片描述

打印網絡權重時用的是train_test.prototxt,用deploy.prototxt也行。繪製的網絡結構圖中的data和loss層爲藍色矩形塊,而ip1~ip3爲灰色八邊形塊。因爲data層的輸出和loss層的輸出爲不帶權重的真實值,所以它倆在即使在net.params中,各自的所有權重也是相同的。實驗保存的圖片中沒有xxx_weights_xx_data/loss.png也驗證了這一點。heatmap反映了某網絡中間層的輸入節點和輸出節點之間的權重,而histogram反映同一層網絡中間層的權重值的分佈。

.

延伸六:如何成爲一名成功的“煉丹師”——DL訓練技巧

來源: 計算機視覺戰隊 
今天給大家講講DNN(深度神經網絡)在訓練過程中遇到的一些問題,然後我們應該怎麼去注意它,並學會怎麼去訓練它。

1、數據集的準備: 
必須要保證大量、高質量且帶有準確標籤的數據,沒有該條件的數據,訓練學習很困難的(但是最近我看了以爲作者寫的一篇文章,說明不一定需要大量數據集,也可以訓練的很好,有空和大家來分享其思想—很厲害的想法); 
2、數據預處理: 
這個不多說,就是0均值和1方差化,其實還有很多方法; 
3、Minibatch: 
這個有時候還要根據你的硬件設備而定,一般建議用128,8這組,但是128,1也很好,只是效率會非常慢,注意的是:千萬不要用過大的數值,否則很容易過擬合; 
4、梯度歸一化: 
其實就是計算出來梯度之後,要除以Minibatch的數量,這個可以通過閱讀源碼得知(我之前有寫過SGD); 
5、學習率: 
① 一般都會有默認的學習率,但是剛開始還是用一般的去學習,然後逐漸的減小它; 
② 一個建議值是0.1,適用於很多NN的問題,一般傾向於小一點;但是如果對於的大數據,何凱明老師也說過,要把學習率調到很小,他說0.00001都不爲過(如果記得不錯,應該是這麼說的); 
③ 一個對於調度學習率的建議:如果在驗證集上性能不再增加就讓學習率除以2或者5,然後繼續,學習率會一直變得很小,到最後就可以停止訓練了; 
④ 很多人用的一個設計學習率的原則就是監測一個比率(每次更新梯度的norm除以當前weight的norm),如果這個比率在10e-3附近,且小於這個值,學習會很慢,如果大於這個值,那麼學習很不穩定,由此會帶來學習失敗。 
6、驗證集的使用: 
使用驗證集,可以知道什麼時候開始降低學習率和什麼時候停止訓練; 
7、weight初始化: 
① 如果你不想繁瑣的話,直接用0.02*randn(num_params)來初始化,當然別的值也可以去嘗試; 
② 如果上面那個建議不太好使,那麼就依次初始化每一個weight矩陣用init_scale / sqrt(layer_width) * randn,init_scale可以被設置爲0.1或者1; 
③ 初始化參數對結果的影響至關重要,要引起重視; 
④ 在深度網絡中,隨機初始化權重,使用SGD的話一般處理的都不好,這是因爲初始化的權重太小了。這種情況下對於淺層網絡有效,但是當足夠深的時候就不行,因爲weight更新的時候,是靠很多weight相乘的,越乘越小,類似梯度消失的意思。 
8、RNN&&LSTM(這方面沒有深入瞭解,借用別人的意思): 
如果訓練RNN或者LSTM,務必保證gradient的norm被約束在15或者5(前提還是要先歸一化gradient),這一點在RNN和LSTM中很重要; 
9、梯度檢查: 
檢查下梯度,如果是你自己計算的梯度;如果使用LSTM來解決長時依賴的問題,記得初始化bias的時候要大一點; 
10、數據增廣: 
儘可能想辦法多的擴增訓練數據,如果使用的是圖像數據,不妨對圖像做一點扭轉,剪切,分割等操作來擴充數據訓練集合; 
11、dropout:(先空着,下次我要單獨詳細講解Dropout) 
12、評價結果: 
評價最終結果的時候,多做幾次,然後平均一下他們的結果。

補充:

1、選擇優化算法 
傳統的隨機梯度下降算法雖然適用很廣,但並不高效,最近出現很多更靈活的優化算法,例如Adagrad、RMSProp等,可在迭代優化的過程中自適應的調節學習速率等超參數,效果更佳; 
2、參數設置技巧 
無論是多核CPU還是GPU加速,內存管理仍然以字節爲基本單元做硬件優化,因此將參數設定爲2的指數倍,如64,128,512,1024等,將有效提高矩陣分片、張量計算等操作的硬件處理效率; 
3、正則優化 
除了在神經網絡單元上添加傳統的L1/L2正則項外,Dropout更經常在深度神經網絡應用來避免模型的過擬合。初始默認的0.5的丟棄率是保守的選擇,如果模型不是很複雜,設置爲0.2就可以; 
4、其他方法 
除了上述訓練調優的方法外,還有其他一些常用方法,包括:使用mini-batch learning方法、遷移訓練學習、打亂訓練集順序、對比訓練誤差和測試誤差調節迭代次數、日誌可視化觀察等等。

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