Caffe的windows安装和Linux安装在这里就不介绍了,网上有很多很好的教程。
1.Caffe框架的入口为./tools/caffe.cpp的main()
(1)框架使用gflag对命令行参数进行解析
DEFINE_type(p1,p2,p3)定义了需要从命令行传递参数的变量:p1为变量,p2默认值,p3为解释。GlobalInit()函数中调用了ParseCommandLineFlags(),该函数是为了解析命令行参数,执行完了该函数,就可以在代码中使用FLAGS_p1使用该参数了,SetUsageMessage函数用于设置命令行帮助信息(-help)。
DEFINE_string(gpu, "",
"Optional; run in GPU mode on given device IDs separated by ','."
"Use '-gpu all' to run on all available GPUs. The effective training "
"batch size is multiplied by the number of devices.");
DEFINE_string(solver, "",
"The solver definition protocol buffer text file.");
DEFINE_string(model, "",
"The model definition protocol buffer text file.");
DEFINE_string(phase, "",
"Optional; network phase (TRAIN or TEST). Only used for 'time'.");
DEFINE_int32(level, 0,
"Optional; network level.");
DEFINE_string(stage, "",
"Optional; network stages (not to be confused with phase), "
"separated by ','.");
DEFINE_string(snapshot, "",
"Optional; the snapshot solver state to resume training.");
DEFINE_string(weights, "",
"Optional; the pretrained weights to initialize finetuning, "
"separated by ','. Cannot be set simultaneously with snapshot.");
DEFINE_int32(iterations, 50,
"The number of iterations to run.");
DEFINE_string(sigint_effect, "stop",
"Optional; action to take when a SIGINT signal is received: "
"snapshot, stop or none.");
DEFINE_string(sighup_effect, "snapshot",
"Optional; action to take when a SIGHUP signal is received: "
"snapshot, stop or none.");
// Set version
gflags::SetVersionString(AS_STRING(CAFFE_VERSION));
// Usage message.
gflags::SetUsageMessage("command line brew\n"
"usage: caffe <command> <args>\n\n"
"commands:\n"
" train train or finetune a model\n"
" test score a model\n"
" device_query show GPU diagnostic information\n"
" time benchmark model execution time");
// Run tool or show usage.
caffe::GlobalInit(&argc, &argv);
(2)各执行函数的注册
在train() test() time() device_query()四个函数定义的后面,各自通过注册器RegisterBrewFunction("xxx") 来注册函数到容器里。(RegisterBrewFunction(train))
// A simple registry for caffe commands.
typedef int (*BrewFunction)(); // 定义函数指针类型 (指向参数为空、返回值为int的函数)
typedef std::map<caffe::string, BrewFunction> BrewMap;
BrewMap g_brew_map;#define RegisterBrewFunction(func) \ #注册器
namespace { \
class __Registerer_##func { \
public: /* NOLINT */ \
__Registerer_##func() { \
g_brew_map[#func] = &func; \ #将每一个<函数名,函数指针>注入g_brew_map
} \
}; \
__Registerer_##func g_registerer_##func; \
}
argv[1]) = "train"
return GetBrewFunction(caffe::string(argv[1]))(); //return(train())
2.进入具体的执行函数train()
(1)根据FLAGS_solver读取超参信息
caffe::SolverParameter solver_param;
caffe::ReadSolverParamsFromTextFileOrDie(FLAGS_solver, &solver_param);-->>ReadSolverParamsFromTextFileOrDie() #upgrade_proto.cpp
-->> bool ReadProtoFromTextFile(const string& filename, Message* proto) #io.cpp
(2)通过SolverFactory创建一个Solver类
shared_ptr<caffe::Solver<float> > solver(caffe::SolverRegistry<float>::CreateSolver(solver_param));
(3)执行迭代
solver->Solve();