(Caffe,LeNet)網(wǎng)絡(luò)訓(xùn)練流程(二)

本文從CSDN上轉(zhuǎn)移過來:
http://blog.csdn.net/mounty_fsc/article/details/51090114

在訓(xùn)練lenet的train_lenet.sh中內(nèi)容為:

./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt

由此可知,訓(xùn)練網(wǎng)咯模型是由tools/caffe.cpp生成的工具caffe在模式train下完成的淌友。
初始化過程總的來說,從main()train()中創(chuàng)建Solver跺讯,在Solver中創(chuàng)建Net,在Net中創(chuàng)建Layer.

1 程序入口

  • 找到caffe.cppmain函數(shù)中殉农,通過GetBrewFunction(caffe::string(argv[1]))()調(diào)用執(zhí)行train()函數(shù)刀脏。
  • train中,通過參數(shù)-examples/mnist/lenet_solver.prototxtsolver參數(shù)讀入solver_param中。
  • 隨后注冊并定義solver的指針(見第2節(jié))
      shared_ptr<caffe::Solver<float> > 
    

solver(caffe::SolverRegistry<float>::CreateSolver(solver_param))
```

  • 調(diào)用solverSolver()方法超凳。多個(gè)GPU涉及到GPU間帶異步處理問題(見第3節(jié))
    if (gpus.size() > 1) {
        caffe::P2PSync<float> sync(solver, NULL, solver->param());
        sync.run(gpus);
    } else {
        LOG(INFO) << "Starting Optimization";
        solver->Solve();
    }
    

2 Solver的創(chuàng)建

在1中愈污,Solver的指針solver是通過SolverRegistry::CreateSolver創(chuàng)建的,CreateSolver函數(shù)中值得注意帶是return registry[type](param)

  // Get a solver using a SolverParameter.
  static Solver<Dtype>* CreateSolver(const SolverParameter& param) {
    const string& type = param.type();
    CreatorRegistry& registry = Registry();
    CHECK_EQ(registry.count(type), 1) << "Unknown solver type: " << type
        << " (known types: " << SolverTypeListString() << ")";
    return registry[type](param);
  }

其中:

registry是一個(gè)map<string,Creator>: typedef std::map<string, Creator> CreatorRegistry
其中Creator是一個(gè)函數(shù)指針類型: typedef Solver<Dtype>* (*Creator)(const SolverParameter&)
registry[type]為一個(gè)函數(shù)指針變量轮傍,在Lenet5中暂雹,此處具體的值為 caffe::Creator_SGDSolver<float>(caffe::SolverParameter const&)
其中Creator_SGDSolver在以下宏中定義,
REGISTER_SOLVER_CLASS(SGD)
該宏完全展開得到的內(nèi)容為:

template <typename Dtype>                                                    \
  Solver<Dtype>* Creator_SGDSolver(                                       \
      const SolverParameter& param)                                            \
  {                                                                            \
    return new SGDSolver<Dtype>(param);                                     \
  }                                                                            \
  static SolverRegisterer<float> g_creator_f_SGD("SGD", Creator_SGDSolver<float>);    \
  static SolverRegisterer<double> g_creator_d_SGD("SGD", Creator_SGDSolver<double>)

從上可以看出创夜,registry[type](param)中實(shí)際上調(diào)用了SGDSolver帶構(gòu)造方法杭跪,事實(shí)上,網(wǎng)絡(luò)是在SGDSolver的構(gòu)造方法中初始化的。
SGDSolver的定義如下:

template <typename Dtype>
class SGDSolver : public Solver<Dtype> {
 public:
  explicit SGDSolver(const SolverParameter& param)
      : Solver<Dtype>(param) { PreSolve(); }
  explicit SGDSolver(const string& param_file)
      : Solver<Dtype>(param_file) { PreSolve(); }
......

SGDSolver繼承與Solver<Dtype>涧尿,因而new SGDSolver<Dtype>(param)將執(zhí)行Solver<Dtype>的構(gòu)造函數(shù)系奉,然后調(diào)用自身構(gòu)造函數(shù)。整個(gè)網(wǎng)絡(luò)帶初始化即在這里面完成(詳見本系列博文(三))现斋。

3 Solver::Solve()函數(shù)

在這個(gè)函數(shù)里面喜最,程序執(zhí)行完網(wǎng)絡(luò)的完整訓(xùn)練過程。
核心代碼如下:

template <typename Dtype>
void Solver<Dtype>::Solve(const char* resume_file) {

  Step(param_.max_iter() - iter_);
  //..
    Snapshot();
  //..
  
  // some additional display 
  // ...
}

說明:

  1. 值得關(guān)注的代碼是Step()庄蹋,在該函數(shù)中瞬内,值得了param_.max_iter()輪迭代(10000)
  2. 在Snapshot()中序列化model到文件

4 Solver::Step()函數(shù)

template <typename Dtype>
void Solver<Dtype>::Step(int iters) {

  //10000輪迭代
  while (iter_ < stop_iter) {
  
    // 每隔500輪進(jìn)行一次測試
    if (param_.test_interval() && iter_ % param_.test_interval() == 0
        && (iter_ > 0 || param_.test_initialization())
        && Caffe::root_solver()) {
      // 測試網(wǎng)絡(luò),實(shí)際是執(zhí)行前向傳播計(jì)算loss
      TestAll();
    }

    // accumulate the loss and gradient
    Dtype loss = 0;
    for (int i = 0; i < param_.iter_size(); ++i) {
      // 執(zhí)行反向傳播限书,前向計(jì)算損失loss虫蝶,并計(jì)算loss關(guān)于權(quán)值的偏導(dǎo)
      loss += net_->ForwardBackward(bottom_vec);
    }

    // 平滑loss,計(jì)算結(jié)果用于輸出調(diào)試等
    loss /= param_.iter_size();
    // average the loss across iterations for smoothed reporting
    UpdateSmoothedLoss(loss, start_iter, average_loss);
 
    // 通過反向傳播計(jì)算的偏導(dǎo)更新權(quán)值
    ApplyUpdate();

  }
}

4.1 Solver::TestAll()函數(shù)

TestAll()中倦西,調(diào)用Test(test_net_id)對每個(gè)測試網(wǎng)絡(luò)test_net(不是訓(xùn)練網(wǎng)絡(luò)train_net)進(jìn)行測試能真。在Lenet中,只有一個(gè)測試網(wǎng)絡(luò)扰柠,所以只調(diào)用一次Test(0)進(jìn)行測試粉铐。
Test()函數(shù)里面做了兩件事:

  • 前向計(jì)算網(wǎng)絡(luò),得到網(wǎng)絡(luò)損失卤档,見 (Caffe蝙泼,LeNet)前向計(jì)算(五)
  • 通過測試網(wǎng)絡(luò)的第11層accuracy層,與第12層loss層結(jié)果統(tǒng)計(jì)accuracy與loss信息劝枣。

4.2 Net::ForwardBackward()函數(shù)

Dtype ForwardBackward(const vector<Blob<Dtype>* > & bottom) {
    Dtype loss;
    Forward(bottom, &loss);
    Backward();
    return loss;
  }

說明:

4.3 Solver::ApplyUpdate()函數(shù)

根據(jù)反向傳播階段計(jì)算的loss關(guān)于網(wǎng)絡(luò)權(quán)值的偏導(dǎo)哗脖,使用配置的學(xué)習(xí)策略,更新網(wǎng)絡(luò)權(quán)值從而完成本輪學(xué)習(xí)采桃。詳見 (Caffe懒熙,LeNet)權(quán)值更新(七)

5 訓(xùn)練完畢

至此,網(wǎng)絡(luò)訓(xùn)練優(yōu)化完成普办。在第3部分solve()函數(shù)中工扎,最后對訓(xùn)練網(wǎng)絡(luò)與測試網(wǎng)絡(luò)再執(zhí)行一輪額外的前行計(jì)算求得loss,以進(jìn)行測試衔蹲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肢娘,一起剝皮案震驚了整個(gè)濱河市呈础,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌橱健,老刑警劉巖而钞,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拘荡,居然都是意外死亡臼节,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門珊皿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來网缝,“玉大人,你說我怎么就攤上這事蟋定》垭” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵驶兜,是天一觀的道長扼仲。 經(jīng)常有香客問我,道長抄淑,這世上最難降的妖魔是什么屠凶? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮肆资,結(jié)果婚禮上阅畴,老公的妹妹穿的比我還像新娘。我一直安慰自己迅耘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布监署。 她就那樣靜靜地躺著颤专,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钠乏。 梳的紋絲不亂的頭發(fā)上栖秕,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音晓避,去河邊找鬼簇捍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛俏拱,可吹牛的內(nèi)容都是我干的暑塑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼锅必,長吁一口氣:“原來是場噩夢啊……” “哼事格!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤驹愚,失蹤者是張志新(化名)和其女友劉穎远搪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逢捺,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谁鳍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劫瞳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倘潜。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柠新,靈堂內(nèi)的尸體忽然破棺而出窍荧,到底是詐尸還是另有隱情,我是刑警寧澤恨憎,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布蕊退,位于F島的核電站,受9級特大地震影響憔恳,放射性物質(zhì)發(fā)生泄漏瓤荔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一钥组、第九天 我趴在偏房一處隱蔽的房頂上張望输硝。 院中可真熱鬧,春花似錦程梦、人聲如沸点把。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郎逃。三九已至,卻和暖如春挺份,著一層夾襖步出監(jiān)牢的瞬間褒翰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工匀泊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留优训,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓各聘,卻偏偏與公主長得像揣非,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子伦吠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

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