以訓練流程的構建爲例:
首先在caffe.cpp的train()中調用caffe::SolverRegistry<float>::CreateSolver(solver_param):
shared_ptr<caffe::Solver<float> >
solver(caffe::SolverRegistry<float>::CreateSolver(solver_param));
即通過solover_factory.hpp中的工廠機制(registry[type](param))new 一個具體的已註冊的Solver的子類(例如new SGDSolver<Dtype>(param))的實例。而在SGDSolver的構造函數中,首先使用SolverParameter來初始化父類Solver,如下:
explicit SGDSolver(const SolverParameter& param)
: Solver<Dtype>(param) { PreSolve(); }
而在父類Solver的構造函數中調用Slover::Init(),在Slover::Init()中又調用Slover::InitTrainNet(),而在InitTrainNet()中首先從SolverParameter參數中解析出Net所需要的參數,
if (param_.has_net()) {
LOG_IF(INFO, Caffe::root_solver())
<< "Creating training net from net file: " << param_.net();
ReadNetParamsFromTextFileOrDie(param_.net(), &net_param);
}
然後再通過net_.reset(new Net<Dtype>(net_param)) new一個Net網絡實例:
if (Caffe::root_solver()) {
net_.reset(new Net<Dtype>(net_param));
} else {
net_.reset(new Net<Dtype>(net_param, root_solver_->net_.get()));
}
進入到Net類中,在Net的構造函數中調用Net::Init(), 在Net::Init()中的for循環中根據總層數逐次調用LayerRegistry<Dtype>::CreateLayer(layer_param):
layers_.push_back(LayerRegistry<Dtype>::CreateLayer(layer_param));
即通過layer_factory.cpp中的工廠機制new 一個具體的已註冊的layer層,這裏是根據Net傳進來的layer_param獲取到層類型再調用registry[type](param)。例如首先是DataLayer層, 使用Net中傳進來的該層的參數LayerParameter初始化DataLayer層:
template <typename Dtype>
DataLayer<Dtype>::DataLayer(const LayerParameter& param)
: BasePrefetchingDataLayer<Dtype>(param),
reader_(param) {
}
然後又在Net::Init()中for循環中new 下一層,例如Convolution。Net中new出來的子層都放到layers_隊列中。
另外,每個for循環中,new出一個Layer後,又通過AppendTop()與AppendBottom()等函數將各層的bottom與top以及weight值構建出一個鏈路出來,bottom、top、weight都是Blob結構,這裏一個top就是一個Blob,例如在mnist的Data層(對應於Caffe中的DataLayer層)中一個top: "data"(一個Blob)即表示一個批次的元素,其維度信息爲(64,1,28,28),一個批次爲64張圖片,長寬均爲28。另外一個top: "label",其維度信息爲(64,1),這也是一個Blob。
Net構造函數中new出所有的子層後回到Slover::InitTrainNet()中,Solver用new出來的Net來初始化其成員 shared_ptr<Net<Dtype> > net_; InitTrainNet()構建完訓練網絡後,Slover::Init()又調用Solver<Dtype>::InitTestNets()使用和InitTrainNet()一樣的方法構建測試網絡(即訓練過程中的驗證操作),其成員變量爲vector<shared_ptr<Net<Dtype> > > test_nets_。
以上調用完成後遍回到caffe.cpp的train()中,即完成了Solver、Net、Layer的構建。以上流程說明了,在Caffe中Blob就是磚頭、Layer是牆,Net是大廈,而Solver就是圖紙。