caffe之儲存和讀入caffmodel檔案
一、caffe如何將卷積層或網路層的權值blob給儲存下來的?
首先Solver類在Step(intiters)中呼叫了Snapshot()函式,在voidSolver<Dtype>::Snapshot()函式中能看到儲存caffemodel檔案的重要函式 SnapshotToBinaryProto(),該函式詳細如下:
可看到該函式裡初始化了NetParameternet_param ; 之後呼叫net_->ToProto(&net_param,param_.snapshot_diff())進行初始化, 該函式詳細如下:
在該函式中初始化了NetParameter 類物件net_param,
可看到在這個函式裡,各個層的 layer_param又將使用add_blobs()將 層裡的所有blob給載入進去,看看 blobs_[i]的 ToProto函式:
可看到指向BlobProto類指標的proto(來自layer_param的add_blobs())
綜上所述,一個net_的所有層裡的所有blob的data資料將被用於初始化 NetParameter類物件net_param, 又呼叫了WriteProtoToBinaryFile(net_param,model_filename) 將其中重要的權參儲存為caffemodel檔案,如下所示:
實質是呼叫了下面這個,最終儲存為caffemodel檔案
二、caffe是如何讀入caffemodel檔案的?
caffemodel檔案通常被用於初始化Net類物件,使用Net
對於caffemodel檔案,將被呼叫voidCopyTrainedLayersFromBinaryProto(const string trained_filename);該函式如下:
可看到內部呼叫了ReadNetParamsFromBinaryFileOrDie(trained_filename,¶m) 初始化了
NetParameter類物件param;param 又將被用於初始化Net類的中各個層的blob;
先看看ReadNetParamsFromBinaryFileOrDie(trained_filename,¶m) ,定義在 upgrade_proto.cpp:
內部主要呼叫了ReadProtoFromBinaryFile(param_file,param) , 該函式具體如下:
看看定義在io.cpp的函式ReadProtoFromBinaryFile:
大致也即是從caffemodel檔案寫入proto, 回到voidCopyTrainedLayersFromBinaryProto(const string trained_filename)函式:
看下另一個函式CopyTrainedLayersFrom(param)的實現:
可由該函式得到,已被初始化的NetParameter類物件 param將被用於初始化Net類中各個層的blob;具體方法是先遍歷 param中的各個LayerParameter物件 ,先找到名字相同的層的層id號,再獲取這個id號的層的blob,再判斷該blob的形狀是否與LayerParameter物件中的blob一致,如果一致則開始呼叫FromProto複製,否則會報錯,FromProto函式如下:
在Net類的各個層初始化的時候均會呼叫setup函式,在這個時候會對blobs_進行判斷,如果是已初始化的則不進行權值引數填充,例如卷積層,在 base_conv_layer.cpp中的LayerSetUp函式中有: