tf.nn.conv2d() / tf.nn.depthwise_conv2d() 和 Batchsize效益
1. 卷積函數tf.nn.conv2d()?
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True, data_format='NHWC',dilations=[1, 1, 1, 1], name=None)對于給定的4-D張量輸入,利用給定的filter執行2-D卷積運算。
- input : [batch, in_height, in_width, in_channels]
- filter : [filter_height, filter_width, in_channels, out_channels]
- padding: "SAME" / "VALID"
- data_format: Defaults to "NHWC".
算法執行過程:
1.filter壓平成2D矩陣,[filter_height * filter_width * in_channels, output_channels]
2.input中提取圖像塊, [batch, out_height, out_width, filter_height * filter_width * in_channels]
3.對于每一個圖像塊,右乘濾波器矩陣和圖像塊向量。
實例:
? ??
左邊代表input:[BatchSize, H, W, in_Channels]=[24,255,255,3];
右側代表filter:Batch_size*[Filter_H, Filter_W, in_Channels, out_Channels]=[127,127,3,1];?
所以,程序循環24次,即可以完成對一個BatchSize=24的卷積/相關操作,輸出結果為:
這個過程是比較復雜的,Tensorflow中提供了更好的深度卷積deep_wise_conv2d()函數可以執行類似的功能。
2.?深度卷積tf.nn.depthwise_conv2d()
深度卷積最早出現在Google的Xception系列的文章,具體的算法實現可以參考xf_mao博主的這邊文章:https://blog.csdn.net/mao_xiao_feng/article/details/78003476。這里我僅僅應用該函數實現了BatchSize圖像的對應(Channel-Wise)卷積工作。
tf.nn.depthwise_conv2d(input, filter, strides, padding, rate=None, name=None, data_format=None)給定4D的輸入張量input=[batch, in_height, in_width, in_channels],濾波器filter=[filter_height,?filter_width, in_channels, channel_multiplier]。 該濾波器包括深度為1的in_channels個卷積濾波器。depthwise_conv2d()對每個輸入通道(從1到channel_multiplier通道)施加一個不同的filter。然后將輸出結果concatenate到一起。輸出的通道數=[in_channels * channel_multiplier]。
對照我們的任務。input:[BatchSize, H, W, in_Channels]=[24,255,255,3]; filter:Batch_size*[Filter_H, Filter_W, in_Channels, out_Channels] = [127,127,3,1]; 如果想實現對應圖層采用對應核圖像進行卷積[Channel-Wise],我們需要將input和filter的shape進行調整。具體為 input=[1, H, W,?BatchSize*in_Channels]; filter=[Filter_H, Filter_W, Batch_Size*in_Channels,1].
核心代碼:
Bz, Hz, Wz, Cz = z.shape Bx, Hx, Wx, Cx = x.shape; zf = tf.reshape(zf, (Hz, Wz, Bz*Cz, 1)) xf = tf.reshape(xf, (1, Hx, Wx, Bx*Cx)) print("zf= ", zf.get_shape().as_list(), " ", "xf=", xf.get_shape().as_list())res_ = tf.nn.depthwise_conv2d(xf, zf, strides=[1,1,1,1], padding='VALID') res_ = tf.concat(tf.split(res_, 24, axis=3), axis=0) res_ = tf.reduce_mean(res_, axis=3, keep_dims = False) print("the results of deep_wise_conv2d:", res_.get_shape().as_list())輸出結果和循環tf.nn.conv2d()的結果一致。
3. 關于mini-batch的作用
3.1 為什么需要有 Batch_Size 這個參數??
- 合理的范圍,越大的 batch size 使下降方向越準確,震蕩越小
- batch size 過大,各batch梯度修正值可能消失,出現取得局部最優的情況
- bath size 過小,引入的隨機性更大,難以達到收斂,極少數情況下可能會效果變好
Batch的選擇決定了優化函數梯度的下降方向。如果數據集比較小,完全可以采用全數據集 ( Full Batch Learning )的形式,這樣做至少有 2 個好處:
- 由全數據集確定的方向能夠更好地代表樣本總體,從而更準確地朝向極值所在的方向
- 由于不同權重的梯度值差別巨大,因此選取一個全局的學習率很困難。Full Batch Learning 可以使用Rprop只基于梯度符號并且針對性單獨更新各權值。
對于類似于ImageNet等超大數據集,以上 2 個好處又變成了 2 個壞處:
- 隨著數據集的海量增長和內存限制,一次性載入所有的數據進來變得越來越不可行
- 以 Rprop 方式迭代,由于各個 Batch 間的采樣差異,各次梯度修正值相互抵消,這才有了后來RMSProp的妥協
如果每次只訓練一個樣本,即 Batch_Size = 1。這就是在線學習(Online Learning)。線性神經元在均方誤差代價函數的錯誤面是一個拋物面,橫截面是橢圓。對于多層神經元、非線性網絡,在局部依然近似是拋物面。使用在線學習,每次修正方向以各自樣本的梯度方向修正,橫沖直撞各自為政,難以達到收斂。如上圖所示。
3.2 Mini-Batch 可以解決什么問題?
如果數據集足夠充分,那么用一半(甚至少得多)的數據訓練算出來的梯度與用全部數據訓練出來的梯度是幾乎一樣的。這就是批梯度下降法(Mini-batches Learning)。
在合理范圍內,增大 Batch_Size 有何好處?內存利用率提高了,大矩陣乘法的并行化效率提高。?跑完一次 epoch(全數據集)所需的迭代次數減少,對于相同數據量的處理速度進一步加快。?在一定范圍內,一般來說 Batch_Size 越大,其確定的下降方向越準,引起訓練震蕩越小。 盲目增大 Batch_Size 有何壞處?內存利用率提高了,但是內存容量可能撐不住了。?跑完一次 epoch(全數據集)所需的迭代次數減少,要想達到相同的精度,其所花費的時間大大增加了,從而對參數的修正也就顯得更加緩慢。?
3.3?調節 Batch_Size 對訓練效果影響到底如何??
Batch_Size 增大到一定程度,其確定的下降方向已經基本不再變化。 調節 Batch_Size 對訓練效果影響到底如何??這里展示了在 MNIST 數據集上的效果。如圖所示:
算法架構:
?
Batch_Size對訓練結果的影響:
結論:
- Batch_Size 太小,算法在 200 epoches 內不收斂。?
- 隨著 Batch_Size 增大,處理相同數據量的速度越快。?
- 隨著 Batch_Size 增大,達到相同精度所需要的 epoch 數量越來越多。?
- 由于上述兩種因素的矛盾, Batch_Size 增大到某個時候,達到時間上的最優。?由于最終收斂精度會陷入不同的局部極值,因此 Batch_Size 增大到某些時候,達到最終收斂精度上的最優。
總結
以上是生活随笔為你收集整理的tf.nn.conv2d() / tf.nn.depthwise_conv2d() 和 Batchsize效益的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 林华达视角-概率图模型与计算机视觉
- 下一篇: VC++环境下利用管道和线程实现进程间通