caffe源码学习

整体结构:

主要有以下部分:net, blob, layer, solver.

  • net.cpp:  
    net定义网络, 整个网络中含有很多layers,net构造函数中将所有layer按配置组装起来。net.cpp负责计算整个网络在训练中的forward, backward过程, 即计算forward/backward 时各layer的gradient。

  • layer:  
    在protobuffer (.proto文件中定义message类型,.prototxt或.binaryproto文件中定义message的值) 中调用时包含属性name, type(data/conv/pool…), connection structure (input blobs and output blobs),layer-specific parameters(如conv层的kernel大小)。定义一个layer需要定义其setup, forward 和backward过程。

  • blob.cpp:  
    net中的数据和求导结果通过4维的blob传递,而实际上,它们只是一维的指针而已。一个layer有很多blobs。

    • 对data,weight blob大小为Number * Channels * Height * Width, 如256*3*224*224;

    • 对conv层,weight blob大小为 Output 节点数 * Input 节点数 * Height * Width,如AlexNet第一个conv层的blob大小为96 x 3 x 11 x 11;

    • 对inner product 层, weight blob大小为 1 * 1 * Output节点数 * Input节点数; bias blob大小为1 * 1 * 1 * Output节点数( conv层和inner product层一样,也有weight和bias,所以在网络结构定义中我们会看到两个blobs_lr,第一个是weights的,第二个是bias的。类似地,weight_decay也有两个,一个是weight的,一个是bias的);

    blob中,mutable_cpu/gpu_data() 和cpu/gpu_data()用来管理memory,cpu/gpu_diff()和 mutable_cpu/gpu_diff()用来计算求导结果。blob内存采用SyncedMemory管理,在一定程度上隐藏了cpu和gpu直接的数据拷贝,head_表示数据的状态。其中的mutable_cpu/gpu_data() 和cpu/gpu_data()的获得是同一个指针,但是mutable意味着数据将被更改,所以head_被修改。

  • slover.cpp:  
    结合loss,用gradient更新weights。主要函数:  
    Init(),
    Solve(),
    ComputeUpdateValue(),  
    Snapshot(), Restore(),//快照(拷贝)与恢复 网络state
    Test();

    在solver.cpp中有3中solver,即3个类:AdaGradSolver, SGDSolver和NesterovSolver可供选择。

    关于loss,可以同时有多个loss,可以加regularization(L1/L2);


关于net的params_和learnable_params_

The mapping from params_ -> learnable_params_: we have
learnable_param_ids_.size() == params_.size(),
and learnable_params_[learnable_param_ids_[i]] == params_[i].get()
if and only if params_[i] is an "owner"; otherwise, params_[i] is a sharer
and learnable_params_[learnable_param_ids_[i]] gives its owner.
    在深度神经网络中为了减少参数,一些神经元的链接采用共享权值。params_记录了整个网络的参数,其中部分参数是共享的,即存在params_[i]和params_[j]这两个blob中的data和diff是一块内存。learnable_param_ids_[i]记录的是第i个参数的owner的id。在net的Init结束时,调用了ShareWeights函数,将共享的参数指向了同一块内存。

void Net<Dtype>::ShareWeights() {
  for (int i = 0; i < params_.size(); ++i) {
    if (param_owners_[i] < 0) { continue; }
    params_[i]->ShareData(*params_[param_owners_[i]]);
    params_[i]->ShareDiff(*params_[param_owners_[i]]);
  }
}


留言:
2016/6/23 11:50:10

有个图示就好了,比如神经网络的参数与数据矩阵的对应。还有计算loss的公式~

龙门外的鱼 回复: 阿stupid
2016/6/24 3:19:35

目前博客当作了笔记用。后续会一点点的完善下去。多谢建议!