caffe源码解析 — net.cpp

来源:互联网 发布:内核与python关系 编辑:程序博客网 时间:2024/05/16 22:52
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

inline Dtype Layer<Dtype>::Forward(const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top){  switch (Caffe::mode())  {  case Caffe::CPU:    return Forward_cpu(bottom, top);  case Caffe::GPU:    return Forward_gpu(bottom, top);  default:    LOG(FATAL) << "Unknown caffe mode.";    return Dtype(0);  }
virtual Dtype Forward_cpu(const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) = 0;}

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的指针

0 0
原创粉丝点击