SPPNet论文笔记和caffe实现说明
来源:互联网 发布:网络出版服务许可单位 编辑:程序博客网 时间:2024/06/08 11:16
SPPNet:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
pdf:https://arxiv.org/pdf/1406.4729v2.pdf
论文主要贡献
之前的CNN网络的输入的size都是固定,为什么要这样呢,是因为最后fc层的输入需要是一个固定的尺寸,例如AlexNet的fc6的输入就是需要固定,但是如果各种图片都通过crop或者warp来resize成一样,就会有下面的情况发生:
crop导致看不全,warp导致变形
而该论文通过在conv和fc层之间引入Spatial Pyramid Pooling,可以接受不同的size输入,在SPP层后面产生固定size的输出送入fc层,而且SPP相较于之前的Pooling来说,通过设置不同level的spatial bins来达到Mutil-level,而且由于输入的size是多变的,所以它可以从各个不同的scales来pool feature,有更强的鲁棒性。
随手画了下大致的网络示意图 以AlexNet为例(有点难看 轻喷)
实验效果
- 直接把原来的Pooling换掉,其他不变输入还是fixed的,这样做为了控制变量,直接看SPP的效果,发现也有1个点的提升
- 输入不同size的图片进行训练,比起第一个实验,又有了0.5点的提升吧(注意此处训练是用了不同size,但是测试还是同一size)
- 做了组对比实验,每张图片令min(w,h)= 256,然后保持比例放缩到这个大小,送入网络。另一个是取刚刚放缩好的图片中间部位的224x224送入网络,实验结果发现full image比crop image高0.5个点,这也说明了输入全图更好。
- 测试时取很多view,比如中心、四个角、四个边的中间以及他们的翻转这18个view,然后全图计算一次conv5的feature map就行,通过映射看这18个view在feature map都是哪块,然后把这18块送入SPP后进入fc,发现也是有提升的
caffe实现
#caffe.proto中的关于SPP层参数的定义message SPPParameter { enum PoolMethod { MAX = 0; AVE = 1; STOCHASTIC = 2; } optional uint32 pyramid_height = 1; optional PoolMethod pool = 2 [default = MAX]; // The pooling method enum Engine { DEFAULT = 0; CAFFE = 1; CUDNN = 2; } optional Engine engine = 6 [default = DEFAULT];}
# AlexNet trainval.prototxt....layer { name: "relu5" type: "ReLU" bottom: "conv5" top: "conv5"}#之前的Pooling层#layer {# name: "pool5"# type: "Pooling"# bottom: "conv5"# top: "pool5"# pooling_param {# pool: MAX# kernel_size: 3# stride: 2# }#}layer { name: "spatial_pyramid_pooling" type: "SPP" bottom: "conv5" top: "pool5" spp_param { pool: MAX pyramid_height: 2 # SPP的level的数量 }}layer { name: "fc6" type: "InnerProduct" bottom: "pool5" top: "fc6" ...}...
void SPPLayer<Dtype>::LayerSetUp(......){ for (int i = 0; i < pyramid_height_; i++) { ...... // pooling layer setup LayerParameter pooling_param = GetPoolingParam( i, bottom_h_, bottom_w_, spp_param); }}// 关于pyramid_height// pyramid_level是0到pyramid_height-1// 暂时是这样理解这段代码的,但是没有找到stride在哪???// pool 1x1 2x2 4x4 8x8 ... pow(2, pyramid_height-1)xpow(2, pyramid_height-1)LayerParameter SPPLayer<Dtype>::GetPoolingParam(const int pyramid_level,......){ ...... LayerParameter pooling_param; int num_bins = pow(2, pyramid_level); // find padding and kernel size so that the pooling is // performed across the entire image int kernel_h = ceil(bottom_h / static_cast<double>(num_bins)); // remainder_h is the min number of pixels that need to be padded before // entire image height is pooled over with the chosen kernel dimension int remainder_h = kernel_h * num_bins - bottom_h; // pooling layer pads (2 * pad_h) pixels on the top and bottom of the // image. int pad_h = (remainder_h + 1) / 2; // similar logic for width int kernel_w = ceil(bottom_w / static_cast<double>(num_bins)); int remainder_w = kernel_w * num_bins - bottom_w; int pad_w = (remainder_w + 1) / 2; pooling_param.mutable_pooling_param()->set_pad_h(pad_h); pooling_param.mutable_pooling_param()->set_pad_w(pad_w); pooling_param.mutable_pooling_param()->set_kernel_h(kernel_h); pooling_param.mutable_pooling_param()->set_kernel_w(kernel_w); pooling_param.mutable_pooling_param()->set_stride_h(kernel_h); pooling_param.mutable_pooling_param()->set_stride_w(kernel_w); ...}
注意事项
直接复现实验1是很容易,就是输入还是固定的,只是Pooling换掉,只有一点注意,pyramid_height的设置如果过大(图片的size很小)会报的错误:Check failed: pad_h_ < kernel_h_,因为size太小了,到conv5时feature map太小了,而caffe这里限制pad_h_ < kernel_h_
复现实验2就有些许问题,如果你的batch不是1的话,因为load_batch是多线程同步的,caffe会默认用这个batch里的第一个数据的chanel height width作为输出的格式,所以会报类似的错误:Check failed: height <= datum_height (80(第一个数据的height) vs. 64(后续数据的height)) ,暂时如果不修改部分源码的话,只有先把trainval.prototxt和test.prototxt的batchsize都设为1吧,实验2仍需要注意实验1的问题
- 实验3,4自行根据前两条注意事项进行操作
- SPPNet论文笔记和caffe实现说明
- SPPnet论文总结
- SPPnet论文总结
- SPPNet论文总结
- SPPnet论文总结
- SPPNet-阅读理解-笔记
- SPPNET 和RCNN
- caffe学习笔记21-VggNet论文笔记
- caffe学习笔记23-GoogLeNet论文笔记
- caffe学习笔记27-ResNet论文笔记
- 【深度学习论文待完成】:SPPNet
- SPPNet
- SPPnet
- sppnet
- sppnet
- Learning Deep Features for Discriminative Localization论文笔记以及Caffe实现
- Deep Learning论文笔记:CNN卷积神经网络推导和实现
- Object Detection--RCNN,SPPNet,Fast RCNN,FasterRCNN论文详解
- [Leetcode]384. Shuffle an Array
- 前端单元测试工具-karma
- 线性代数复习分析(矩阵代数运算)
- checkbox 复选框只选择一个
- Android、Java错误集
- SPPNet论文笔记和caffe实现说明
- OBJ文件格式详解
- Android小知识
- 如何从一个svn地址切换到另一个地址
- Android开发之APP直播简介
- [Leetcode]357. Count Numbers with Unique Digits
- BZOJ2096: [Poi2010]Pilot
- vim常用命令(目前我所用到的欢迎大家填补)
- springboot(四) 用mybatis-generator自动生成bean和dao