日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Caffe中Layer注册机制

發(fā)布時間:2023/11/27 生活经验 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Caffe中Layer注册机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Caffe內(nèi)部維護一個注冊表用于查找特定Layer對應的工廠函數(shù)(Layer Factory的設(shè)計用到了設(shè)計模式里的工廠模式)。Caffe的Layer注冊表是一組鍵值對(key, value)( LayerRegistry里用map數(shù)據(jù)結(jié)構(gòu)維護一個CreatorRegistry list, 保存各個Layer的creator的函數(shù)句柄),key為Layer的類型(Layer類名去掉后面的”Layer”字符串),value為其對應的工廠函數(shù)(creator的函數(shù)句柄):

typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&);
typedef std::map<string, Creator> CreatorRegistry;

注冊表類型為CreatorRegistry,實際類型為std::map<string, Creator>??梢酝ㄟ^Registry 函數(shù)獲取注冊表的全局單例。而注冊的過程就是一個map操作。

Caffe是通過宏定義的方式注冊各種Layer,在編譯階段自動執(zhí)行宏替換就注冊了所有的Layer. 每一個Layer type只允許注冊一次。使用兩組宏來控制Layer的注冊:

#define REGISTER_LAYER_CREATOR(type, creator)                                  \LayerRegisterer<float> g_creator_f_##type(#type, creator<float>);     \LayerRegisterer<double> g_creator_d_##type(#type, creator<double>)    \#define REGISTER_LAYER_CLASS(type)                                             \template <typename Dtype>                                                    \shared_ptr<Layer<Dtype> > Creator_##type##Layer(const LayerParameter& param) \{                                                                            \return shared_ptr<Layer<Dtype> >(new type##Layer<Dtype>(param));           \}                                                                            \REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)

REGISTER_LAYER_CLASS宏可以實現(xiàn)將指定Layer注冊到全局注冊表中,首先定義一個工廠函數(shù)用來產(chǎn)生Layer對象,然后調(diào)用REGISTER_LAYER_CREATOR將工廠函數(shù)和Layer的類型名進行注冊,支持兩種Layer的數(shù)據(jù)類型,float和double。兩個變量一個對應float,一個對應double,這兩個變量的初始化,也就是它們的構(gòu)造函數(shù)實際上完成Layer的注冊動作。REGISTER_LAYER_CLASS實際上是為每一個Layer創(chuàng)建一個creator函數(shù).

LayerRegisterer對象初始化時(會調(diào)用LayerRegisterer類構(gòu)造函數(shù))實際上又是調(diào)用LayerRegistry類的靜態(tài)方法 AddCreator函數(shù)。

以下是對Caffe code中l(wèi)ayer_factory.hpp文件的注釋:

/*** @brief A layer factory that allows one to register layers.* During runtime, registered layers could be called by passing a LayerParameter* protobuffer to the CreateLayer function:**     LayerRegistry<Dtype>::CreateLayer(param);** There are two ways to register a layer. Assuming that we have a layer like:**   template <typename Dtype>*   class MyAwesomeLayer : public Layer<Dtype> {*     // your implementations*   };** and its type is its C++ class name, but without the "Layer" at the end* ("MyAwesomeLayer" -> "MyAwesome").** If the layer is going to be created simply by its constructor, in your c++* file, add the following line:**    REGISTER_LAYER_CLASS(MyAwesome);** Or, if the layer is going to be created by another creator function, in the* format of:**    template <typename Dtype>*    Layer<Dtype*> GetMyAwesomeLayer(const LayerParameter& param) {*      // your implementation*    }** (for example, when your layer has multiple backends, see GetConvolutionLayer* for a use case), then you can register the creator function instead, like** REGISTER_LAYER_CREATOR(MyAwesome, GetMyAwesomeLayer)** Note that each layer type should only be registered once.*/#ifndef CAFFE_LAYER_FACTORY_H_
#define CAFFE_LAYER_FACTORY_H_#include <map>
#include <string>#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"namespace caffe {template <typename Dtype>
class Layer;// LayerRegistry:注冊類,將每一個Layer的type(std::string)和對應的creator(函數(shù)指針)存放到一個map中
template <typename Dtype>
class LayerRegistry {public:// LayerRegistry里用map數(shù)據(jù)結(jié)構(gòu), 維護一個CreatorRegistry list, 保存各個layer的creator的函數(shù)句柄typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&); // 函數(shù)指針,返回Layer<Dtype>類型的指針typedef std::map<string, Creator> CreatorRegistry;// 獲取注冊表,內(nèi)部注冊表,靜態(tài)函數(shù),僅第一次調(diào)用時會new,其它直接returnstatic CreatorRegistry& Registry() { // 只創(chuàng)建一個map實例// 全局靜態(tài)變量(map實例)static CreatorRegistry* g_registry_ = new CreatorRegistry();return *g_registry_;}// Adds a creator.// AddCreator函數(shù)用來向Registry列表中添加一組<type, creator>// 向map中加入一個映射static void AddCreator(const string& type, Creator creator) {CreatorRegistry& registry = Registry();CHECK_EQ(registry.count(type), 0)<< "Layer type " << type << " already registered.";registry[type] = creator;}// Get a layer using a LayerParameter.// 在net.cpp中會被調(diào)用,在初始化整個網(wǎng)絡的時候會根據(jù)參數(shù)文件中的層的類型去創(chuàng)建該層的實例static shared_ptr<Layer<Dtype> > CreateLayer(const LayerParameter& param) {if (Caffe::root_solver()) {LOG(INFO) << "Creating layer " << param.name();}const string& type = param.type(); // 從LayerParameter中獲得字符串typeCreatorRegistry& registry = Registry(); // 獲取注冊表指針// 驗證是否查找到給定type的creatorCHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type<< " (known types: " << LayerTypeList() << ")";return registry[type](param); // 根據(jù)layer name, 調(diào)用相應creator函數(shù)}private:// Layer registry should never be instantiated - everything is done with its// static variables.// 禁止實例化LayerRegistry() {}// 返回layer typestatic string LayerTypeList() {CreatorRegistry& registry = Registry(); // 獲取注冊表指針string layer_types;// 遍歷注冊表for (typename CreatorRegistry::iterator iter = registry.begin();iter != registry.end(); ++iter) {if (iter != registry.begin()) {layer_types += ", ";}layer_types += iter->first;}return layer_types;}
};// LayerRegisterer:Layer注冊器,供后面的宏使用
template <typename Dtype>
class LayerRegisterer {public:// 向LayerRegistry的registry list中, 添加一個layer的creatorLayerRegisterer(const string& type,shared_ptr<Layer<Dtype> > (*creator)(const LayerParameter&)) {// LOG(INFO) << "Registering layer type: " << type;LayerRegistry<Dtype>::AddCreator(type, creator);}
};// 通過宏定義注冊各種Layer
// 將創(chuàng)建layer對象的函數(shù)指針加入map
#define REGISTER_LAYER_CREATOR(type, creator)                                  \LayerRegisterer<float> g_creator_f_##type(#type, creator<float>);     \LayerRegisterer<double> g_creator_d_##type(#type, creator<double>)    \#define REGISTER_LAYER_CLASS(type)                                             \template <typename Dtype>                                                    \shared_ptr<Layer<Dtype> > Creator_##type##Layer(const LayerParameter& param) \{                                                                            \return shared_ptr<Layer<Dtype> >(new type##Layer<Dtype>(param));           \}                                                                            \REGISTER_LAYER_CREATOR(type, Creator_##type##Layer)}  // namespace caffe#endif  // CAFFE_LAYER_FACTORY_H_
以下是用于獲取所有層名的函數(shù):

#include "funset.hpp"
#include "common.hpp"int get_layer_type_list()
{caffe::LayerRegistry<double>::CreatorRegistry& registry = caffe::LayerRegistry<double>::Registry();std::vector<std::string> layers_list;for (caffe::LayerRegistry<double>::CreatorRegistry::iterator iter = registry.begin(); iter != registry.end(); ++iter) {layers_list.push_back(iter->first);}fprintf(stdout, "layer count: %d\n", layers_list.size());for (int i = 0; i < layers_list.size(); i++) {fprintf(stdout, "%d:    %s\n", i+1, layers_list[i].c_str());}return 0;
}
執(zhí)行結(jié)果如下:


GitHub: https://github.com/fengbingchun/Caffe_Test

總結(jié)

以上是生活随笔為你收集整理的Caffe中Layer注册机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。