首先查看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);