caffe源码解析 — net.cpp

24 篇文章 0 订阅

caffe源码解析 — net.cpp

分类: caffe源码   616人阅读  评论(2)  收藏  举报
Net类是Solve类的一个成员,在net.cpp中定义了对Net的所有操作,其中包括:
  • Init
  • GetLearningRateAndWeightDecay
  • ForwardPrefilled
  • Backward
  • ShareTrainedLayersWith
  • CopyTrainedLayersFrom
  • ToProto
  • Update
  • has_blob
  • blob_by_name
  • has_layer
  • layer_by_name

Net(const NetParameter& param) 
功能:调用Init函数初始化网络 
输入:NetParameter& param 
输出:无

Net(const string& param_file) 
功能:调用Init函数初始化网络 
输入:string& param_file 
输出:无

Init(const NetParameter& in_param) 
功能:初始化网络 
输入:NetParameter& in_param 
输出:无 
步骤: 
<1> 调用InsertSplits()函数从in_param读入新网络到param 
<2> 定义name_,blob_name_to_idx,available_blobs,num_layers 
<3> param.input_size()返回输入层blob的个数; 
param.input(i)表示第i个blob的名字; 
param.layers_size()返回网络的层数。 
<4> 对每一个输入层的blob:

  1. 产生一块和当前blob一样大的空间 e.g. imput_dim=[12 55 66 39 20 24 48 64]表示第一个blob的四个维数为 12 55 66 39,第二个为 20 24 48 64 接着blob_pointer指向这块空间
  2. blob_pointer压到blobs_中 vector<shared_ptr<Blob<Dtype>>> blobs_
  3. blob_name压到blob_names_中 vector<string> blob_names_
  4. param.force_backward()压到blob_need_backward_中 
    vector<bool> blob_need_backward_
  5. i 压到 net_input_blob_indices_中 net_input_blob_indices_ -> vector
  6. blob_pointer.get() 压到 net_input_blobs_中 
    注意与blobs_的区别 
    vector<shared_ptr<Blob<Dtype>>> blobs_ 
    vector<Blob<Dtype>*> net_input_blobs_ 
    shared_ptr类型的参数调用.get()则得到Blob*类型
  7. map<string, int> blob_name_to_idx
  8. 初始化为输入层的每个blob的名字 set<string> available_blobs
  9. 计算所需内存 memory_used += blob_pointer->count()

<5> 存每一层的输入blob指针 vector<vector<Blob<Dtype>*> > bottom_vecs_ 
存每一层输入(bottom)的id vector<vector<int> > bottom_id_vecs_ 
存每一层输出(top)的blob vector<vector<Blob<Dtype>*> > top_vecs_ 
用网络的层数param.layers_size()去初始化上面四个变量 
vector<vector<int> > top_id_vecs_ 
<6> 对第i层(很大的一个for循环):

  1. param.layers(i)返回的是关于第当前层的参数: 
    layer_param = param.layers(i)
  2. 把当前层的参数转换为shared_ptr<Layer<Dtype>>,并压入到layers_中
  3. 把当前层的名字压入到layer_names_:vector<string> layer_names_
  4. 判断当前层是否需要反馈 need_backward = param.force_backward()
  5. 下面开始产生当前层:分为处理bottom的blob和top的blob两个步骤 
    对第j个bottom的blob:

    • layer_param.bottom_size()存的是当前层的输入blob数量
    • layer_param.bottom(j)存的是第j个输入blob的名字
    • 读取当前blob的id,其中blob_name_to_idx在输入层初始化过了 
      blob_name_to_idx[blob_name] = i
    • 输出当前blob的名字
    • 存入第j个输入blob的指针bottom_vecs_[i].push_back(blobs_[blob_id].get())
    • 存入第j个输入blob的id bottom_id_vecs_[i].push_back(blob_id)
    • 更新need_backward
    • 从available_blobs中删除第j个blob的名字

    对第j个top的blob:

    • layer_param.top_size()存的是当前层的输出blob数量
    • layer_param.top(j)存的是第j个输出blob的名字
    • 判断是否进行同址计算
    • 输出当前blob的名字
    • 定义一块新的blob空间,用blob_pointer指向这块空间
    • 把这个指针存入到blobs_中
    • 把blob_name、force_backward、idx存入对应的容器中
    • 向available_blobs插入当前blob的名字
    • top_vecs_[i]对于第i层,插入当前blob的指针
    • top_id_vecs_[i]对于第i层,插入当前blob的id
  6. 输出当前层位于top的blob的信息
  7. 计算所需内存
  8. 判断当前层i是否需要backward

<7> 所有名字在available_blobs中的blob为当前层的输出blob, 
存入net_output_blobs_中 
<8> 建立每个blob的name和index的对应关系map:blob_names_index_ 
<9> 建立每个层的name和index的对应关系map:layer_names_index_ 
<10> 调用GetLearningRateAndWeightDecay函数

GetLearningRateAndWeightDecay() 
功能:收集学习速率和权重衰减,即更新params_、params_lr_和params_weight_decay_ 
输入:无 
输出:无 
步骤:对每一层 
1. 把当前层的所有blob存入params_中 
params_// The parameters in the network 
2. 如果有lr, 则把当前层的所有blob的lr存入params_lr_中; 否则, lr默认为1 
3. 如果有 weight_decay,则把当前层的所有 blob 的 weight_decay 
存入 params_weight_decay_ 中 
4. 否则,weight_decay 默认为1

ForwardPrefilled(Dtype* loss) 
功能:前馈预先填满,即预先进行一次前馈 
输入:Dtype* loss 
输出:net_output_blobs_,前馈后的输出层blob:vector

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">inline</span> Dtype Layer<Dtype>::Forward(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Blob<Dtype></span>*>& bottom, <span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Blob<Dtype></span>*>* top)
{
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (Caffe::mode())
  {
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> Caffe::CPU:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> Forward_cpu(bottom, top);
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> Caffe::GPU:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> Forward_gpu(bottom, top);
  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span>:
    LOG(FATAL) << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Unknown caffe mode."</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> Dtype(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
  }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> Dtype Forward_cpu(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Blob<Dtype></span>*>& bottom, <span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Blob<Dtype></span>*>* top) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

Forward(const vector<Blob<Dtype>*> & bottom, Dtype* loss) 
功能:把网络输入层的blob读到net_input_blobs_,然后进行前馈,计算出loss 
输入:整个网络输入层的blob 
输出:整个网络输出层的blob

Forward(const string& input_blob_protos, Dtype* loss) 
功能:Forward的重载,只是输入层的blob以string的格式传入

Backward() 
功能:对整个网络进行反向传播

ShareTrainedLayersWith(Net* other) 
功能:从Other网络复制某些层 
步骤:对Other网络的第i层(源层): 
1. 定义一个Layer的指针指向第i层 
2. 读取第i层(源层)的名字 
3. 找通过名字来找目标层 
如果没找到,即target_layer_id == layer_names_.size() 
则忽略Other的第i层,即Other的第i层不需要share给网络 
4. 如果找到了,即other的第i层需要share给网络, 
则把目标层的所有blob读到target_blobs中

  1. 判断目标层和源层的blob数量是否相等
  2. 判断每个blob大小是否相等
  3. 调用ShareData函数把源层的blob赋给目标层的blob

CopyTrainedLayersFrom(const NetParameter& param) 
功能:和ShareTrainedLayersWith一样 
步骤:不同的是调用FromProto函数把源层的blob赋给目标层的blob

CopyTrainedLayersFrom(const string trained_filename) 
功能:从文件中读入NetParameter param,然后调用CopyTrainedLayersFrom()

ToProto(NetParameter* param, bool write_diff) 
功能:把网络的参数存入prototxt中 
步骤: 
1. 设置网络的名字:param->set_name(name_) 
2. 加入输入层blob的名字 
3. 对于第i层:

  1. 加入bottom的blob的名字
  2. 加入top的blob的名字
  3. 写到proto中

Update() 
功能:更新params_中blob的值

has_blob(const string& blob_name) 
功能:判断是否存在名字为blob_name的blob

blob_by_name(const string& blob_name) 
功能:给一个blob的名字,返回这个blob的指针

has_layer(const string& layer_name) 
功能:判断是否存在名字为layer_name的layer

layer_by_name(const string& layer_name) 
功能:给一个layer的名字,返回这个layer的指针

版权声明:本文为博主原创文章,未经博主允许不得转载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值