zoukankan      html  css  js  c++  java
  • Caffe源码-Net类(下)

    net.cpp部分源码

    // 接着上一篇博客的介绍,此部分为Net类中前向反向计算函数,以及一些与HDF5文件或proto文件相互转换的函数。
    
    template <typename Dtype>
    Dtype Net<Dtype>::ForwardFromTo(int start, int end) {   //执行第start层到第end层的前向计算过程
      CHECK_GE(start, 0);     //检查start >= 0, end < 总层数
      CHECK_LT(end, layers_.size());
      Dtype loss = 0;         //存储每层前向计算的loss之和
      for (int i = start; i <= end; ++i) {
        for (int c = 0; c < before_forward_.size(); ++c) {
          before_forward_[c]->run(i);   //在调用前向计算之前调用的回调函数
        }
        Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], top_vecs_[i]); //调用Layer类的前向计算函数,返回计算出的loss
        loss += layer_loss;   //累加
        if (debug_info_) { ForwardDebugInfo(i); }   //允许打印调试信息,则打印输出blob和参数blob的数据的均值信息
        for (int c = 0; c < after_forward_.size(); ++c) {
          after_forward_[c]->run(i);    //同样,在调用前向计算之后调用的回调函数
        }
      }
      return loss;
    }
    
    template <typename Dtype>
    Dtype Net<Dtype>::ForwardFrom(int start) {    //执行第start层到末尾层的前向计算过程
      return ForwardFromTo(start, layers_.size() - 1);
    }
    
    template <typename Dtype>
    Dtype Net<Dtype>::ForwardTo(int end) {        //执行起始层到第end层的前向计算过程
      return ForwardFromTo(0, end);
    }
    
    template <typename Dtype>
    const vector<Blob<Dtype>*>& Net<Dtype>::Forward(Dtype* loss) {    //执行网络的所有层的前向计算过程
      if (loss != NULL) {
        *loss = ForwardFromTo(0, layers_.size() - 1);   //返回的loss保存起来
      } else {
        ForwardFromTo(0, layers_.size() - 1);
      }
      return net_output_blobs_;   //输出网络的输出blob数据
    }
    
    template <typename Dtype>
    const vector<Blob<Dtype>*>& Net<Dtype>::Forward(
        const vector<Blob<Dtype>*> & bottom, Dtype* loss) {   //旧版本函数,将bottom当作网络的输入,执行整个网络的前向计算过程
      LOG_EVERY_N(WARNING, 1000) << "DEPRECATED: Forward(bottom, loss) "
          << "will be removed in a future version. Use Forward(loss).";
      // Copy bottom to net bottoms
      for (int i = 0; i < bottom.size(); ++i) {
        net_input_blobs_[i]->CopyFrom(*bottom[i]);    //bottom中的数据拷贝至网络的输入blob中
      }
      return Forward(loss);   //前向计算
    }
    
    template <typename Dtype>
    void Net<Dtype>::BackwardFromTo(int start, int end) {   //执行第start层到第end层的反向计算过程
      CHECK_GE(end, 0);
      CHECK_LT(start, layers_.size());    //检查输入参数,从后往前,start不超过末尾层,end不小于起始层
      for (int i = start; i >= end; --i) {
        for (int c = 0; c < before_backward_.size(); ++c) {
          before_backward_[c]->run(i);    //反向计算之前调用的回调函数
        }
        if (layer_need_backward_[i]) {    //当前层是否需要反向计算
          layers_[i]->Backward(top_vecs_[i], bottom_need_backward_[i], bottom_vecs_[i]);  //反向计算
          if (debug_info_) { BackwardDebugInfo(i); }    //打印调试信息
        }
        for (int c = 0; c < after_backward_.size(); ++c) {
          after_backward_[c]->run(i);     //反向计算之后调用的回调函数
        }
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::ForwardDebugInfo(const int layer_id) {       //打印第layer_id层的前向计算结果的调试信息
      for (int top_id = 0; top_id < top_vecs_[layer_id].size(); ++top_id) {
        const Blob<Dtype>& blob = *top_vecs_[layer_id][top_id];   //第layer_id层的第top_id个输出blob
        const string& blob_name = blob_names_[top_id_vecs_[layer_id][top_id]];    //该blob对应的名称
        const Dtype data_abs_val_mean = blob.asum_data() / blob.count();  //计算blob中data_的绝对值之和的均值
        LOG_IF(INFO, Caffe::root_solver())
            << "    [Forward] "
            << "Layer " << layer_names_[layer_id]
            << ", top blob " << blob_name
            << " data: " << data_abs_val_mean;    //打印信息
      }
      for (int param_id = 0; param_id < layers_[layer_id]->blobs().size(); ++param_id) {
        const Blob<Dtype>& blob = *layers_[layer_id]->blobs()[param_id];  //第layer_id层的第param_id个参数blob
        const int net_param_id = param_id_vecs_[layer_id][param_id];      //该参数blob在params_中索引
        const string& blob_name = param_display_names_[net_param_id];     //由索引得到参数blob的名称
        const Dtype data_abs_val_mean = blob.asum_data() / blob.count();  //参数blob的data_的绝对值之和的均值
        LOG_IF(INFO, Caffe::root_solver())
            << "    [Forward] "
            << "Layer " << layer_names_[layer_id]
            << ", param blob " << blob_name
            << " data: " << data_abs_val_mean;    //打印均值信息
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::BackwardDebugInfo(const int layer_id) {      //打印第layer_id层的反向计算结果的调试信息
      const vector<Blob<Dtype>*>& bottom_vec = bottom_vecs_[layer_id];
      for (int bottom_id = 0; bottom_id < bottom_vec.size(); ++bottom_id) { //第layer_id层的第bottom_id个输入blob
        if (!bottom_need_backward_[layer_id][bottom_id]) { continue; }      //不处理不需要反传的输入
        const Blob<Dtype>& blob = *bottom_vec[bottom_id];         //输入blob数据
        const string& blob_name = blob_names_[bottom_id_vecs_[layer_id][bottom_id]];  //输入blob名称
        const Dtype diff_abs_val_mean = blob.asum_diff() / blob.count();  //输入blob的diff_的绝对值之和的均值
        LOG_IF(INFO, Caffe::root_solver())
            << "    [Backward] "
            << "Layer " << layer_names_[layer_id]
            << ", bottom blob " << blob_name
            << " diff: " << diff_abs_val_mean;    //打印
      }
      for (int param_id = 0; param_id < layers_[layer_id]->blobs().size(); ++param_id) {
        if (!layers_[layer_id]->param_propagate_down(param_id)) { continue; }   //略过无需反传的
        const Blob<Dtype>& blob = *layers_[layer_id]->blobs()[param_id];    //第layer_id层的第param_id个参数blob
        const Dtype diff_abs_val_mean = blob.asum_diff() / blob.count();    //参数blob的diff_的绝对值之和的均值
        LOG_IF(INFO, Caffe::root_solver())
            << "    [Backward] "
            << "Layer " << layer_names_[layer_id]
            << ", param blob " << param_id
            << " diff: " << diff_abs_val_mean;    //打印
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::UpdateDebugInfo(const int param_id) {    //打印net中第param_id个参数的一些信息
      const Blob<Dtype>& blob = *params_[param_id];           //net中第param_id个参数blob
      const int param_owner = param_owners_[param_id];        //net中第param_id个参数的来源的索引(源参数的索引)
      const string& layer_name = layer_names_[param_layer_indices_[param_id].first];  //第param_id个参数所在层的名称
      const string& param_display_name = param_display_names_[param_id];    //该参数的名称
      const Dtype diff_abs_val_mean = blob.asum_diff() / blob.count();      //该参数的diff_的绝对值之和的均值
      if (param_owner < 0) {    //param_owner为-1表示该参数为源参数
        const Dtype data_abs_val_mean = blob.asum_data() / blob.count();  //计算data_的绝对值之和的均值
        LOG_IF(INFO, Caffe::root_solver())
            << "    [Update] Layer " << layer_name
            << ", param " << param_display_name
            << " data: " << data_abs_val_mean
            << "; diff: " << diff_abs_val_mean;   //打印
      } else {  //该参数为共享参数
        const string& owner_layer_name =
            layer_names_[param_layer_indices_[param_owner].first];  //该共享参数对应的源参数的名称
        LOG_IF(INFO, Caffe::root_solver())
            << "    [Update] Layer " << layer_name
            << ", param blob " << param_display_name
            << " (owned by layer " << owner_layer_name << ", " << "param "
            << param_display_names_[param_owners_[param_id]] << ")"
            << " diff: " << diff_abs_val_mean;    //打印
      }
    }
    
    //将other网络的layer的参数blob数据共享给当前网络中的相同名称的layer(只修改指针指向的位置,并不会复制数据)
    template <typename Dtype>
    void Net<Dtype>::ShareTrainedLayersWith(const Net* other) {
      int num_source_layers = other->layers().size();   //来源网络的layer的个数
      for (int i = 0; i < num_source_layers; ++i) {
        Layer<Dtype>* source_layer = other->layers()[i].get();      //来源网络的第i个layer的指针
        const string& source_layer_name = other->layer_names()[i];  //来源网络第i个layer的名称
        int target_layer_id = 0;
        while (target_layer_id != layer_names_.size() &&
            layer_names_[target_layer_id] != source_layer_name) {   //在当前网络中寻找与来源网络第i个layer名称相同的layer
          ++target_layer_id;
        }
        if (target_layer_id == layer_names_.size()) {   //未找到名称相同的,该layer的参数不进行共享
          LOG(INFO) << "Ignoring source layer " << source_layer_name;
          continue;
        }
        //当前网络中第target_layer_id个layer与other网络的第i个layer的名称相同,开始共享参数
        DLOG(INFO) << "Copying source layer " << source_layer_name;
        vector<shared_ptr<Blob<Dtype> > >& target_blobs = layers_[target_layer_id]->blobs();  //当前层的blob数据
        CHECK_EQ(target_blobs.size(), source_layer->blobs().size())
            << "Incompatible number of blobs for layer " << source_layer_name;    //检查两个layer的参数blob是否相等
        for (int j = 0; j < target_blobs.size(); ++j) {
          Blob<Dtype>* source_blob = source_layer->blobs()[j].get();    //other的第i层的第j个参数blob
          CHECK(target_blobs[j]->shape() == source_blob->shape())
              << "Cannot share param " << j << " weights from layer '"
              << source_layer_name << "'; shape mismatch.  Source param shape is "
              << source_blob->shape_string() << "; target param shape is "
              << target_blobs[j]->shape_string();     //检查两个参数blob的形状是否相同
          target_blobs[j]->ShareData(*source_blob);   //共享数据,将target_blobs[j]的data_的数据指针指向source_blob中的data_
        }
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::BackwardFrom(int start) {    //执行第start层到起始层的反向计算过程
      BackwardFromTo(start, 0);
    }
    
    template <typename Dtype>
    void Net<Dtype>::BackwardTo(int end) {        //执行末尾层到第end层的反向计算过程
      BackwardFromTo(layers_.size() - 1, end);
    }
    
    template <typename Dtype>
    void Net<Dtype>::Backward() {     //执行网络的所有层的反向计算过程
      BackwardFromTo(layers_.size() - 1, 0);    //整个网络
      if (debug_info_) {              //打印调试信息
        Dtype asum_data = 0, asum_diff = 0, sumsq_data = 0, sumsq_diff = 0;
        for (int i = 0; i < learnable_params_.size(); ++i) {  //net中的所有可学习参数
          asum_data += learnable_params_[i]->asum_data();     //参数blob的data_的绝对值之和
          asum_diff += learnable_params_[i]->asum_diff();     //参数blob的diff_的绝对值之和
          sumsq_data += learnable_params_[i]->sumsq_data();   //参数blob的data_的平方和
          sumsq_diff += learnable_params_[i]->sumsq_diff();   //参数blob的diff_的平方和
        }
        const Dtype l2norm_data = std::sqrt(sumsq_data);      //开方
        const Dtype l2norm_diff = std::sqrt(sumsq_diff);
        LOG(ERROR) << "    [Backward] All net params (data, diff): "
                   << "L1 norm = (" << asum_data << ", " << asum_diff << "); "
                   << "L2 norm = (" << l2norm_data << ", " << l2norm_diff << ")"; //打印
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::Reshape() {    //调整网络中所有层的输入输出数据和参数数据等的形状
      for (int i = 0; i < layers_.size(); ++i) {
        layers_[i]->Reshape(bottom_vecs_[i], top_vecs_[i]);   //调用各层各自的reshape函数
      }
    }
    
    //从param中拷贝同名的layer的参数blob数据(与ShareTrainedLayersWith不同,该函数是复制数据而不是修改数据指针的位置)
    template <typename Dtype>
    void Net<Dtype>::CopyTrainedLayersFrom(const NetParameter& param) {
      int num_source_layers = param.layer_size();     //来源网络参数中layer的个数
      for (int i = 0; i < num_source_layers; ++i) {
        const LayerParameter& source_layer = param.layer(i);    //来源的第i个layer对应的LayerParameter
        const string& source_layer_name = source_layer.name();  //来源网络的layer的名称
        int target_layer_id = 0;
        while (target_layer_id != layer_names_.size() &&
            layer_names_[target_layer_id] != source_layer_name) { //同样,在当前net中寻找与之名称相同的layer
          ++target_layer_id;
        }
        if (target_layer_id == layer_names_.size()) {   //未找到,跳过该层
          LOG(INFO) << "Ignoring source layer " << source_layer_name;
          continue;
        }
        //当前net中第target_layer_id个layer与param的第i个对应
        DLOG(INFO) << "Copying source layer " << source_layer_name;
        vector<shared_ptr<Blob<Dtype> > >& target_blobs =
            layers_[target_layer_id]->blobs();  //当前net中第target_layer_id个layer的参数blob
        CHECK_EQ(target_blobs.size(), source_layer.blobs_size())
            << "Incompatible number of blobs for layer " << source_layer_name;    //检查参数个数是否相等
        for (int j = 0; j < target_blobs.size(); ++j) {
          if (!target_blobs[j]->ShapeEquals(source_layer.blobs(j))) {   //检查参数blob与param中的BlobProto消息的数据形状是否一致
            Blob<Dtype> source_blob;
            const bool kReshape = true;
            //不一致,则将source_layer的BlobProto消息的数据拷贝至source_blob中,然后报错
            source_blob.FromProto(source_layer.blobs(j), kReshape);
            LOG(FATAL) << "Cannot copy param " << j << " weights from layer '"
                << source_layer_name << "'; shape mismatch.  Source param shape is "
                << source_blob.shape_string() << "; target param shape is "
                << target_blobs[j]->shape_string() << ". "
                << "To learn this layer's parameters from scratch rather than "
                << "copying from a saved net, rename the layer.";   //报错
          }
          const bool kReshape = false;
          //将source_layer中第j个BlobProto消息数据拷贝至target_blobs[j]中
          target_blobs[j]->FromProto(source_layer.blobs(j), kReshape);
        }
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::CopyTrainedLayersFrom(const string& trained_filename) {  //从文件trained_filename中拷贝网络参数
      if (H5Fis_hdf5(trained_filename.c_str())) {       //判断文件是否未hdf5格式
        CopyTrainedLayersFromHDF5(trained_filename);    //从hdf5类型的文件中拷贝网络参数
      } else {
        CopyTrainedLayersFromBinaryProto(trained_filename);   //从二进制的proto文件中读取网络的参数
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::CopyTrainedLayersFromBinaryProto(const string& trained_filename) { //从二进制的proto文件中读取网络的参数
      NetParameter param;
      ReadNetParamsFromBinaryFileOrDie(trained_filename, &param); //从trained_filename文件中读取,存入param中
      CopyTrainedLayersFrom(param);   //将参数拷贝至当前网络中
    }
    
    template <typename Dtype>
    void Net<Dtype>::CopyTrainedLayersFromHDF5(const string& trained_filename) {    //从hdf5类型的文件中拷贝网络参数
    #ifdef USE_HDF5
      hid_t file_hid = H5Fopen(trained_filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);  //打开hdf5类型的文件
      CHECK_GE(file_hid, 0) << "Couldn't open " << trained_filename;    //检查是否打开
      hid_t data_hid = H5Gopen2(file_hid, "data", H5P_DEFAULT);         //打开file_hid中的"data"数据集
      CHECK_GE(data_hid, 0) << "Error reading weights from " << trained_filename;   //检查是否打开
      int num_layers = hdf5_get_num_links(data_hid);    //获取data_hid中links(元素?)的个数,此处即为layer的个数
      for (int i = 0; i < num_layers; ++i) {
        string source_layer_name = hdf5_get_name_by_idx(data_hid, i);   //data_hid中第i个link的名称
        if (!layer_names_index_.count(source_layer_name)) {             //在当前net中寻找同名的layer
          LOG(INFO) << "Ignoring source layer " << source_layer_name;   //未找到,跳过
          continue;
        }
        int target_layer_id = layer_names_index_[source_layer_name];    //得到该layer在当前网络中的索引
        DLOG(INFO) << "Copying source layer " << source_layer_name;
        vector<shared_ptr<Blob<Dtype> > >& target_blobs = layers_[target_layer_id]->blobs();  //当前网络中该layer的参数blob
        hid_t layer_hid = H5Gopen2(data_hid,
            source_layer_name.c_str(), H5P_DEFAULT); //打开data_hid中名为source_layer_name的数据集
        CHECK_GE(layer_hid, 0) << "Error reading weights from " << trained_filename;  //检查是否打开
        // Check that source layer doesn't have more params than target layer
        int num_source_params = hdf5_get_num_links(layer_hid);    //返回layer_hid中links的个数,即为参数的个数
        CHECK_LE(num_source_params, target_blobs.size())
            << "Incompatible number of blobs for layer " << source_layer_name;  //检查是否与参数blob的个数相等
        for (int j = 0; j < target_blobs.size(); ++j) {   //拷贝每个参数blob
          ostringstream oss;
          oss << j;
          string dataset_name = oss.str();
          int target_net_param_id = param_id_vecs_[target_layer_id][j]; //第target_layer_id层第j个参数在params_中的索引
          if (!H5Lexists(layer_hid, dataset_name.c_str(), H5P_DEFAULT)) { //layer_hid中是否存在名为dataset_name的数据集
            // Target param doesn't exist in source weights...
            if (param_owners_[target_net_param_id] != -1) {   //hdf5文件中不存在该参数,但是该参数为共享参数,所以不影响
              // ...but it's weight-shared in target, so that's fine.
              continue;
            } else {
              LOG(FATAL) << "Incompatible number of blobs for layer "
                  << source_layer_name;   //源参数,但是在hdf5文件中不存在,报错
            }
          }
          hdf5_load_nd_dataset(layer_hid, dataset_name.c_str(), 0, kMaxBlobAxes,
              target_blobs[j].get()); //读取dataset_name数据集,检查其形状和数据类型,并存入target_blobs[j]的cpu data中
        }
        H5Gclose(layer_hid);    //关闭
      }
      H5Gclose(data_hid);
      H5Fclose(file_hid);
    #else
      LOG(FATAL) << "CopyTrainedLayersFromHDF5 requires hdf5;"
                 << " compile with USE_HDF5.";
    #endif  // USE_HDF5
    }
    
    //将当前net的所有LayerParameter拷贝至NetParameter类型的变量中
    template <typename Dtype>
    void Net<Dtype>::ToProto(NetParameter* param, bool write_diff) const {
      param->Clear();           //先清空所有数据
      param->set_name(name_);   //当前net的名称存入param中
      // Add bottom and top
      DLOG(INFO) << "Serializing " << layers_.size() << " layers";
      for (int i = 0; i < layers_.size(); ++i) {    //处理每一层
        LayerParameter* layer_param = param->add_layer();   //在param中添加新的LayerParameter消息,返回其指针
        layers_[i]->ToProto(layer_param, write_diff);       //将当前net中的layer数据拷贝至layer_param消息中
      }
    }
    
    //将当前net的所有LayerParameter写入到hdf5类型的filename文件中
    template <typename Dtype>
    void Net<Dtype>::ToHDF5(const string& filename, bool write_diff) const {
    // This code is taken from https://github.com/sh1r0/caffe-android-lib
    #ifdef USE_HDF5
      hid_t file_hid = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);  //创建hdf5文件
      CHECK_GE(file_hid, 0) << "Couldn't open " << filename << " to save weights.";
      hid_t data_hid = H5Gcreate2(file_hid, "data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);   //创建"data"数据集
      CHECK_GE(data_hid, 0) << "Error saving weights to " << filename << ".";
      hid_t diff_hid = -1;
      if (write_diff) {
        diff_hid = H5Gcreate2(file_hid, "diff", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); //如果需要存梯度信息,则再创建"diff"数据集
        CHECK_GE(diff_hid, 0) << "Error saving weights to " << filename << ".";
      }
      for (int layer_id = 0; layer_id < layers_.size(); ++layer_id) {   //处理每一层
        const LayerParameter& layer_param = layers_[layer_id]->layer_param(); //当前网络的第layer_id层的layer参数
        string layer_name = layer_param.name();         //layer的名称
        hid_t layer_data_hid = H5Gcreate2(data_hid, layer_name.c_str(),
            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);     //使用该名称在"data"中创建数据集
        CHECK_GE(layer_data_hid, 0) << "Error saving weights to " << filename << ".";
        hid_t layer_diff_hid = -1;
        if (write_diff) {
          layer_diff_hid = H5Gcreate2(diff_hid, layer_name.c_str(),
              H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);   //需要写梯度,则再在"diff"中创建数据集
          CHECK_GE(layer_diff_hid, 0) << "Error saving weights to " << filename << ".";
        }
        int num_params = layers_[layer_id]->blobs().size();   //该layer中参数blob的个数
        for (int param_id = 0; param_id < num_params; ++param_id) {
          ostringstream dataset_name;
          dataset_name << param_id;
          const int net_param_id = param_id_vecs_[layer_id][param_id];  //第layer_id层第param_id个参数在params_的索引
          if (param_owners_[net_param_id] == -1) {
            // Only save params that own themselves
            //源参数,则在layer_data_hid中创建dataset_name数据集,并将参数blob的data_数据写入其中
            hdf5_save_nd_dataset<Dtype>(layer_data_hid, dataset_name.str(), *params_[net_param_id]);
          }
          if (write_diff) {
            // Write diffs regardless of weight-sharing
            //在layer_diff_hid中创建dataset_name数据集,并将参数blob的diff_数据写入其中
            hdf5_save_nd_dataset<Dtype>(layer_diff_hid, dataset_name.str(),
                *params_[net_param_id], true);
          }
        }
        H5Gclose(layer_data_hid);   //关闭
        if (write_diff) {
          H5Gclose(layer_diff_hid);
        }
      }
      H5Gclose(data_hid);   //各种关闭
      if (write_diff) {
        H5Gclose(diff_hid);
      }
      H5Fclose(file_hid);
    // This code is taken from https://github.com/sh1r0/caffe-android-lib
    #else
      LOG(FATAL) << "ToHDF5 requires hdf5; compile with USE_HDF5.";
    #endif  // USE_HDF5
    }
    
    template <typename Dtype>
    void Net<Dtype>::Update() {             //网络更新,把网络中的所有可学习参数blob更新一次
      for (int i = 0; i < learnable_params_.size(); ++i) {
        learnable_params_[i]->Update();   //调用blob类的函数,data_ = Dtype(-1) * diff_ + data_
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::ClearParamDiffs() {    //梯度清空,清空网络中所有可学习参数blob的diff_数据
      for (int i = 0; i < learnable_params_.size(); ++i) {    //处理每个可学习参数
        Blob<Dtype>* blob = learnable_params_[i];
        switch (Caffe::mode()) {    //当前caffe运行的模式
        case Caffe::CPU:
          caffe_set(blob->count(), static_cast<Dtype>(0), blob->mutable_cpu_diff());  //将blob中diff_在cpu上的数据全部置为0
          break;
        case Caffe::GPU:
    #ifndef CPU_ONLY
          caffe_gpu_set(blob->count(), static_cast<Dtype>(0), blob->mutable_gpu_diff());  //将diff_在gpu上的数据全部置为0
    #else
          NO_GPU;
    #endif
          break;
        }
      }
    }
    
    template <typename Dtype>
    void Net<Dtype>::ShareWeights() {   //layer间的参数共享,将所有共享参数的data_和diff_数据指针指向对应的源参数的对应数据
      for (int i = 0; i < params_.size(); ++i) {    //网络中的所有参数
        if (param_owners_[i] < 0) { continue; }     //源参数才为-1,不处理
        params_[i]->ShareData(*params_[param_owners_[i]]);  //共享参数,则将源参数的data_和diff_指针传给当前参数
        params_[i]->ShareDiff(*params_[param_owners_[i]]);
      }
    }
    
    template <typename Dtype>
    bool Net<Dtype>::has_blob(const string& blob_name) const {      //判断网络中是否存在名为blob_name的输出blob
      return blob_names_index_.find(blob_name) != blob_names_index_.end();
    }
    
    template <typename Dtype>
    const shared_ptr<Blob<Dtype> > Net<Dtype>::blob_by_name(    //返回名为blob_name的blob的数据指针
        const string& blob_name) const {
      shared_ptr<Blob<Dtype> > blob_ptr;
      if (has_blob(blob_name)) {    //网络中是否存在该名称的blob
        blob_ptr = blobs_[blob_names_index_.find(blob_name)->second]; //由名称确定在blobs_中的位置,返回索引
      } else {
        blob_ptr.reset((Blob<Dtype>*)(NULL));
        LOG(WARNING) << "Unknown blob name " << blob_name;    //不存在,警告
      }
      return blob_ptr;
    }
    
    template <typename Dtype>
    bool Net<Dtype>::has_layer(const string& layer_name) const {    //判断网络中是否存在名为layer_name的层
      return layer_names_index_.find(layer_name) != layer_names_index_.end();
    }
    
    template <typename Dtype>
    const shared_ptr<Layer<Dtype> > Net<Dtype>::layer_by_name(    //返回名为layer_name的layer的指针
        const string& layer_name) const {
      shared_ptr<Layer<Dtype> > layer_ptr;
      if (has_layer(layer_name)) {    //网络中是否存在该名称的layer
        layer_ptr = layers_[layer_names_index_.find(layer_name)->second]; //找到在layers_中的位置,返回其指针
      } else {
        layer_ptr.reset((Layer<Dtype>*)(NULL));
        LOG(WARNING) << "Unknown layer name " << layer_name;  //未找到,警告
      }
      return layer_ptr;
    }
    

    小结

    1. Protocol库中定义了两种序列化数据的格式,一种为文本类型(textual类型),caffe中 ".prototxt" 文件均是此类型,用户可以用来定义网络参数(如train_val.prototxt中设置的是NetParameter类型数据)和求解器参数(如solver.prototxt中设置的是SolverParameter类型数据)。另一种为二进制类型(binary类型),caffe中的模型快照文件".caffemodel"和求解器快照文件".solverstate"均是此类型,一般用来存储数据量较大且无需用户修改的数据,如网络中的所有blob类型的可学习参数等。

    参考

    https://confluence.hdfgroup.org/display/HDF5
    https://developers.google.com/protocol-buffers
    (链接打不开的话则需要某科学上网工具)
    Caffe的源码笔者是第一次阅读,一边阅读一边记录,对代码的理解和分析可能会存在错误或遗漏,希望各位读者批评指正,谢谢支持!

  • 相关阅读:
    September 29th 2017 Week 39th Friday
    September 28th 2017 Week 39th Thursday
    September 27th 2017 Week 39th Wednesday
    September 26th 2017 Week 39th Tuesday
    September 25th 2017 Week 39th Monday
    September 24th 2017 Week 39th Sunday
    angular2 学习笔记 ( Form 表单 )
    angular2 学习笔记 ( Component 组件)
    angular2 学习笔记 ( Http 请求)
    angular2 学习笔记 ( Router 路由 )
  • 原文地址:https://www.cnblogs.com/Relu110/p/12044371.html
Copyright © 2011-2022 走看看