Caffe源码中Pooling Layer文件分析
Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/vision_layers文件中PoolingLayer类,在最新版caffe中,PoolingLayer类被单独放在了include/caffe/layers/pooling_layer.hpp文件中,这两个文件中PoolingLayer类的内容及实现是完全一致的:
1. include文件:
(1)、<caffe/blob.hpp>:此文件的介绍可以参考:http://blog.csdn.net/fengbingchun/article/details/59106613
(2)、<caffe/layer.hpp>:此文件的介绍可以参考:http://blog.csdn.net/fengbingchun/article/details/60871052
(3)、<caffe/proto/caffe.pb.h>:此文件的介绍可以参考:http://blog.csdn.net/fengbingchun/article/details/55267162
2. 类PoolingLayer:池化层,Layer类的子类
Pooling layer的主要作用是降维,缩小feature map,图像降采样,方法有:
(1)、均值采样:取区域平均值作为降采样值;
(2)、最大值采样:取区域最大值作为降采样值;
(3)、随机采样:取区域内随机一个像素值。
<caffe/layers/pooling_layer.hpp>文件的详细介绍如下:
#ifndef CAFFE_POOLING_LAYER_HPP_
#define CAFFE_POOLING_LAYER_HPP_#include <vector>#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"namespace caffe {
/*** @brief Pools the input image by taking the max, average, etc. within regions.** TODO(dox): thorough documentation for Forward, Backward, and proto params.*/
// 池化层,Layer类的子类,图像降采样,有三种Pooling方法:Max、Avx、Stochastic
template <typename Dtype>
class PoolingLayer : public Layer<Dtype> {public:
// 显示构造函数explicit PoolingLayer(const LayerParameter& param) : Layer<Dtype>(param) {}
// 参数初始化,通过类PoolingParameter获取成员变量值,包括:
// global_pooling_、kernel_h_、kernel_w_、pad_h_、pad_w_、stride_h_、stride_w_virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top);
// 调整top blobs的shape,并有可能会reshape rand_idx_或max_idx_;
// 获取成员变量值,包括:channels_、height_、width_、pooled_height_、pooled_width_virtual void Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top);
// 获得Pooling layer的类型: Poolingvirtual inline const char* type() const { return "Pooling"; }
// 获得Pooling layer所需的bottom blobs的个数: 1virtual inline int ExactNumBottomBlobs() const { return 1; }
// 获得Pooling layer所需的bottom blobs的最少个数: 1virtual inline int MinTopBlobs() const { return 1; }// MAX POOL layers can output an extra top blob for the mask;// others can only output the pooled inputs.
// 获得Pooling layer所需的bottom blobs的最多个数: Max为2,其它(Avg, Stochastic)为1virtual inline int MaxTopBlobs() const {return (this->layer_param_.pooling_param().pool() ==PoolingParameter_PoolMethod_MAX) ? 2 : 1;}protected:
// CPU实现Pooling layer的前向传播,仅有Max和Ave两种方法实现virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top);
// GPU实现Pooling layer的前向传播,Max、Ave、Stochastic三种方法实现virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top);
// CPU实现Pooling layer的反向传播,仅有Max和Ave两种方法实现virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
// GPU实现Pooling layer的反向传播,Max、Ave、Stochastic三种方法实现virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);// Caffe中类的成员变量名都带有后缀"_",这样就容易区分临时变量和类成员变量int kernel_h_, kernel_w_; // 滤波器(卷积核)大小int stride_h_, stride_w_; // 步长大小int pad_h_, pad_w_; // 图像扩充大小int channels_; // 图像通道数int height_, width_; // 图像高、宽
// 池化后图像高、宽
// pooled_height_ = (height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1
// pooled_width_ = (width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1int pooled_height_, pooled_width_;bool global_pooling_; // 是否全区域池化(将整幅图像降采样为1*1)Blob<Dtype> rand_idx_; // 随机采样索引,Pooling方法为STOCHASTIC时用到并会ReshapeBlob<int> max_idx_; // 最大值采样索引,Pooling方法为MAX时用到并会Reshape
};} // namespace caffe#endif // CAFFE_POOLING_LAYER_HPP_
在caffe.proto文件中,有一个message是与pooling layer 相关的,如下: message PoolingParameter { // Pooling层参数类enum PoolMethod { // 枚举类型,Pooling的方法:Max(最大值采样)、AVE(均值采样)、STOCHASTIC(随机采样)MAX = 0;AVE = 1;STOCHASTIC = 2;}optional PoolMethod pool = 1 [default = MAX]; // The pooling method, pooling方法// Pad, kernel size, and stride are all given as a single value for equal// dimensions in height and width or as Y, X pairs.optional uint32 pad = 4 [default = 0]; // The padding size (equal in Y, X),图像扩充大小(添加图像边界的像素大小)optional uint32 pad_h = 9 [default = 0]; // The padding height,图像扩充大小,Yoptional uint32 pad_w = 10 [default = 0]; // The padding width,图像扩充大小,Xoptional uint32 kernel_size = 2; // The kernel size (square),滤波器(卷积核、滑动窗)的大小(高=宽)optional uint32 kernel_h = 5; // The kernel height,滤波器(卷积核、滑动窗)的高optional uint32 kernel_w = 6; // The kernel width,滤波器(卷积核、滑动窗)的宽optional uint32 stride = 3 [default = 1]; // The stride (equal in Y, X),滑动步长(高=宽),卷积核卷积时平移的步幅optional uint32 stride_h = 7; // The stride height,滑动步长,高optional uint32 stride_w = 8; // The stride width,滑动步长,宽enum Engine {DEFAULT = 0;CAFFE = 1;CUDNN = 2;}optional Engine engine = 11 [default = DEFAULT]; //// If global_pooling then it will pool over the size of the bottom by doing// kernel_h = bottom->height and kernel_w = bottom->widthoptional bool global_pooling = 12 [default = false]; // 是否是全区域池化
}
pooling layer的测试代码如下:#include "funset.hpp"
#include <string>
#include <vector>
#include "common.hpp"int test_caffe_layer_pooling()
{caffe::Caffe::set_mode(caffe::Caffe::CPU); // set run caffe mode// set layer parametercaffe::LayerParameter layer_param;layer_param.set_phase(caffe::Phase::TRAIN);// cv::Mat -> caffe::Blobstd::string image_name = "E:/GitCode/Caffe_Test/test_data/images/a.jpg";cv::Mat mat1 = cv::imread(image_name, 1);if (!mat1.data) {fprintf(stderr, "read image fail: %s\n", image_name.c_str());return -1;}mat1.convertTo(mat1, CV_32FC3);std::vector<cv::Mat> mat2;cv::split(mat1, mat2);std::vector<int> mat_reshape{ 1, (int)mat2.size(), mat2[0].rows, mat2[0].cols };caffe::Blob<float> blob;blob.Reshape(mat_reshape);size_t size = mat2[0].rows * mat2[0].cols;float* data = new float[mat2.size() * size];memcpy(data, mat2[0].data, size * sizeof(float));memcpy(data + size, mat2[1].data, size * sizeof(float));memcpy(data + 2 * size, mat2[2].data, size * sizeof(float));blob.set_cpu_data(data);for (int method = 0; method < 2; ++method) {// set pooling parametercaffe::PoolingParameter* pooling_param = layer_param.mutable_pooling_param();if (method == 0) pooling_param->set_pool(caffe::PoolingParameter::MAX);else pooling_param->set_pool(caffe::PoolingParameter::AVE);pooling_param->set_kernel_size(3);pooling_param->set_pad(2);pooling_param->set_stride(2);pooling_param->set_global_pooling(false);std::vector<caffe::Blob<float>*> bottom_blob{ &blob }, top_blob{ &caffe::Blob<float>()/*, &caffe::Blob<float>() */ };// test PoolingLayer functioncaffe::PoolingLayer<float> pooling_layer(layer_param);pooling_layer.SetUp(bottom_blob, top_blob);fprintf(stderr, "top blob info: channels: %d, height: %d, width: %d\n",top_blob[0]->channels(), top_blob[0]->height(), top_blob[0]->width());pooling_layer.Forward(bottom_blob, top_blob);int height = top_blob[0]->height();int width = top_blob[0]->width();const float* p = top_blob[0]->cpu_data();std::vector<cv::Mat> mat3{ cv::Mat(height, width, CV_32FC1, (float*)p),cv::Mat(height, width, CV_32FC1, (float*)(p + height * width)),cv::Mat(height, width, CV_32FC1, (float*)(p + height * width * 2)) };cv::Mat mat4;cv::merge(mat3, mat4);mat4.convertTo(mat4, CV_8UC3);if (method == 0) image_name = "E:/GitCode/Caffe_Test/test_data/images/forward0.jpg";else image_name = "E:/GitCode/Caffe_Test/test_data/images/forward1.jpg";cv::imwrite(image_name, mat4);for (int i = 0; i < bottom_blob[0]->count(); ++i)bottom_blob[0]->mutable_cpu_diff()[i] = bottom_blob[0]->cpu_data()[i];for (int i = 0; i < top_blob[0]->count(); ++i)top_blob[0]->mutable_cpu_diff()[i] = top_blob[0]->cpu_data()[i];std::vector<bool> propagate_down{ true };pooling_layer.Backward(top_blob, propagate_down, bottom_blob);height = bottom_blob[0]->height();width = bottom_blob[0]->width();p = bottom_blob[0]->cpu_diff();std::vector<cv::Mat> mat5{ cv::Mat(height, width, CV_32FC1, (float*)p),cv::Mat(height, width, CV_32FC1, (float*)(p + height * width)),cv::Mat(height, width, CV_32FC1, (float*)(p + height * width * 2)) };cv::Mat mat6;cv::merge(mat5, mat6);mat6.convertTo(mat6, CV_8UC3);if (method == 0) image_name = "E:/GitCode/Caffe_Test/test_data/images/backward0.jpg";else image_name = "E:/GitCode/Caffe_Test/test_data/images/backward1.jpg";cv::imwrite(image_name, mat6);}delete[] data;return 0;
}
执行结果如下图:GitHub:https://github.com/fengbingchun/Caffe_Test
相关文章:

手持终端以物联网的模式
近年来,物联宇手持终端以物联网的模式,开启了信息化的管理模式,迸发了新的自我提升和业务新商机。手持终端是一款智能的电子设备,它的核心功能为用户速带来业务效率的提升,如快递行业,每天的工作量需求大&a…

Linux系统基础-管理之用户、权限管理
Linux用户、权限管理一、如何实现"用户管理"1.什么是用户 "User" : 是一个使用者获取系统资源的凭证,是权限的结合,为了识别界定每一个用户所能访问的资源及其服务的。只是一种凭证。会有一个表示数字,计算机会首…
Ubuntu14.04 LTS中安装Ruby 2.4源码操作步骤
(1)、查看是否已安装ruby,执行命令,如下图,可见机子上还没有安装ruby,即使通过apt-get install命令安装也只能安装1.8版本;(2)、从 http://www.ruby-lang.org/en/downloads/ 下载最新稳定版2.4即ruby-2.4.0.tar.gz&a…

图森未来完成2.15亿美元D轮融资,将拓展无人驾驶运输服务
AI科技大本营消息,9月17日,图森未来宣布获得1.2亿美元的D2轮投资,并完成总额为2.15亿美元的D轮融资。D2轮的投资方除了此前已宣布的UPS外,还包括新的投资方鼎晖资本,以及一级供应商万都(Mando Corporation&…

中国互联网公司开源项目调研报告
近年来,开源技术得到越来越多的重视,微软收购GitHub、IBM收购红帽,都表明了开源的价值。国内公司也越来越多的参与开源,加入开源基金会/贡献开源项目。但是,它们到底做得如何呢?为此InfoQ统计了国内在GitHu…

ReSharper 配置及用法
1:安装后,Resharper会用他自己的英文智能提示,替换掉 vs2010的智能提示,所以我们要换回到vs2010的智能提示 2:快捷键。是使用vs2010的快捷键还是使用 Resharper的快捷键呢?我是使用re的快捷键 3: Resharper安装后,会做…
Ubuntu14.04 LTS中升级gcc/g++版本到4.9.4的操作步骤
Ubuntu14.04 LTS中默认的gcc/g版本为4.8.4,如下图,在C11中增加了对正则表达式的支持,但是好像到gcc/g 4.9.2版本才会对正则表达式能很好的支持,这里介绍下Ubuntu14.04 LTS升级gcc/g版本到4.9.4的操作步骤: 1࿰…

华为全球最快AI训练集群Atlas 900诞生
作者 | 胡巍巍来源 | CSDN(ID:CSDNnews)你,和计算有什么关系?早上,你打开手机App,查看天气预报,和计算有关;中午,你打开支付宝人脸支付,买了份宫保…

rabbitmq可靠发送的自动重试机制 --转
原贴地址 https://www.jianshu.com/p/6579e48d18ae https://www.jianshu.com/p/4112d78a8753 git项目代码地址 https://github.com/littlersmall/rabbitmq-access 转载于:https://www.cnblogs.com/hmpcly/p/10641688.html

在Linux下如何安装配置SVN服务
2019独角兽企业重金招聘Python工程师标准>>> Linux下在阿里云上架一个svn centos上安装:yum install subversion 安装成功 键入命令 svnserve --version 有版本信息则进行下一步 1、新建版本库目录 mkdir -p /opt/svndata/repos 2、设置此目录为…

201671030129 周婷 《英文文本统计分析》结对项目报告
项目内容这个作业属于哪个课程软件工程这个作业的要求在哪里软件工程结对项目课程学习目标熟悉软件开发整体流程及结对编程,提升自身能力本次作业在哪个具体方面帮助我们实现目标体验组队编程,体验一个完整的工程任务一: 作业所点评博客GetHu…

C++/C++11中std::string用法汇总
C/C11中std::string是个模板类,它是一个标准库。使用string类型必须首先包含<string>头文件。作为标准库的一部分,string定义在命名空间std中。std::string是C中的字符串。字符串对象是一种特殊类型的容器,专门设计来操作字符序列。str…

你在付费听《说好不哭》,我在这里免费看直播还送书 | CSDN新书发布会
周一的时候,我拖着疲惫的身体回到家中,躺倒床上刷刷朋友圈,什么?周杰伦出新歌了?朋友圈都是在分享周杰伦的新歌《说好不哭》,作为周杰伦的粉丝,我赶紧打开手机上的QQ音乐,准备去听&a…

解决Mysql:unrecognized service错误的方法(CentOS)附:修改用户名密码
2019独角兽企业重金招聘Python工程师标准>>> service mysql start出错,mysql启动不了,解决mysql: unrecognized service错误的方法如下: [rootctohome.com ~]# service mysql startmysql: unrecognized service [rootctohome.co…
Caffe源码中Net文件分析
Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/net.hpp文件的内容:1. include文件:(1)、<caffe/blob.hpp>:此文件的介绍可以参考:http://blo…

满满干货的硬核技术沙龙,免费看直播还送书 | CSDN新书发布会
周一的时候,我拖着疲惫的身体回到家中,躺倒床上刷刷朋友圈,什么,周杰伦出新歌了?朋友圈都是在分享周杰伦的新歌《说好的不哭》,作为周杰伦的粉丝,我赶紧打开我手机上的QQ音乐,准备去…

【重磅上线】思维导图工具XMind:ZEN基础问题详解合集
XMind是XMind Ltd公司旗下一款出色的思维导图和头脑风暴软件。黑暗的UI设计、独特的ZEN模式、丰富的风格和主题、多分支的颜色等等功能会让你的工作更加便捷与高效。在视觉感官上也会给你带来最佳的体验感。 对于初学者来说,肯定会遇到各种各样的问题,有…

Linux内置的审计跟踪工具:last命令
这个命令是last。它对于追踪非常有用。让我们来看一下last可以为你做些什么。last命令的功能是什么last显示的是自/var/log/wtmp文件创建起所有登录(和登出)的用户。这个文件是二进制文件,它不能被文本编辑器浏览,比如vi、Joe或者其他软件。这是非常有用…

C++/C++11中std::set用法汇总
一个容器就是一些特定类型对象的集合。顺序容器(sequential container)为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。与之相对的,有序和无序关联容器,则根据关键字的值来存储元…

值得收藏!基于激光雷达数据的深度学习目标检测方法大合集(下)
作者 | 黄浴来源 | 转载自知乎专栏自动驾驶的挑战和发展【导读】在近日发布的《值得收藏!基于激光雷达数据的深度学习目标检测方法大合集(上)》一文中,作者介绍了一部分各大公司和机构基于激光雷达的目标检测所做的工作࿰…

java B2B2C源码电子商务平台 -commonservice-config配置服务搭建
2019独角兽企业重金招聘Python工程师标准>>> Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring Environment和PropertySource抽象…

Topshelf:一款非常好用的 Windows 服务开发框架
背景 多数系统都会涉及到“后台服务”的开发,一般是为了调度一些自动执行的任务或从队列中消费一些消息,开发 windows service 有一点不爽的是:调试麻烦,当然你还需要知道 windows service 相关的一些开发知识(也不难&…

C++中nothrow的介绍及使用
在C中,使用malloc等分配内存的函数时,一定要检查其返回值是否为”空指针”,并以此作为检查内存操作是否成功的依据,这种Test-for-NULL代码形式是一种良好的编程习惯,也是编写可靠程序所必需的。在C中new在申请内存失败…

你猜猜typeof (typeof 1) 会返回什么值(类型)?!
typeof typeof操作符返回一个字符串,表示未经计算的操作数的类型。 语法: var num a; console.log(typeof (num)); 或console.log(typeof num) 复制代码typeof 可以返回的类型为:number、string、boolean、undefined、null、object、functi…

阿里云智能运维的自动化三剑客
整理 | 王银出品 | AI科技大本营(ID:rgznai100)近日,2019 AI开发者大会在北京举行。会上,近百位中美顶尖AI专家、知名企业代表以及千余名AI开发者进行技术解读和产业论证。而在AIDevOps论坛上,阿里巴巴高级技术专家滕圣…

Sublime Text2.0.2注册码
直接输入注册码就可以了 ----- BEGIN LICENSE ----- Andrew Weber Single User License EA7E-855605 813A03DD 5E4AD9E6 6C0EEB94 BC99798F 942194A6 02396E98 E62C9979 4BB979FE 91424C9D A45400BF F6747D88 2FB88078 90F5CC94 1CDC92DC 8457107A F151657B 1D22E383 A997F016 …
Caffe源码中Solver文件分析
Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/solver.hpp文件的内容:1. include文件: <caffe/solver.hpp>:此文件的介绍可以参考: http://b…

百度大脑金秋九月CV盛典,人脸识别新产品及伙伴计划发布会压轴开启
提起人脸识别你最先想到的是什么?是告别排队,刷脸就能支付的超市;还是告别黄牛,刷脸就能自助挂号建档的医院?其实,“刷脸”的时代早已到来,并且人脸识别技术的发展已经超越你的想象,…

BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 序
BIML 101 - BIML 快速入门教程 做大数据的项目,最花时间的就是数据清洗。 没有一个相对可靠的数据,数据分析就是无木之舟,无水之源。 如果你已经进了ETL这个坑,而且预算有限,并且有大量的活要做; 时间紧&am…

ADO数据库操作
void CSjtestDlg::OnBnClickedButtonAdd() {// TODO: 在此添加控件通知处理程序代码this->ShowWindow(SW_HIDE);DigAdd dig ;dig.DoModal() ;this->ShowWindow(SW_SHOW);m_Grid.DeleteAllItems() ;ADOConn m_Adoconn ;m_Adoconn.OnInitADOConn() ;CString sql ;sql.Forma…