caffe 代码阅读笔记1

首先查看caffe.cpp里的train函数:

 1 // Train / Finetune a model.  
 2 //训练,微调一个网络模型  
 3 int train() {  
 4   // google的glog库,检查--solver、--snapshot和--weight并输出消息;必须有指定solver,snapshot和weight两者指定其一;  
 5   CHECK_GT(FLAGS_solver.size(), 0) << "Need a solver definition to train.";  
 6   CHECK(!FLAGS_snapshot.size() || !FLAGS_weights.size())  
 7       << "Give a snapshot to resume training or weights to finetune "  
 8       "but not both.";  
 9   
10   caffe::SolverParameter solver_param;  //实例化SolverParameter类,该类保存solver参数和相应的方法  
11   caffe::ReadSolverParamsFromTextFileOrDie(FLAGS_solver, &solver_param); //将-solver指定solver.prototxt文件内容解析到solver_param中  
12   
13   // If the gpus flag is not provided, allow the mode and device to be set  
14   // in the solver prototxt.  
15   // 根据命令参数-gpu或者solver.prototxt提供的信息设置GPU  
16   if (FLAGS_gpu.size() == 0  
17       && solver_param.solver_mode() == caffe::SolverParameter_SolverMode_GPU) {  
18       if (solver_param.has_device_id()) {  
19           FLAGS_gpu = "" +  
20               boost::lexical_cast<string>(solver_param.device_id());    
21       } else {  // Set default GPU if unspecified  
22           FLAGS_gpu = "" + boost::lexical_cast<string>(0);  // boost::lexical_cast(0)是将数值0转换为字符串'“0”;  
23       }  
24   }  
25   
26   // 多GPU下,将GPU编号存入vector容器中(get_gpus()函数通过FLAGS_gpu获取);  
27   vector<int> gpus;  
28   get_gpus(&gpus);  
29   if (gpus.size() == 0) {  
30     LOG(INFO) << "Use CPU.";  
31     Caffe::set_mode(Caffe::CPU);  
32   } else {  
33     ostringstream s;  
34     for (int i = 0; i < gpus.size(); ++i) {  
35       s << (i ? ", " : "") << gpus[i];  
36     }  
37     LOG(INFO) << "Using GPUs " << s.str();  
38 #ifndef CPU_ONLY  
39     cudaDeviceProp device_prop;  
40     for (int i = 0; i < gpus.size(); ++i) {  
41       cudaGetDeviceProperties(&device_prop, gpus[i]);  
42       LOG(INFO) << "GPU " << gpus[i] << ": " << device_prop.name;  
43     }  
44 #endif  
45     solver_param.set_device_id(gpus[0]);  
46     Caffe::SetDevice(gpus[0]);  
47     Caffe::set_mode(Caffe::GPU);  
48     Caffe::set_solver_count(gpus.size());  
49   }  
50     
51   // 处理snapshot, stop or none信号,其声明在include/caffe/util/signal_Handler.h中;  
52   // GetRequestedAction在caffe.cpp中,将‘stop’,‘snapshot’,‘none’转换为标准信号,即解析;  
53   caffe::SignalHandler signal_handler(  
54         GetRequestedAction(FLAGS_sigint_effect),  
55         GetRequestedAction(FLAGS_sighup_effect));  
56   
57   //指向caffe::Solver对象,该对象由CreateSolver创建  
58   shared_ptr<caffe::Solver<float> >  
59       solver(caffe::SolverRegistry<float>::CreateSolver(solver_param));  
60   
61   //solver设置操作函数  
62   solver->SetActionFunction(signal_handler.GetActionFunction());  
63   
64   // 从snapshot或caffemodel中恢复train;  
65   if (FLAGS_snapshot.size()) {  
66     LOG(INFO) << "Resuming from " << FLAGS_snapshot;  
67     solver->Restore(FLAGS_snapshot.c_str());  
68   } else if (FLAGS_weights.size()) {  
69     CopyLayers(solver.get(), FLAGS_weights);  
70   }  
71   
72   if (gpus.size() > 1) {  
73     caffe::P2PSync<float> sync(solver, NULL, solver->param());  
74     sync.Run(gpus);  
75   } else {  
76     LOG(INFO) << "Starting Optimization";  
77     solver->Solve();   // // 初始化完成,开始优化网络  
78   }  
79   LOG(INFO) << "Optimization Done.";  
80   return 0;  
81 }  
82 RegisterBrewFunction(train);  
83   
// Test: score a model.  
//测试网络模型  
int test() {  
  CHECK_GT(FLAGS_model.size(), 0) << "Need a model definition to score.";  
  CHECK_GT(FLAGS_weights.size(), 0) << "Need model weights to score.";  
  
  // Set device id and mode  
  vector<int> gpus;  
  get_gpus(&gpus);  
  if (gpus.size() != 0) {  
    LOG(INFO) << "Use GPU with device ID " << gpus[0];  
#ifndef CPU_ONLY  
    cudaDeviceProp device_prop;  
    cudaGetDeviceProperties(&device_prop, gpus[0]);  
    LOG(INFO) << "GPU device name: " << device_prop.name;  
#endif  
    Caffe::SetDevice(gpus[0]);  
    Caffe::set_mode(Caffe::GPU);  
  } else {  
    LOG(INFO) << "Use CPU.";  
    Caffe::set_mode(Caffe::CPU);  
  }  
  // Instantiate the caffe net.    
  //实例化caffe网络  
  Net<float> caffe_net(FLAGS_model, caffe::TEST);  
  caffe_net.CopyTrainedLayersFrom(FLAGS_weights);  
  LOG(INFO) << "Running for " << FLAGS_iterations << " iterations.";  
  
  vector<int> test_score_output_id;  
  vector<float> test_score;  
  float loss = 0;  
  for (int i = 0; i < FLAGS_iterations; ++i) {  
    float iter_loss;  
    const vector<Blob<float>*>& result =  
        caffe_net.Forward(&iter_loss);  
    loss += iter_loss;  
    int idx = 0;  
    for (int j = 0; j < result.size(); ++j) {  
      const float* result_vec = result[j]->cpu_data();  
      for (int k = 0; k < result[j]->count(); ++k, ++idx) {  
        const float score = result_vec[k];  
        if (i == 0) {  
          test_score.push_back(score);  
          test_score_output_id.push_back(j);  
        } else {  
          test_score[idx] += score;  
        }  
        const std::string& output_name = caffe_net.blob_names()[  
            caffe_net.output_blob_indices()[j]];  
        LOG(INFO) << "Batch " << i << ", " << output_name << " = " << score;  
      }  
    }  
  }  
  loss /= FLAGS_iterations;  
  LOG(INFO) << "Loss: " << loss;  
  for (int i = 0; i < test_score.size(); ++i) {  
    const std::string& output_name = caffe_net.blob_names()[  
        caffe_net.output_blob_indices()[test_score_output_id[i]]];  
    const float loss_weight = caffe_net.blob_loss_weights()[  
        caffe_net.output_blob_indices()[test_score_output_id[i]]];  
    std::ostringstream loss_msg_stream;  
    const float mean_score = test_score[i] / FLAGS_iterations;  
    if (loss_weight) {  
      loss_msg_stream << " (* " << loss_weight  
                      << " = " << loss_weight * mean_score << " loss)";  
    }  
    LOG(INFO) << output_name << " = " << mean_score << loss_msg_stream.str();  
  }  
  
  return 0;  
}  
RegisterBrewFunction(test);