net_surgery中如何将全连接层转换成卷积层

来源:互联网 发布:java ee圣思园教程 编辑:程序博客网 时间:2024/05/21 19:37

最近在读Fully convolutional networks for semantic segmentation这篇论文,看到里面很多地方都感觉有些不太明白,只好一点一点来刨了。首先这个net_surgery的例子是非常重要的一个启示,关于如何把一个classifier转换成fully convolutional network

 

原始输入层定义:

https://github.com/BVLC/caffe/blob/master/models/bvlc_reference_caffenet/deploy.prototxt

Name:Alex(假设取名为Alex)

Input_shape{

Dim:10

Dim:3

Dim:227

Dim:227

}

layer {

name: "fc6"

type: "InnerProduct"

bottom: "pool5"

top: "fc6"

inner_product_param {

num_output: 4096

}

}

 

 

调整后的输入定义:

https://github.com/BVLC/caffe/blob/master/examples/net_surgery/bvlc_caffenet_full_conv.prototxt

Name:FCN(假设取名为FCN)

Input_shape{

Dim:10

Dim:3

Dim:451

Dim:451

}

layer {

name: "fc6-conv"

type: "Convolution"

bottom: "pool5"

top: "fc6-conv"

convolution_param {

num_output: 4096

kernel_size: 6

}

}

 

 

最重要的地方就是pool5后第一个全连接层的修改,花了些时间进行分析才算看明白了,记录下来怕后面看到又忘了。

 

对网络每一层的数据(blobs)以及参数(params)进行分析,可以推出,

在1x3x227x227的输入的前提下,Alex的pool5的数据(blobs)大小(shape)为1x256x6x6,这个时候下一层是全连接层fc6,它的num_output为4096,这时候fc6层的参数(params)大小(shape)为:4096x9216(1*256*6*6=9216)

 

然后对网络的输入进行修改,将输入放大到1x3x451x451,保留其他的参数不变,这个时候再次进行推算,可以得出FCN的pool5的数据(blobs)大小(shape)为1x256x13x13,然后将下一层的全连接层fc6修改为卷积层fc6-conv,num_output为4096,kernel_size为6,此时该层的参数(params)大小(shape)为4096x256x6x6,换算一下,刚好为4096x9216(256*6*6=9216)。

 

至此,可以将3x227x227输入情况下Alex的fc6层的参数(4096x9216)赋值给3x451x451输入情况下FCN的fc6-conv层(4096x9216)


一开始我一直以为是在相同输入大小的情况下来进行转换,使用451x451进行分析,得出pool5层后的fc层参数大小是4096x256x13x13,也就是4096x43264,然而models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel里的参数是(4096x9216),所以是没法赋值过来的。


如果不调整输入大小,直接将fc6层改为卷积层的话是可以做到参数相大小相匹配的,这个时候pool5为1x256x6x6,然后fc6-conv设定为num_output=4096,kernel_size:6,同样可以达到fc6-conv层的参数为4096x256x6x6=4096x9216的效果,但是注意观察进一步fc6-conv层之后的数据大小会发现,生成的feature_map边长变为(6-6)/1+1=1,只剩下了1x4096x1x1了,当然这样子做也没有什么问题,只是这1x1的的feature_map没法看到heat map的效果了啊

0 0