1. 程式人生 > >TensorFlow 訓練多個loss函式技巧: 訓練步驟,凍結部分層(freeze some scopes),從tensorboard檢查問題

TensorFlow 訓練多個loss函式技巧: 訓練步驟,凍結部分層(freeze some scopes),從tensorboard檢查問題

這兩天使用TensorFlow訓練一個多個損失函式的網路模型,自己搭建網路,調參訓練,由於網路是一個兩階段的網路,具有三個損失函式,其中兩個損失函式監督第一個階段,一個損失函式家督第二個階段,而且損失函式監督的並不全是最後一層,還有中間層,這需要調整我的訓練方式。

訓練方式

  1. 先分別訓練第一階段的兩個損失函式
  2. 固定住第一階段的網路的引數,只訓練第二階段網路引數
  3. 調整三個loss函式的正則化引數,減小學習率同時訓練三個loss函式進行精調

凍結部分層(固定低層引數)

第一步和最後一步都好說,假設定義好了三個loss函式分別為self.loss1,self.loss2,self.loss3和加入正則化後的整個網路的損失函式self.loss,那麼第一步和第三步的實現例項為

 optimizer = tf.train.AdamOptimizer(self.lr, beta=0.9, beta=0.999, name='AdamOptimizer')
 update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
 with tf.control_denpendencies(update_ops):
     self.train_op = optimizer.minimize(self.loss)

這是我們常用的整個網路的引數都進行訓練的方式,當需要固定低層的引數時,例如我有一個24層的網路,我需要固定1-14層,只更新15-24層,也就是上面的第二個步驟,則程式碼如下

optimizer = tf.train.AdamOptimizer(self.lr, beta=0.9, beta=0.999, name='AdamOptimizer')
update_ops3 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
                                scope="block15|block16|block17|block18|block19|block20|block21|block22|block23|block24")
self.train_op3 = optimizer.minimize(self.loss3, var_list=update_ops3)

也就是在tf.get_collection()的變數中scope賦予需要更新的值,當不指定時預設值為none,這時網路會更新全部的引數。這裡需要注意的是:

  1. 原來的tf.GraphKeys.UPDATE_OPS已經修改為tf.GraphKeys.TRAINABLE_VARIABLES,實踐證明不修改會報錯,我不太清楚兩者的本質區別,需要後續學習
  2. 這裡的block*是我封裝好的層
  3. 多個封裝的scope之間用‘|’上述的scope=“block15|block16|block17|block18|block19|block20|block21|block22|block23|block24” 應該還有更簡便的寫法,不過這樣也可以達到目的

tensorboard視覺化結果

上述操作後依然不放心,不知道是不是整的達到了目的,我使用了兩種方法進行驗證,第一種是訓練一下,使用tensorboard的distributions或者histograms模組看看除了指定的層之外其他的層有沒有改變,事實證明沒有改變。
除此之外,還發現了另外一種方式就是看GRAPHS,如下圖所示,我使用了四次不同了優化,因此圖中有四個不同的優化器和梯度,其中gradient_2就是我優化self.loss的梯度,可以從圖的右邊看出,梯度是傳播到了每一個block的。
圖一:tensorbora_GRAPHS

而下圖是我固定了低層的引數只是訓練後面層的引數時的梯度gradient_3,顯然圖的右邊可以看出只在區域性指定的層傳播,這回放心了。
在這裡插入圖片描述

以上是自己的學習結果,如有錯誤請大家不吝賜教。