在做tensorflow模型轉caffe模型時,遇到了幾個坑。其中之一就是caffe的padding方式和tensorflow的padding方式有很大的區別,導致每一層的輸出都無法對齊,讓我一度懷疑轉換模型的代碼是錯的。
卷積操作輸出的形狀計算公式是這樣的:
output_shape = (image_shape-fileter_shape+2*padding)/stride+1
因為padding前面的系數是2,所以在padding時,一般是對稱地補,左/右各padding一列 或者 上下各padding一行。
那么問題來了,如果stride是2,而括號里算出來的值剛好是奇數怎么辦?那就再偷偷摸摸補一列padding或者補一行padding。
於是,caffe和tensorflow的區別就出來了。
caffe偷偷摸摸地把一行0補在上面 或者 把一列0補在左邊,tensorflow正好鏡像對稱,把一行0補在下面或者把一列0補在右邊。這就是導致輸出對齊不了的原因,前面幾層輸出的feature map的中間還能勉強對上,隨着網絡結構的加深,到fc之前已經完全對不上了。
那tensorflow轉caffe豈不是無解?想基於tensorflow訓練模型再轉成caffe投入實際應用中走不通了?
當然不是。只要稍微修改一下源碼就好啦。
https://github.com/petewarden/tensorflow_makefile/blob/master/tensorflow/core/kernels/ops_util.cc
把60行的*pad_top 改成 *pad_bottom,把61行的*pad_bottom改成*pad_top
把65行的*pad_left 改成 *pad_right ,把66行的*pad_right 改成 *pad_left
然后重新編譯一下,就可以讓tensorflow和caffe的padding方式保持一致了。
除了padding方式外,卷積層和fc層的通道順序也需要注意一下:
卷積層的通道順序:在caffe里是[N,C,H,W],而tensorflow是[H,W,C,N]
fc層的通道順序:在caffe 里是[c_in,c_out],而tensorflow是[c_out,c_in]