Caffe 代碼學(xué)習(xí) 4: Layer Factory

工廠模式: Layer Factory的設(shè)計(jì)用到了設(shè)計(jì)模式里的工廠模式. 我們先來看兩個(gè)很重要的macro definition. 在宏定義中, #是把參數(shù)字符串化矩屁,##是連接兩個(gè)參數(shù)成為一個(gè)整體 (參考這里). 那么第一個(gè)宏定義 REGISTER_LAYER_CLASS實(shí)際上是為每一個(gè)layer創(chuàng)建一個(gè)creator函數(shù).

#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)

這個(gè)函數(shù)最后調(diào)用了另一個(gè)宏定義, REGISTER_LAYER_CREATOR. 我們來看下他是怎么定義的.

#define REGISTER_LAYER_CREATOR(type, creator)                                  \
  static LayerRegisterer<float> g_creator_f_##type(#type, creator<float>);     \
  static LayerRegisterer<double> g_creator_d_##type(#type, creator<double>)    \

以EuclideanLossLayer為例, 在該類的最后, 調(diào)用 REGISTER_LAYER_CLASS(EuclideanLoss);來注冊(cè)這一個(gè)類. 通過上面的兩個(gè)宏定義, 實(shí)際上是"創(chuàng)建"了下面的函數(shù).

template <typename Dtype>   
// create一個(gè)EuclideanLossLayer對(duì)象, 并返回對(duì)象指針                                                 
shared_ptr<Layer<Dtype> > Creator_EuclideanLossLayer(const LayerParameter& param) 
{                                                                            
  return shared_ptr<Layer<Dtype> >(new EuclideanLossLayer<Dtype>(param));           
}                                                                                       \
static LayerRegisterer<float> g_creator_f_EuclideanLoss("EuclideanLoss", Creator_EuclideanLossLayer<float>);     
static LayerRegisterer<double> g_creator_d_EuclideanLoss("EuclideanLoss", Creator_EuclideanLossLayer<double>);

LayerRegistry

LayerRegistry里用map數(shù)據(jù)結(jié)構(gòu), 維護(hù)一個(gè)CreatorRegistry list, 保存各個(gè)layer的creator的函數(shù)句柄: key 是類名, val 是對(duì)應(yīng)的creator函數(shù)句柄.

  typedef shared_ptr<Layer<Dtype> > (*Creator)(const LayerParameter&); // 定義類型 Creator為函數(shù)句柄
  typedef std::map<string, Creator> CreatorRegistry;  // 定義一個(gè) <LayerName, CreatorHandler>的Creator列表

  static CreatorRegistry& Registry() {
    static CreatorRegistry* g_registry_ = new CreatorRegistry();
    return *g_registry_;
  }  // 只創(chuàng)建一個(gè)列表實(shí)例

AddCreator函數(shù)用來向Registry列表中添加一組<layername, creatorhandlr>

  // Adds a creator.
  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;
  }

CreateLayer用于根據(jù)輸入的LayerParam, 獲取當(dāng)前Layer的layername, 再去registry里通過layername獲取對(duì)應(yīng)的creator來創(chuàng)建layer

  // Get a layer using a LayerParameter.
  static shared_ptr<Layer<Dtype> > CreateLayer(const LayerParameter& param) {
    if (Caffe::root_solver()) {
      LOG(INFO) << "Creating layer " << param.name();
    }
    const string& type = param.type();  // 獲取layer name
    CreatorRegistry& registry = Registry();
    CHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type
        << " (known types: " << LayerTypeListString() << ")";
    return registry[type](param);   //  根據(jù)layer name, 調(diào)用相應(yīng)creator函數(shù) (registry里存的是函數(shù)句柄)
  }

LayerRegisterer

這個(gè)類只有一個(gè)方法, 即其構(gòu)造函數(shù). 構(gòu)造函數(shù)只做一件事: 在LayerRegistry的registry list中, 添加一個(gè)layer的creator

template <typename Dtype>
class LayerRegisterer {
 public:
  LayerRegisterer(const string& type,
                  shared_ptr<Layer<Dtype> > (*creator)(const LayerParameter&)) {
    // LOG(INFO) << "Registering layer type: " << type;
    LayerRegistry<Dtype>::AddCreator(type, creator);
  }
};

再次總結(jié): 創(chuàng)建一個(gè)新layer后, 先寫一個(gè)靜態(tài)函數(shù)創(chuàng)建并返回該函數(shù)的對(duì)象 (Creator), 然后創(chuàng)建對(duì)應(yīng)的LayerRegisterer對(duì)象, 該對(duì)象在構(gòu)造時(shí)會(huì)調(diào)用 LayerRegistry 中的 AddCreator, 將該layer 注冊(cè)到 registy中去.

在調(diào)用時(shí), xxxxx (補(bǔ)充net, solver 相關(guān)內(nèi)容).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绩卤,隨后出現(xiàn)的幾起案子叁鉴,更是在濱河造成了極大的恐慌土涝,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幌墓,死亡現(xiàn)場(chǎng)離奇詭異但壮,居然都是意外死亡冀泻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門蜡饵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弹渔,“玉大人,你說我怎么就攤上這事溯祸≈ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵焦辅,是天一觀的道長博杖。 經(jīng)常有香客問我,道長筷登,這世上最難降的妖魔是什么剃根? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮前方,結(jié)果婚禮上狈醉,老公的妹妹穿的比我還像新娘。我一直安慰自己惠险,他們只是感情好苗傅,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著莺匠,像睡著了一般金吗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上趣竣,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音旱物,去河邊找鬼遥缕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宵呛,可吹牛的內(nèi)容都是我干的单匣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼宝穗,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼户秤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逮矛,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤鸡号,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后须鼎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲸伴,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡府蔗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了汞窗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姓赤。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖仲吏,靈堂內(nèi)的尸體忽然破棺而出不铆,到底是詐尸還是另有隱情,我是刑警寧澤裹唆,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布誓斥,位于F島的核電站,受9級(jí)特大地震影響品腹,放射性物質(zhì)發(fā)生泄漏岖食。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一舞吭、第九天 我趴在偏房一處隱蔽的房頂上張望泡垃。 院中可真熱鬧,春花似錦羡鸥、人聲如沸蔑穴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽存和。三九已至,卻和暖如春衷旅,著一層夾襖步出監(jiān)牢的瞬間捐腿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工柿顶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茄袖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓嘁锯,卻偏偏與公主長得像宪祥,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子家乘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 我們來分析一下Caffe中的源程序蝗羊,來探究一下深度學(xué)習(xí)的奧秘。作為一個(gè)菜雞程序員仁锯,我表示壓力有點(diǎn)大耀找! 我們會(huì)發(fā)現(xiàn),...
    JohnHush閱讀 551評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理扑馁,服務(wù)發(fā)現(xiàn)涯呻,斷路器凉驻,智...
    卡卡羅2017閱讀 134,626評(píng)論 18 139
  • 轉(zhuǎn)載:http://www.reibang.com/p/32fcadd12108 每個(gè)UIView有一個(gè)伙伴稱為l...
    F麥子閱讀 6,167評(píng)論 0 13
  • 本文從CSDN上轉(zhuǎn)移過來:http://blog.csdn.net/mounty_fsc/article/deta...
    漚江一流閱讀 1,136評(píng)論 0 0
  • 人生是條流水涝登,我卻無法做到細(xì)水長流⌒ё纾——題記 喜歡翻空間的我只要一有動(dòng)態(tài)就是一遍刷胀滚,曾經(jīng)有人這樣問了我一句,也許也...
    薰衣草的夏季閱讀 436評(píng)論 0 0