cxxnet学习笔记6

来源:互联网 发布:百胜yum统一认证平台 编辑:程序博客网 时间:2024/05/21 16:54

layer模块实现了神经网络层并定义了Forward和Backprop。

layer包括以下这些源码文件:


loss

activation_layer-inl.hpp

batch_norm_layer-inl.hpp

bias_layer-inl.hpp

concat_layer-inl.hpp

convolution_layer-inl.hpp

cudnn_convolution_layer-inl.hpp

cudnn_pooling_layer-inl.hpp

dropout_layer-inl.hpp

fixconn_layer-inl.hpp

flatten_layer-inl.hpp

fullc_layer-inl.hpp

insanity_layer-inl.hpp

insanity_pooling_layer-inl.hpp

layer.h

layer_impl-inl.hpp

layer_impl.cpp

layer_impl.cu

lrn_layer-inl.hpp

op.h

pairtest_layer-inl.hpp

param.h

pooling_layer-inl.hpp

prelu_layer-inl.hpp

split_layer-inl.hpp

visitor.h

xelu_layer-inl.hpp


其中loss是一个文件夹,展开其内部如下所示:


loss_layer_base-inl.hpp

lp_loss_layer-inl.hpp

multi_logistic_layer-inl.hpp

softmax_layer-inl.hpp


我们还是从layer.h开始。

layer.h是该模块的接口,它主要定义了如下这些内容:


template<typename xpu>

struct Node {};

//该结构体用于存储网络中的Forward激励与BP梯度。


struct LabelRecord {};

//一个label记录可被一个损失函数采用,使用结构体保障未来的可扩展性。


struct LabelInfo {}

//用于保存label实例的额外信息,这些信息可被layer用来计算在目标函数上的梯度,这个数据结构会被升级,以满足不同种类的监督信号的需求。


template<typename xpu>

struct ConnectState {};

//表示连接状态,时间空间信息可被Forward和Backprop之间共享。并不是所有layer需要它。


//ILayer是该模块的接口,它是一个纯粹的接口,里面没有数据成员,然而,在一个layer中可以存在具有相同模式的成员,具体规则如下:


Connection 和 Layer:

在当前CXXnet设计中,connection和layer的概念为:

一个layer定义了Forward和Backprop功能并给定了输入输出节点;

一个layer不依附于特定的节点,而Connection是;

Connection是节点间的连接,这些节点的功能由layer支持;

不同的connection可共享一个相同的layer;

这意味着layer不能包含特定状态(如:标记为dropout)的节点类;

Connection指定其状态由connection维护,在Forward/Backprop过程中传递给layer。


权重和梯度:

一些layer可以有参数为权重和梯度的connection;

这些权重由特定实现持有;

它们可以用一个vistor获取,见IVisitor;

SaveModel和LoadModel用来序列化和反序列化它们。


参数:

参数与每一个layer相关(如:隐层节点个数),可以调用SetParam设置。


template<typename xpu>

class ILayer {


 public:


  struct IVisitor {};

//定义layer的vistor,用于访问layer的权重和梯度值。


  virtual ~ILayer(void) {}


  virtual void InitConnection(

  const std::vector<Node<xpu>*> &nodes_in,

            const std::vector<Node<xpu>*> &nodes_out,

            ConnectState<xpu> *p_cstate) = 0;

//初始化connection,该函数负责俩件事

1、设置输出节点的形状;

2、在p_cstate分配必要的时间状态空间。


  virtual void OnBatchSizeChanged(

const std::vector<Node<xpu>*> &nodes_in,

const std::vector<Node<xpu>*> &nodes_out,

ConnectState<xpu> *p_cstate) {}

//当batch大小改变时更新p_cstate,


  virtual void Forward(bool is_train,

                       const std::vector<Node<xpu>*> &nodes_in,

                       const std::vector<Node<xpu>*> &nodes_out,

                       ConnectState<xpu> *p_cstate) = 0;

//由输入节点向输出节点做前向传播


  virtual void Backprop(bool prop_grad,

                        const std::vector<Node<xpu>*> &nodes_in,

                        const std::vector<Node<xpu>*> &nodes_out,

                        ConnectState<xpu> *p_cstate) = 0;

//由输出节点向输入节点做后向传播,在函数调用前,确保输出节点包含梯度值。


  virtual boolAllowSharing(void)const {

    return true;

  }

//询问是否可跨多个connection共享这一layer,对于大多数layer应当返回true。


  virtual void SetStream(mshadow::Stream<xpu> *stream) {}

//设置内部计算的stream为stream。


  virtual void ApplyVisitor(IVisitor *pvisitor) {}

//应用vistor到layer,vistor用来访问layer的内容。


  virtual voidSetParam(const char *name, const char* val) {}

//设置layer的参数。


  virtual voidInitModel(void) {}

//初始化Model参数,只在model参数未被初始化时调用。


  virtual void SaveModel(utils::IStream &fo) const {}

//将model存入二进制文件。


  virtual void LoadModel(utils::IStream &fi) {}

//从二进制文件中读取model

};


上面这些就是ILayer类的定义。下面的是一些枚举,省略其中一部分。


const intkSharedLayer = 0;

const intkFullConnect = 1;

const intkSoftmax = 2;

const intkFixConnect = 31;

const intkBatchNorm_no_ma = 32;

const intkPairTestGap = 1024;

typedef int LayerType;


inline LayerType GetLayerType(constchar *type) {}

//给出type名,返回其对应的整数值,对应关系参考上面的枚举。


template<typename xpu>

ILayer<xpu>* CreateLayer(LayerType type,

                         mshadow::Random<xpu> *p_rnd,

                         const LabelInfo *label_info);

//由给定类型创建一个updater,它与节点很像,但包含了label信息。


//指定connection的数据结构,定义了节点间的连接。

template<typename xpu>

struct Connection {

  ILayer<xpu> *layer;

//指向后端连接的layer


  LayerType type;

//后端layer的类型


  ConnectState<xpu> state;

//表示当前的共享信息


  std::vector<Node<xpu>*> nodes_in;

//输入节点容器


  std::vector<Node<xpu>*> nodes_out;

//输出节点容器


  inline void SetStream(mshadow::Stream<xpu> *stream) {}

//设置内部计算流

};


layer.h的定义到此为止,其重点在于node、ILayer和Connection这三部分。


op.h定义了mshadow针对cxxnet的额外操作。


在每一个layer中几乎都用到了参数,param.h提供的结构体LayerParam并不强制使用,但在layer中使用它会很有帮助。LayerParam定义了任意layer所有可能会用到的参数。


visitor.h给出了visitor关于layer权重操作的实现,提供给utils模块从一个layer设置或得到权重的方法。它实现了俩个类GetWeightVisitor和SetWeightVisitor,都继承于IVisitor,如名字所示,一个用来从layer获得权重,一个用于给layer设置权重,使用举例如下:


 Get Example:

      GetWeightVisitor vs("weight");

      layer->ApplyVisitor(&vs);

      std::vector<mshadow::Tensor<xpu, 2> > weights = vs.data;


 Set Example:

      GetSetVisitor vs(data, "weight");

      layer->ApplyVisitor(&vs);

由于Layer模块最为复杂庞大,所以我们分为两节来讲,本节到此结束,下一节会对所有.hpp文件学习。



0 0
原创粉丝点击