Caffe中Layer注册机制
来源:互联网 发布:腾讯云域名建站教程 编辑:程序博客网 时间:2024/06/05 10:49
Caffe内部维护一个注册表用于查找特定Layer对应的工厂函数,(Layer Factory的设计用到了设计模式里的工厂模式)。Caffe的Layer注册表是一组键值对(key, value)( LayerRegistry里用map数据结构维护一个CreatorRegistry list, 保存各个Layer的creator的函数句柄),key为Layer的类型(Layer类名去掉后面的”Layer”字符串),value为其对应的工厂函数(creator的函数句柄),注册表类型为CreatorRegistry,实际类型为std::map。可以通过Registry 函数获取注册表的全局单例。而注册的过程就是一个map操作。
Caffe是通过宏定义的方式注册各种Layer,在编译阶段自动执行宏替换就注册了所有的Layer. 每一个Layer type只允许注册一次。使用两组宏来控制Layer的注册.:
#define REGISTER_LAYER_CREATOR(type, creator) \
LayerRegisterer<
float
> g_creator_f_##type(#type, creator<
float
>); \
LayerRegisterer<
double
> g_creator_d_##type(#type, creator<
double
>) \
#define REGISTER_LAYER_CLASS(type) \
template <typename dtype=
""
> \
shared_ptr<layer<dtype> > Creator_##type##Layer(
const
LayerParameter& param) \
{ \
return
shared_ptr<layer<dtype> >(
new
type##Layer<dtype>(param)); \
} \
REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)</dtype></layer<dtype></layer<dtype></typename></
double
></
double
></
float
></
float
>
REGISTER_LAYER_CLASS宏可以实现将指定Layer注册到全局注册表中,首先定义一个工厂函数用来产生Layer对象,然后调用REGISTER_LAYER_CREATOR将工厂函数和Layer的类型名进行注册,支持两种Layer的数据类型,float和double。两个变量一个对应float,一个对应double,这两个变量的初始化,也就是它们的构造函数实际上完成Layer的注册动作。REGISTER_LAYER_CLASS实际上是为每一个Layer创建一个creator函数.
LayerRegisterer对象初始化时(会调用LayerRegisterer类构造函数)实际上又是调用LayerRegistry类的静态方法 AddCreator函数。
以下是对Caffe code中layer_factory.hpp文件的注释:
#ifndef CAFFE_LAYER_FACTORY_H_
#define CAFFE_LAYER_FACTORY_H_
#include<map>
#include <string>
#include
"caffe/common.hpp"
#include
"caffe/proto/caffe.pb.h"
namespace caffe {
template <typename dtype=
""
>
class
Layer;
// LayerRegistry:注册类,将每一个Layer的type(std::string)和对应的creator(函数指针)存放到一个map中
template <typename dtype=
""
>
class
LayerRegistry {
public
:
// LayerRegistry里用map数据结构, 维护一个CreatorRegistry list, 保存各个layer的creator的函数句柄
typedef shared_ptr<layer<dtype> > (*Creator)(
const
LayerParameter&);
// 函数指针,返回Layer<dtype>类型的指针
typedef std::map<string, creator=
""
> CreatorRegistry;
// 获取注册表,内部注册表,静态函数,仅第一次调用时会new,其它直接return
static
CreatorRegistry& Registry() {
// 只创建一个map实例
// 全局静态变量(map实例)
static
CreatorRegistry* g_registry_ =
new
CreatorRegistry();
return
*g_registry_;
}
// Adds a creator.
// AddCreator函数用来向Registry列表中添加一组<type, creator="">
// 向map中加入一个映射
static
void
AddCreator(
const
string& type, Creator creator) {
CreatorRegistry& registry = Registry();
CHECK_EQ(registry.count(type),
0
)
<<
"Layer type "
<< type <<
" already registered."
;
registry[type] = creator;
}
// Get a layer using a LayerParameter.
// 在net.cpp中会被调用,在初始化整个网络的时候会根据参数文件中的层的类型去创建该层的实例
static
shared_ptr<layer<dtype> > CreateLayer(
const
LayerParameter& param) {
if
(Caffe::root_solver()) {
LOG(INFO) <<
"Creating layer "
<< param.name();
}
const
string& type = param.type();
// 从LayerParameter中获得字符串type
CreatorRegistry& registry = Registry();
// 获取注册表指针
// 验证是否查找到给定type的creator
CHECK_EQ(registry.count(type),
1
) <<
"Unknown layer type: "
<< type
<<
" (known types: "
<< LayerTypeList() <<
")"
;
return
registry[type](param);
// 根据layer name, 调用相应creator函数
}
private
:
// Layer registry should never be instantiated - everything is done with its
// static variables.
// 禁止实例化
LayerRegistry() {}
// 返回layer type
static
string LayerTypeList() {
CreatorRegistry& registry = Registry();
// 获取注册表指针
string layer_types;
// 遍历注册表
for
(typename CreatorRegistry::iterator iter = registry.begin();
iter != registry.end(); ++iter) {
if
(iter != registry.begin()) {
layer_types +=
", "
;
}
layer_types += iter->first;
}
return
layer_types;
}
};
// LayerRegisterer:Layer注册器,供后面的宏使用
template <typename dtype=
""
>
class
LayerRegisterer {
public
:
// 向LayerRegistry的registry list中, 添加一个layer的creator
LayerRegisterer(
const
string& type,
shared_ptr<layer<dtype> > (*creator)(
const
LayerParameter&)) {
// LOG(INFO) << "Registering layer type: " << type;
LayerRegistry<dtype>::AddCreator(type, creator);
}
};
// 通过宏定义注册各种Layer
// 将创建layer对象的函数指针加入map
#define REGISTER_LAYER_CREATOR(type, creator) \
LayerRegisterer<
float
> g_creator_f_##type(#type, creator<
float
>); \
LayerRegisterer<
double
> g_creator_d_##type(#type, creator<
double
>) \
#define REGISTER_LAYER_CLASS(type) \
template <typename dtype=
""
> \
shared_ptr<layer<dtype> > Creator_##type##Layer(
const
LayerParameter& param) \
{ \
return
shared_ptr<layer<dtype> >(
new
type##Layer<dtype>(param)); \
} \
REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)
}
// namespace caffe
#endif
// CAFFE_LAYER_FACTORY_H_
</dtype></layer<dtype></layer<dtype></typename></
double
></
double
></
float
></
float
></dtype></layer<dtype></typename></layer<dtype></type,></string,></dtype></layer<dtype></typename></typename></string></map></dtype*></typename></dtype></typename></dtype>
- Caffe中Layer注册机制
- Caffe中Layer注册机制
- caffe中layer层介绍
- caffe 中 BatchNorm layer设定
- Caffe中新建Layer--改写Faster-RCNN的proposal layer
- Caffe中新建Layer--改写Faster-RCNN的proposal layer
- caffe layer
- caffe layer
- caffe中增加自己的layer
- caffe中特殊的layer解释
- 在Caffe中使用Python Layer
- 从caffe中新增layer(cpp版本)
- Caffe中Layer参数的初始化方式
- 在caffe中添加自定义的layer
- 在caffe中添加自定义的layer
- Caffe源码中layer文件分析
- Caffe源码中Pooling Layer文件分析
- Caffe源码中Pooling Layer文件分析
- android中设置TextView的值\n不起作用
- maven 常用命令
- autolayout 入门(二)
- 数学(3) 各种数学分布,高斯,伯努利,二项,多项,泊松,指数,Beta,Dirichlet
- Brekeke SIP Server搭建
- Caffe中Layer注册机制
- Unity3d 滑动事件--向上、向下、向左、向右(PC好用但是手机滑动不是很理想)
- IDEA没找到新建.java文件解决
- React-Router4x 路由
- openTSDB安装步骤
- spring data mongodb高级查询语句的使用(网上基本没资料)
- 线性代数的本质
- Long-term Recurrent Convolutional Networks for Visual Recognition and Description
- 测试用例的设计