caffe中所有的layer都是類的結構,它們的構造相關的函式都註冊在乙個全域性變數g_registry_ 中。
首先這個變數的型別 creatorregistry是乙個map定義,
public:
typedef shared_ptr> (*creator)(const layerparameter&);
typedef std::mapcreatorregistry;
注意creator會根據資料型別(如float,double)的不同而不同,
該定義對應的變數是g_registry_(實際是對應float有乙個,對應double有乙個)
層的註冊函式是通過下邊這個registry() 函式實現的,
static creatorregistry& registry()
注意static 這個關鍵字,這是乙個靜態結構,在caffe程式啟動時(通過register_layer_class(……)這個巨集)建立g_registry_ ,(因為是static,所以只在建立時執行一次),以後各個層通過register_layer_class(……)這個巨集呼叫時,返回的是註冊到g_registry_的具體的層。
當然我們可以看一眼這個巨集定義,
template class layerregisterer
};#define register_layer_creator(type, creator) \
static layerregistererg_creator_f_##type(#type, creator); \
static layerregistererg_creator_d_##type(#type, creator) \
#define register_layer_class(type) \
template \
shared_ptr> creator_##type##layer(const layerparameter& param) \
\register_layer_creator(type, creator_##type##layer)
} // namespace caffe
比如對absval層,register_layer_class 這個巨集首先定義了乙個creator_absvallayer函式,然後通過巨集
register_layer_creator(type, creator_absvallayer)定義了乙個layerregisterer(實際是兩個layerregisterer,根據資料型別是float還是double,各定義了乙個)靜態例項,這個定義相當根據資料型別於立即執行了
addcreateor("convolution", creator_absvallayer)這個函式,
// adds a creator.
static void addcreator(const string& type, creator creator)
也就是把這個creator_absvallayer函式註冊到陣列
registry["convolution"] = creator_absvallayer;
如果我們把最終所有類的註冊展開的話,會是下面的形式(注意這個是對應資料型別為float的registry,對應資料型別為double的也有乙個同樣結構的registery)
在構造網路時,net::init函式中的for迴圈會根據網路的型別逐層構建,通過
layers_.push_back(layerregistry::createlayer(layer_param));
呼叫
// get a layer using a layerparameter.
static shared_ptr> createlayer(const layerparameter& param)
const string& type = param.type();
creatorregistry& registry = registry();
check_eq(registry.count(type), 1) << "unknown layer type: " << type
<< " (known types: " << layertypeliststring() << ")";
return registry[type](param);
}
完成這個layer的建設工作。當然,取決於不同的層,呼叫函式是不同的,例如對convolution層,呼叫函式是
shared_ptr> getconvolutionlayer(const layerparameter& param)
以absval為例,這個createlayer先是得到型別type=「absval」,然後得到registry也就該類對應的註冊資訊,最後通過registry[type](param)例項化absval這個類。
另外,值得注意的一點是,像convolution這樣不能直接自己構造的類(因為有gpu和cpu模式),註冊的建構函式有所不同,如
register_layer_creator(convolution, getconvolutionlayer);
caffe原始碼解析
目錄目錄 簡單介紹 主要函式readprotofromtextfile 函式 writeprotototextfile 函式 readprotofrombinaryfile 函式 writeprototobinaryfile 函式 readimagetocvmat 函式 matchext 函式 cv...
caffe原始碼 卷積層
input 3 5 5 c h w pading 1 步長 2 卷積核 2 3 3 3 n c k k output 2 3 3 c h w 如下圖所示 首先需要理解caffe裡面的im2col和col2im 然後 卷積層 其實和 全連線層 差不多了 input 3 4 4 c h w 卷積核 1 ...
caffe原始碼解析 一
用si載入 後 首先從caffe layer的實現看起,不同框架下最大的差異就在於層的實現也決定了層的靈活性 layer可以看成是乙個基類,下面存在data layer,activation neuron layers,vision layer,common layers,loss layer,各個...