8、caffe 之网络搭建net.cpp

caffe 通过工厂模式----先父类构造然后子类构造的原则,进行solver.cpp的构造函数初始化;

   Solver<Dtype>::Solver(const SolverParameter& param)
    : net_(), callbacks_(), requested_early_exit_(false) {
  Init(param);
}

在构造函数中,进行网络初始化;

template <typename Dtype>
void Solver<Dtype>::Init(const SolverParameter& param) {
  CHECK(Caffe::root_solver() || root_solver_)
      << "root_solver_ needs to be set for all non-root solvers";
  LOG_IF(INFO, Caffe::root_solver()) << "Initializing solver from parameters: "
    << std::endl << param.DebugString();
  param_ = param;
  CHECK_GE(param_.average_loss(), 1) << "average_loss should be non-negative.";
  CheckSnapshotWritePermissions();
  if (Caffe::root_solver() && param_.random_seed() >= 0) {
    Caffe::set_random_seed(param_.random_seed());
  }
  // Scaffolding code
  InitTrainNet();
  if (Caffe::root_solver()) {
    InitTestNets();
    LOG(INFO) << "Solver scaffolding done.";
  }
  iter_ = 0;
  current_step_ = 0;
}

在void Solver<Dtype>::Init(const SolverParameter& param)函数中首先打印了lenet_solver.prototxt信息(主要通过protobuf自带的函数param.DebugString()),输出了调试信息

test_iter: 100
test_interval: 500
base_lr: 0.01
display: 100
max_iter: 10000
lr_policy: "inv"
gamma: 0.0001
power: 0.75
momentum: 0.9
weight_decay: 0.0005
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
solver_mode: GPU
device_id: 0
net: "examples/mnist/lenet_train_test.prototxt"
train_state {
  level: 0
  stage: ""
}

其实protobuf 中的调试信息函数应该为:param.ShortDebugString(); 但是该函数将结果进行换行,手册查询的;

test_iter: 100 test_interval: 500 base_lr: 0.01 display: 100 max_iter: 10000 lr_policy: "inv" gamma: 0.0001 power: 0.75 momentum: 0.9 weight_decay: 0.0005 snapshot: 5000 snapshot_prefix: "examples/mnist/lenet" solver_mode: GPU device_id: 0 net: "examples/mnist/lenet_train_test.prototxt" train_state { level: 0 stage: "" }

调试信息完成之后,然后进行网络展开解析

 // Scaffolding code
  InitTrainNet();

在函数void Solver<Dtype>::InitTrainNet() 中,首先对网络构建之前,进行一些参数初始化;

  NetState net_state;
  net_state.set_phase(TRAIN);
  net_state.MergeFrom(net_param.state());
  net_state.MergeFrom(param_.train_state());
  net_param.mutable_state()->CopyFrom(net_state);

 

然后在new了一个网络对象,通过net.cpp文件进行net构造函数的初始化,这个过程就是对Net路径的网络进行解析即:

 net_.reset(new Net<Dtype>(net_param));
net: "examples/mnist/lenet_train_test.prototxt"

在net.cpp文件中,执行了net的构造函数,进行初始化;

void Net<Dtype>::Init(const NetParameter& in_param)

通过gdb调试可以查看网络的名字(name: "LeNet"),层次(11)等;

 phase_ = in_param.state().phase();

然后进行整个网络层次的规则检查,主要看存在的include/exclude是否满足条件;可以参考博客:https://yangwenbo.com/articles/caffe-net-config-all-in-one.html?utm_source=tuicool&utm_medium=referral

  FilterNet(in_param, &filtered_param);

然后进行网络层次搭建,作者是把整个网络架构存放在map中;例如以mnist为例~~

name: "LeNet"
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"
    batch_size: 64
    backend: LMDB
  }
}

layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}

 

然后代码进行解析

void InsertSplits(const NetParameter& param, NetParameter* param_split) {
  // Initialize by copying from the input NetParameter.
  param_split->CopyFrom(param);
  param_split->clear_layer();
  map<string, pair<int, int> > blob_name_to_last_top_idx;
  /*
    第一层的mnist 中的top-name 及其位置定义转存blob-name
     data  0 0
     label 0 0
   */
   
  map<pair<int, int>, pair<int, int> > bottom_idx_to_source_top_idx;
   /* 
    第二层的conv1 中的 bottom-name 及其位置定义 转存在blob-name 
   此处为 data 位置为[1,0]
   而连接为 mnist top-name (data)转存的blob 的位置  连接上 conv1 bottom-name (data)
     [1,0] = 0 1   
     
   */
  map<pair<int, int>, int> top_idx_to_bottom_count;
  map<pair<int, int>, float> top_idx_to_loss_weight;
  map<pair<int, int>, int> top_idx_to_bottom_split_idx;
  map<int, string> layer_idx_to_layer_name;
  /*
       存储的每一个层次的名字
       0 layer_name mnist
       1 layer_name conv1 
       . ................
 
   */
  for (int i = 0; i < param.layer_size(); ++i) {
    const LayerParameter& layer_param = param.layer(i);
    layer_idx_to_layer_name[i] = layer_param.name();
    cout<<"layer_idx_to_layer_name="<<layer_param.name()<<endl;
    cout<<"layer_param.bottom_size="<<layer_param.bottom_size()<<endl;

     for (int j = 0; j < layer_param.bottom_size(); ++j) {
      const string& blob_name = layer_param.bottom(j);
      cout<<"blob_name="<<blob_name<<endl;
   
      if (blob_name_to_last_top_idx.find(blob_name) ==
          blob_name_to_last_top_idx.end()) {
        LOG(FATAL) << "Unknown bottom blob '" << blob_name << "' (layer '"
                   << layer_param.name() << "', bottom index " << j << ")";
      }
      const pair<int, int>& bottom_idx = make_pair(i, j);
      const pair<int, int>& top_idx = blob_name_to_last_top_idx[blob_name];
      bottom_idx_to_source_top_idx[bottom_idx] = top_idx;
      ++top_idx_to_bottom_count[top_idx];
    }
    for (int j = 0; j < layer_param.top_size(); ++j) {
      const string& blob_name = layer_param.top(j);
      cout<<"blob_name="<<blob_name<<endl;
  /*
    blob_name 为caffe 存储的数据结构 记录了数据名称(top bottom )的坐标
      0 0
      0 1
   */
      blob_name_to_last_top_idx[blob_name] = make_pair(i, j);
    }
.......................

 

 

完待续。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sxj731533730

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值