maxpooling的计算公式是:
h_o = (h_i + 2 * pad - kernal_size) / stride + 1
w_o = (w_i + 2 * pad - kernal_size) / stride + 1
对于除不尽(输入h_i或卷积核为单数)的情况,pytorch和caffe的处理方式不同,导致最后转出来的结果对不上,出现caffe比pytorch的尺寸大1
在pytorch的maxpool中,有ceil_mode的设置
ceil_mode: when True, will use ceil instead of floor to compute the output shape
如果不设置的话默认使用是floor模式,而caffe只有ceil模式,因此转过来就出问题。
像我的情况是输入240,pytorch设置kernel_size=3, stride=2, padding=1,ceil_mode默认False,输出120,此时caffe同设置下输出121。
解决办法:
若pytorch模型训练之前就发现了这个问题,把pytorch的pooling设置为kernel_size=3, stride=2, padding=0,ceil_mode=True,该方式也是一般caffe的设置方式(如alexnet)
若pytorch模型已经训练完,不做finetune转到caffe,只能手动修改了,注意不能直接把padding设置为0,不能直接把padding设置为0,不能直接把padding设置为0,除非后续还做finetune。因为出来的值会不同。
最蠢的办法是在后面跟一个slice层,把h和w的最后一层切掉就可以了。
耍小聪明的办法是我把caffe的pooling层的实现也改成floor模式,改动比较简单,也方便实现,就不放了。
举个例子,直观点看:
对于一个这样的tensor:
tensor([[[[0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1.],
[2., 2., 2., 2., 2., 2.],
[3., 3., 3., 3., 3., 3.],
[4., 4., 4., 4., 4., 4.],
[5., 5., 5., 5., 5., 5.]]]])
pytorch的结果(floor)是:
tensor([[[[1., 1., 1.],
[3., 3., 3.],
[5., 5., 5.]]]])
caffe的结果(ceiling)是:
tensor([[[[1., 1., 1., 1.],
[3., 3., 3., 3.],
[5., 5., 5., 5.],
[5., 5., 5., 5.]]]])
如果直接将caffe的padding设为0:
tensor([[[[2., 2., 2.],
[4., 4., 4.],
[5., 5., 5.]]]])