关于Layers的一些概述
- Layers是Caffe中最复杂、承担的工作量最大的一类组件。从数据的载入(Input layer), 卷积的计算(Conv layer),对feature map的下采样(pooling layer),网络非线性的引入(ReLU layer,Sigmoid layer)还是概率(softmax layer)与损失的计算(softmax loss layer),上述种种复杂的工作都由Layers来完成。
- Layers是Caffe中基本的计算单元,除了输入层,其余的层可以看作接受一个输入,经过计算后给出输出的函数。
如上图所示,conv layer接受bottom blob作为输入,经过卷积运算后给出输出top blob。 - 每个层定义三个重要的函数——setup(), forward()和backward()。
setup()负责按照网络定义对layer进行初始化,forward()负责进行前向传播,backward负责进行后向传播,所谓后向传播就是将在layer top的梯度传播到layer的bottom,如果layer本身有可学习的参数(例如卷积层、全连接层),那么还要计算并保存相对于参数的梯度以进行后续的梯度下降。 - 所有的layers都有派生自一个共同的基类——layer
layer作为基类,定义了所有类共有的接口——setup, forward和backward。派生类通过重载基类中的若干虚函数来实现specific的功能。
如何添加自己的layer?
关于如何添加自己的layer,这边博文叙述十分详细,我不再赘述。
Making a Caffe Layer
一个layer是如何被创建的?
Caffe中使用简单工厂模式来创建不同的layer。
- 具体负责这个任务的是类LayerRegistry,这个类使用static变量g_registry_来记录layer的名称与其对应的创建layer的函数。
- 创建layer的函数既可以是layer本身的构造函数,也可以是另外指定的函数,只要这个函数返回的是指向类实例的指针就可以,可以参见layer_factory.cpp中创建conv layer实例的函数代码
- g_registry_的类型是
std::map<string, Creator>
,Creator是指向函数的指针,具体为typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&)
- 使用宏
REGISTER_LAYER_CLASS(LayerName)
直接使用layer的构造函数作为创建layer的函数,使用宏REGISTER_LAYER_CREATOR(LayerName, LayerCreator)
可以指定用来创建layer的函数。
*
Net类通过调用静态函数LayerRegistry<Dtype>::CreateLayer(layer_param)
实例化layer
CreateLayer的代码非常容易理解
static shared_ptr<Layer<Dtype> > CreateLayer(const LayerParameter& param) {
if (Caffe::root_solver()) {
LOG(INFO) << "Creating layer " << param.name();
}
const string& type = param.type();
CreatorRegistry& registry = Registry();//registry是std::map<string, Creator>类型
CHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type
<< " (known types: " << LayerTypeListString() << ")";
return registry[type](param);
}