Caffeを使ったCNNによる手書き文字分類 [4] - ネットワークの訓練方法

blog.li.nu >
この記事が役に立ったら
 前回までで、データセットの準備、ネットワークの構造の説明、各prototxtの準備が整ったので、訓練が行えるようになりました。 訓練の方法は2通りあります。1つは、Caffeeに用意されているプログラムを端末から直接叩くことで、もう1つは、PythonからCaffeを扱えるようにしたPyCaffeと呼ばれるライブラリで訓練する方法です。 今回は簡単のため、前者の方法を紹介します。なお、訓練後の実戦配備(deploy)については、PyCaffeを使ったほうがはるかに簡単で柔軟性があるため、そちらはPythonでやる方法を次の記事で紹介します。
 ここでは、Caffe付属の実行ファイルを使い、訓練できるようになること、また、訓練誤差とテスト誤差の違いを理解すること、誤差だけでなく正答率も出せるようになることが目標です。

フォルダ構成の確認

 まずはフォルダ構成を確認します。現時点で以下のようになっていることが前提です。
4_mycnnfolder.png
自分のフォルダ(/home/ユーザー名/)直下に mycnn というフォルダを置いています。 また、上のようにテスト用の mnist_test_lmdb、訓練用の mnist_train_lmdb が設置されています。 訓練を実施するために solver.prototxt と train.prototxt も設置しました。train.ipynb は無視してください。

訓練の方法

訓練については、Python のライブラリである PyCaffe から行う方法と、Caffe 付属の実行ファイルにコマンドを渡して、Caffe にやってもらう方法の2種類があります。 後者は1行で終って簡単であるため、今回は後者について説明をします。まず、この実行ファイルは端末(黒い画面)で次のように撃ちこめば実行できます。
$HOME/caffe/build/tools/caffe
$HOME は環境変数と呼ばれるもので、 「/home/あなたのユーザー名」 に相当するものを自動で算出してくれます。試しに端末を出した状態で
echo $HOME
と書いてみればそれが分かります。おそらく、「/home/あなたのユーザー名」が表示されたことでしょう。 つまり、このツールは Caffe をインストールしたフォルダにある build の tools に格納されています。 どのようなオプションがあるかは、 Linux のルールにより、用意されていればですが、普通は --help と書けば表示されることになっています。 実際に
$HOME/caffe/build/tools/caffe --help
を実行してみましょう。すると
caffe: command line brew
usage: caffe  

commands:
  train           train or finetune a model
  test            score a model
  device_query    show GPU diagnostic information
  time            benchmark model execution time

  Flags from src/gflags.cc:
    -flagfile (load flags from file) type: string default: ""
    -fromenv (set flags from the environment [use 'export FLAGS_flag1=value'])
      type: string default: ""
.....
という長々としたヘルプが表示されます。簡単に言うと、 "caffe [やりたいこと] [引数各種]" と書けば訓練できます。 訓練したい場合、前者は train 、後者は --solver=solver.prototxtのパス とすれば良いですね。
 すでに訓練のための準備は整っているので、次のようにして訓練を実行してください。
cd $HOME/mycnn/
$HOME/caffe/build/tools/caffe train --solver=solver.prototxt
すると、黒い画面に色々な文字が流れて、学習が始まると思います。 Optimization Done. と出てくるまでコーヒーでも飲んで待ちましょう。 GeForce GTX TITAN X の場合は1分ほどで終了します。最終的には以下のような表記で終了したはずです。
I0318 15:13:42.657608  3382 layer_factory.hpp:76] Creating layer mnist
I0318 15:13:42.657755  3382 net.cpp:106] Creating Layer mnist
I0318 15:13:42.657778  3382 net.cpp:411] mnist -> data
I0318 15:13:42.657794  3382 net.cpp:411] mnist -> label
I0318 15:13:42.658409  3388 db_lmdb.cpp:38] Opened lmdb mnist_test_lmdb
I0318 15:13:42.658512  3382 data_layer.cpp:41] output data size: 100,1,28,28
I0318 15:13:42.659410  3382 net.cpp:150] Setting up mnist
I0318 15:13:42.659430  3382 net.cpp:157] Top shape: 100 1 28 28 (78400)
I0318 15:13:42.659441  3382 net.cpp:157] Top shape: 100 (100)
I0318 15:13:42.659451  3382 net.cpp:165] Memory required for data: 314000
I0318 15:13:42.659459  3382 layer_factory.hpp:76] Creating layer conv1
I0318 15:13:42.659473  3382 net.cpp:106] Creating Layer conv1
I0318 15:13:42.659483  3382 net.cpp:454] conv1 <- data
I0318 15:13:42.659497  3382 net.cpp:411] conv1 -> conv1
I0318 15:13:42.659677  3382 net.cpp:150] Setting up conv1
I0318 15:13:42.659693  3382 net.cpp:157] Top shape: 100 20 24 24 (1152000)
I0318 15:13:42.659701  3382 net.cpp:165] Memory required for data: 4922000
I0318 15:13:42.659718  3382 layer_factory.hpp:76] Creating layer pool1
I0318 15:13:42.659732  3382 net.cpp:106] Creating Layer pool1
I0318 15:13:42.659742  3382 net.cpp:454] pool1 <- conv1
I0318 15:13:42.659754  3382 net.cpp:411] pool1 -> pool1
I0318 15:13:42.659790  3382 net.cpp:150] Setting up pool1
I0318 15:13:42.659803  3382 net.cpp:157] Top shape: 100 20 12 12 (288000)
I0318 15:13:42.659812  3382 net.cpp:165] Memory required for data: 6074000
I0318 15:13:42.659821  3382 layer_factory.hpp:76] Creating layer conv2
I0318 15:13:42.659834  3382 net.cpp:106] Creating Layer conv2
I0318 15:13:42.659844  3382 net.cpp:454] conv2 <- pool1
I0318 15:13:42.659855  3382 net.cpp:411] conv2 -> conv2
I0318 15:13:42.660253  3382 net.cpp:150] Setting up conv2
I0318 15:13:42.660269  3382 net.cpp:157] Top shape: 100 50 8 8 (320000)
I0318 15:13:42.660279  3382 net.cpp:165] Memory required for data: 7354000
I0318 15:13:42.660298  3382 layer_factory.hpp:76] Creating layer pool2
I0318 15:13:42.660316  3382 net.cpp:106] Creating Layer pool2
I0318 15:13:42.660326  3382 net.cpp:454] pool2 <- conv2
I0318 15:13:42.660341  3382 net.cpp:411] pool2 -> pool2
I0318 15:13:42.660379  3382 net.cpp:150] Setting up pool2
I0318 15:13:42.660393  3382 net.cpp:157] Top shape: 100 50 4 4 (80000)
I0318 15:13:42.660405  3382 net.cpp:165] Memory required for data: 7674000
I0318 15:13:42.660418  3382 layer_factory.hpp:76] Creating layer ip1
I0318 15:13:42.660434  3382 net.cpp:106] Creating Layer ip1
I0318 15:13:42.660446  3382 net.cpp:454] ip1 <- pool2
I0318 15:13:42.660459  3382 net.cpp:411] ip1 -> ip1
I0318 15:13:42.663516  3382 net.cpp:150] Setting up ip1
I0318 15:13:42.663533  3382 net.cpp:157] Top shape: 100 500 (50000)
I0318 15:13:42.663543  3382 net.cpp:165] Memory required for data: 7874000
I0318 15:13:42.663558  3382 layer_factory.hpp:76] Creating layer relu1
I0318 15:13:42.663570  3382 net.cpp:106] Creating Layer relu1
I0318 15:13:42.663579  3382 net.cpp:454] relu1 <- ip1
I0318 15:13:42.663590  3382 net.cpp:397] relu1 -> ip1 (in-place)
I0318 15:13:42.663604  3382 net.cpp:150] Setting up relu1
I0318 15:13:42.663614  3382 net.cpp:157] Top shape: 100 500 (50000)
I0318 15:13:42.663622  3382 net.cpp:165] Memory required for data: 8074000
I0318 15:13:42.663645  3382 layer_factory.hpp:76] Creating layer ip2
I0318 15:13:42.663661  3382 net.cpp:106] Creating Layer ip2
I0318 15:13:42.663671  3382 net.cpp:454] ip2 <- ip1
I0318 15:13:42.663682  3382 net.cpp:411] ip2 -> ip2
I0318 15:13:42.663803  3382 net.cpp:150] Setting up ip2
I0318 15:13:42.663817  3382 net.cpp:157] Top shape: 100 10 (1000)
I0318 15:13:42.663826  3382 net.cpp:165] Memory required for data: 8078000
I0318 15:13:42.663838  3382 layer_factory.hpp:76] Creating layer loss
I0318 15:13:42.663851  3382 net.cpp:106] Creating Layer loss
I0318 15:13:42.663859  3382 net.cpp:454] loss <- ip2
I0318 15:13:42.663869  3382 net.cpp:454] loss <- label
I0318 15:13:42.663880  3382 net.cpp:411] loss -> loss
I0318 15:13:42.663894  3382 layer_factory.hpp:76] Creating layer loss
I0318 15:13:42.663974  3382 net.cpp:150] Setting up loss
I0318 15:13:42.663987  3382 net.cpp:157] Top shape: (1)
I0318 15:13:42.663995  3382 net.cpp:160]     with loss weight 1
I0318 15:13:42.664010  3382 net.cpp:165] Memory required for data: 8078004
I0318 15:13:42.664019  3382 net.cpp:226] loss needs backward computation.
I0318 15:13:42.664028  3382 net.cpp:226] ip2 needs backward computation.
I0318 15:13:42.664036  3382 net.cpp:226] relu1 needs backward computation.
I0318 15:13:42.664044  3382 net.cpp:226] ip1 needs backward computation.
I0318 15:13:42.664053  3382 net.cpp:226] pool2 needs backward computation.
I0318 15:13:42.664062  3382 net.cpp:226] conv2 needs backward computation.
I0318 15:13:42.664072  3382 net.cpp:226] pool1 needs backward computation.
I0318 15:13:42.664079  3382 net.cpp:226] conv1 needs backward computation.
I0318 15:13:42.664088  3382 net.cpp:228] mnist does not need backward computation.
I0318 15:13:42.664098  3382 net.cpp:270] This network produces output loss
I0318 15:13:42.664111  3382 net.cpp:283] Network initialization done.
I0318 15:13:42.664154  3382 solver.cpp:59] Solver scaffolding done.
I0318 15:13:42.664379  3382 caffe.cpp:212] Starting Optimization
I0318 15:13:42.664393  3382 solver.cpp:287] Solving LeNet
I0318 15:13:42.664402  3382 solver.cpp:288] Learning Rate Policy: fixed
I0318 15:13:42.664774  3382 solver.cpp:340] Iteration 0, Testing net (#0)
I0318 15:13:43.801057  3382 solver.cpp:408]     Test net output #0: loss = 2.35588 (* 1 = 2.35588 loss)
I0318 15:13:43.811292  3382 solver.cpp:236] Iteration 0, loss = 2.35228
I0318 15:13:43.811316  3382 solver.cpp:252]     Train net output #0: loss = 2.35228 (* 1 = 2.35228 loss)
I0318 15:13:43.811331  3382 sgd_solver.cpp:106] Iteration 0, lr = 0.01
I0318 15:13:46.753796  3382 solver.cpp:340] Iteration 200, Testing net (#0)
I0318 15:13:47.894870  3382 solver.cpp:408]     Test net output #0: loss = 0.428551 (* 1 = 0.428551 loss)
I0318 15:13:47.904305  3382 solver.cpp:236] Iteration 200, loss = 0.352812
I0318 15:13:47.904328  3382 solver.cpp:252]     Train net output #0: loss = 0.352812 (* 1 = 0.352812 loss)
I0318 15:13:47.904341  3382 sgd_solver.cpp:106] Iteration 200, lr = 0.01
I0318 15:13:50.821164  3382 solver.cpp:340] Iteration 400, Testing net (#0)
I0318 15:13:51.916532  3382 solver.cpp:408]     Test net output #0: loss = 0.295521 (* 1 = 0.295521 loss)
I0318 15:13:51.925935  3382 solver.cpp:236] Iteration 400, loss = 0.235877
I0318 15:13:51.925959  3382 solver.cpp:252]     Train net output #0: loss = 0.235877 (* 1 = 0.235877 loss)
I0318 15:13:51.925971  3382 sgd_solver.cpp:106] Iteration 400, lr = 0.01
I0318 15:13:54.819229  3382 solver.cpp:340] Iteration 600, Testing net (#0)
I0318 15:13:55.914777  3382 solver.cpp:408]     Test net output #0: loss = 0.26432 (* 1 = 0.26432 loss)
I0318 15:13:55.924188  3382 solver.cpp:236] Iteration 600, loss = 0.182522
I0318 15:13:55.924212  3382 solver.cpp:252]     Train net output #0: loss = 0.182522 (* 1 = 0.182522 loss)
I0318 15:13:55.924226  3382 sgd_solver.cpp:106] Iteration 600, lr = 0.01
I0318 15:13:58.818703  3382 solver.cpp:340] Iteration 800, Testing net (#0)
I0318 15:13:59.913530  3382 solver.cpp:408]     Test net output #0: loss = 0.201615 (* 1 = 0.201615 loss)
I0318 15:13:59.923005  3382 solver.cpp:236] Iteration 800, loss = 0.269571
I0318 15:13:59.923058  3382 solver.cpp:252]     Train net output #0: loss = 0.269571 (* 1 = 0.269571 loss)
I0318 15:13:59.923071  3382 sgd_solver.cpp:106] Iteration 800, lr = 0.01
I0318 15:14:02.819603  3382 solver.cpp:340] Iteration 1000, Testing net (#0)
I0318 15:14:03.916120  3382 solver.cpp:408]     Test net output #0: loss = 0.177828 (* 1 = 0.177828 loss)
I0318 15:14:03.925526  3382 solver.cpp:236] Iteration 1000, loss = 0.173842
I0318 15:14:03.925549  3382 solver.cpp:252]     Train net output #0: loss = 0.173842 (* 1 = 0.173842 loss)
I0318 15:14:03.925570  3382 sgd_solver.cpp:106] Iteration 1000, lr = 0.01
I0318 15:14:06.818325  3382 solver.cpp:340] Iteration 1200, Testing net (#0)
I0318 15:14:07.915375  3382 solver.cpp:408]     Test net output #0: loss = 0.155351 (* 1 = 0.155351 loss)
I0318 15:14:07.924793  3382 solver.cpp:236] Iteration 1200, loss = 0.108761
I0318 15:14:07.924816  3382 solver.cpp:252]     Train net output #0: loss = 0.108761 (* 1 = 0.108761 loss)
I0318 15:14:07.924837  3382 sgd_solver.cpp:106] Iteration 1200, lr = 0.01
I0318 15:14:10.823040  3382 solver.cpp:340] Iteration 1400, Testing net (#0)
I0318 15:14:11.942628  3382 solver.cpp:408]     Test net output #0: loss = 0.148154 (* 1 = 0.148154 loss)
I0318 15:14:11.952159  3382 solver.cpp:236] Iteration 1400, loss = 0.0609879
I0318 15:14:11.952183  3382 solver.cpp:252]     Train net output #0: loss = 0.0609879 (* 1 = 0.0609879 loss)
I0318 15:14:11.952203  3382 sgd_solver.cpp:106] Iteration 1400, lr = 0.01
I0318 15:14:14.873962  3382 solver.cpp:340] Iteration 1600, Testing net (#0)
I0318 15:14:15.992725  3382 solver.cpp:408]     Test net output #0: loss = 0.131436 (* 1 = 0.131436 loss)
I0318 15:14:16.002230  3382 solver.cpp:236] Iteration 1600, loss = 0.291724
I0318 15:14:16.002254  3382 solver.cpp:252]     Train net output #0: loss = 0.291725 (* 1 = 0.291725 loss)
I0318 15:14:16.002274  3382 sgd_solver.cpp:106] Iteration 1600, lr = 0.01
I0318 15:14:18.922446  3382 solver.cpp:340] Iteration 1800, Testing net (#0)
I0318 15:14:20.039000  3382 solver.cpp:408]     Test net output #0: loss = 0.129016 (* 1 = 0.129016 loss)
I0318 15:14:20.048508  3382 solver.cpp:236] Iteration 1800, loss = 0.0556022
I0318 15:14:20.048532  3382 solver.cpp:252]     Train net output #0: loss = 0.0556022 (* 1 = 0.0556022 loss)
I0318 15:14:20.048547  3382 sgd_solver.cpp:106] Iteration 1800, lr = 0.01
I0318 15:14:22.970935  3382 solver.cpp:340] Iteration 2000, Testing net (#0)
I0318 15:14:24.088537  3382 solver.cpp:408]     Test net output #0: loss = 0.114576 (* 1 = 0.114576 loss)
I0318 15:14:24.098008  3382 solver.cpp:236] Iteration 2000, loss = 0.110296
I0318 15:14:24.098032  3382 solver.cpp:252]     Train net output #0: loss = 0.110296 (* 1 = 0.110296 loss)
I0318 15:14:24.098045  3382 sgd_solver.cpp:106] Iteration 2000, lr = 0.01
I0318 15:14:27.021292  3382 solver.cpp:340] Iteration 2200, Testing net (#0)
I0318 15:14:28.140019  3382 solver.cpp:408]     Test net output #0: loss = 0.11897 (* 1 = 0.11897 loss)
I0318 15:14:28.149525  3382 solver.cpp:236] Iteration 2200, loss = 0.109589
I0318 15:14:28.149549  3382 solver.cpp:252]     Train net output #0: loss = 0.109589 (* 1 = 0.109589 loss)
I0318 15:14:28.149562  3382 sgd_solver.cpp:106] Iteration 2200, lr = 0.01
I0318 15:14:31.071166  3382 solver.cpp:340] Iteration 2400, Testing net (#0)
I0318 15:14:32.189035  3382 solver.cpp:408]     Test net output #0: loss = 0.0957816 (* 1 = 0.0957816 loss)
I0318 15:14:32.198529  3382 solver.cpp:236] Iteration 2400, loss = 0.0452349
I0318 15:14:32.198552  3382 solver.cpp:252]     Train net output #0: loss = 0.0452348 (* 1 = 0.0452348 loss)
I0318 15:14:32.198565  3382 sgd_solver.cpp:106] Iteration 2400, lr = 0.01
I0318 15:14:35.120736  3382 solver.cpp:340] Iteration 2600, Testing net (#0)
I0318 15:14:36.240253  3382 solver.cpp:408]     Test net output #0: loss = 0.0962278 (* 1 = 0.0962278 loss)
I0318 15:14:36.249775  3382 solver.cpp:236] Iteration 2600, loss = 0.22706
I0318 15:14:36.249799  3382 solver.cpp:252]     Train net output #0: loss = 0.227059 (* 1 = 0.227059 loss)
I0318 15:14:36.249812  3382 sgd_solver.cpp:106] Iteration 2600, lr = 0.01
I0318 15:14:39.172605  3382 solver.cpp:340] Iteration 2800, Testing net (#0)
I0318 15:14:40.348649  3382 solver.cpp:408]     Test net output #0: loss = 0.0932576 (* 1 = 0.0932576 loss)
I0318 15:14:40.358490  3382 solver.cpp:236] Iteration 2800, loss = 0.00793065
I0318 15:14:40.358517  3382 solver.cpp:252]     Train net output #0: loss = 0.00793056 (* 1 = 0.00793056 loss)
I0318 15:14:40.358532  3382 sgd_solver.cpp:106] Iteration 2800, lr = 0.01
I0318 15:14:43.394129  3382 solver.cpp:340] Iteration 3000, Testing net (#0)
I0318 15:14:44.574527  3382 solver.cpp:408]     Test net output #0: loss = 0.102128 (* 1 = 0.102128 loss)
I0318 15:14:44.584008  3382 solver.cpp:236] Iteration 3000, loss = 0.0599364
I0318 15:14:44.584033  3382 solver.cpp:252]     Train net output #0: loss = 0.0599362 (* 1 = 0.0599362 loss)
I0318 15:14:44.584053  3382 sgd_solver.cpp:106] Iteration 3000, lr = 0.01
I0318 15:14:47.570310  3382 solver.cpp:340] Iteration 3200, Testing net (#0)
I0318 15:14:48.688124  3382 solver.cpp:408]     Test net output #0: loss = 0.0781087 (* 1 = 0.0781087 loss)
I0318 15:14:48.697677  3382 solver.cpp:236] Iteration 3200, loss = 0.0838349
I0318 15:14:48.697715  3382 solver.cpp:252]     Train net output #0: loss = 0.0838348 (* 1 = 0.0838348 loss)
I0318 15:14:48.697736  3382 sgd_solver.cpp:106] Iteration 3200, lr = 0.01
I0318 15:14:51.668588  3382 solver.cpp:340] Iteration 3400, Testing net (#0)
I0318 15:14:52.804702  3382 solver.cpp:408]     Test net output #0: loss = 0.08053 (* 1 = 0.08053 loss)
I0318 15:14:52.814335  3382 solver.cpp:236] Iteration 3400, loss = 0.0446551
I0318 15:14:52.814364  3382 solver.cpp:252]     Train net output #0: loss = 0.044655 (* 1 = 0.044655 loss)
I0318 15:14:52.814380  3382 sgd_solver.cpp:106] Iteration 3400, lr = 0.01
I0318 15:14:55.794299  3382 solver.cpp:340] Iteration 3600, Testing net (#0)
I0318 15:14:56.917431  3382 solver.cpp:408]     Test net output #0: loss = 0.0822716 (* 1 = 0.0822716 loss)
I0318 15:14:56.927007  3382 solver.cpp:236] Iteration 3600, loss = 0.122091
I0318 15:14:56.927032  3382 solver.cpp:252]     Train net output #0: loss = 0.12209 (* 1 = 0.12209 loss)
I0318 15:14:56.927044  3382 sgd_solver.cpp:106] Iteration 3600, lr = 0.01
I0318 15:14:59.936321  3382 solver.cpp:340] Iteration 3800, Testing net (#0)
I0318 15:15:01.064332  3382 solver.cpp:408]     Test net output #0: loss = 0.0712671 (* 1 = 0.0712671 loss)
I0318 15:15:01.074139  3382 solver.cpp:236] Iteration 3800, loss = 0.0471237
I0318 15:15:01.074173  3382 solver.cpp:252]     Train net output #0: loss = 0.0471236 (* 1 = 0.0471236 loss)
I0318 15:15:01.074193  3382 sgd_solver.cpp:106] Iteration 3800, lr = 0.01
I0318 15:15:04.068575  3382 solver.cpp:340] Iteration 4000, Testing net (#0)
I0318 15:15:05.192591  3382 solver.cpp:408]     Test net output #0: loss = 0.0669779 (* 1 = 0.0669779 loss)
I0318 15:15:05.202126  3382 solver.cpp:236] Iteration 4000, loss = 0.0956275
I0318 15:15:05.202148  3382 solver.cpp:252]     Train net output #0: loss = 0.0956274 (* 1 = 0.0956274 loss)
I0318 15:15:05.202168  3382 sgd_solver.cpp:106] Iteration 4000, lr = 0.01
I0318 15:15:08.132586  3382 solver.cpp:340] Iteration 4200, Testing net (#0)
I0318 15:15:09.258705  3382 solver.cpp:408]     Test net output #0: loss = 0.0672639 (* 1 = 0.0672639 loss)
I0318 15:15:09.268530  3382 solver.cpp:236] Iteration 4200, loss = 0.0474286
I0318 15:15:09.268558  3382 solver.cpp:252]     Train net output #0: loss = 0.0474285 (* 1 = 0.0474285 loss)
I0318 15:15:09.268571  3382 sgd_solver.cpp:106] Iteration 4200, lr = 0.01
I0318 15:15:12.210129  3382 solver.cpp:340] Iteration 4400, Testing net (#0)
I0318 15:15:13.332058  3382 solver.cpp:408]     Test net output #0: loss = 0.0638991 (* 1 = 0.0638991 loss)
I0318 15:15:13.341629  3382 solver.cpp:236] Iteration 4400, loss = 0.0803695
I0318 15:15:13.341652  3382 solver.cpp:252]     Train net output #0: loss = 0.0803694 (* 1 = 0.0803694 loss)
I0318 15:15:13.341665  3382 sgd_solver.cpp:106] Iteration 4400, lr = 0.01
I0318 15:15:16.278879  3382 solver.cpp:340] Iteration 4600, Testing net (#0)
I0318 15:15:17.401496  3382 solver.cpp:408]     Test net output #0: loss = 0.0639758 (* 1 = 0.0639758 loss)
I0318 15:15:17.411195  3382 solver.cpp:236] Iteration 4600, loss = 0.0269316
I0318 15:15:17.411221  3382 solver.cpp:252]     Train net output #0: loss = 0.0269316 (* 1 = 0.0269316 loss)
I0318 15:15:17.411232  3382 sgd_solver.cpp:106] Iteration 4600, lr = 0.01
I0318 15:15:20.382869  3382 solver.cpp:340] Iteration 4800, Testing net (#0)
I0318 15:15:21.502028  3382 solver.cpp:408]     Test net output #0: loss = 0.0620971 (* 1 = 0.0620971 loss)
I0318 15:15:21.511581  3382 solver.cpp:236] Iteration 4800, loss = 0.12216
I0318 15:15:21.511605  3382 solver.cpp:252]     Train net output #0: loss = 0.12216 (* 1 = 0.12216 loss)
I0318 15:15:21.511618  3382 sgd_solver.cpp:106] Iteration 4800, lr = 0.01
I0318 15:15:24.461321  3382 solver.cpp:461] Snapshotting to binary proto file _iter_5000.caffemodel
I0318 15:15:24.473604  3382 sgd_solver.cpp:269] Snapshotting solver state to binary proto file _iter_5000.solverstate
I0318 15:15:24.483548  3382 solver.cpp:320] Iteration 5000, loss = 0.0696701
I0318 15:15:24.483579  3382 solver.cpp:340] Iteration 5000, Testing net (#0)
I0318 15:15:25.610076  3382 solver.cpp:408]     Test net output #0: loss = 0.058336 (* 1 = 0.058336 loss)
I0318 15:15:25.610106  3382 solver.cpp:325] Optimization Done.
I0318 15:15:25.610116  3382 caffe.cpp:215] Optimization Done.
このように、指定された display の数ごとに、訓練中のネットワークの誤差が loss として出力されています。一方で、テストは test_interval で指定した間隔ごとに実施され、その時の誤差もあわせて報告されています。 訓練用ネットワークの誤差は Train net output: の時の loss を、テスト用の場合は Test net output: の時の loss を見ればよいですね。
 以上の出力内容から、最初は2.30あったテスト誤差が、最終的には0.05といった値まで小さくなっていることが理解できます。 なお、誤差の絶対的な値の大きさには特に大きな意味はないので、最初の誤差よりも小さくなっていることを確認できたということが重要です。
 また、 max_iter に達すると、その時のネットワークの状態を保存したファイル(solverstate, caffemodel)がそれぞれ生成されます。指定がない場合、「_iter_最後の回数.caffemodel」といった名前になっています。 solverstate はそこからさらに学習するための保存データであり、 caffemodel は学習済みモデルとして実戦配備(deploy)するための保存データです。 この結果に満足して、実際に自分でペイントなどで書いた数字を判別させたいときは caffemodel を使います。 要するに solverstate はただの訓練時の中断セーブデータであり、 caffemodel はそこで訓練を終了した、すぐに一般画像に対して使用可能な完成データです。

訓練誤差とテスト誤差

 先ほど見てきた訓練用ネットワークの誤差関数の値は訓練誤差、テスト用ネットワークの誤差関数の値はテスト誤差と呼ばれています。 ここで、訓練誤差とテスト誤差をわざわざ両方表示させた意味について考えてみましょう。
 訓練誤差は、その名の通り訓練データから取り出した現在のバッチに対する誤差です。この誤差をもとに直接パラメータ更新を行うので、訓練誤差は基本的に「減って当たり前」の指標です。 もちろん、学習率や学習データ、構造のなどの兼ね合いで0にはなりませんが、少なくとも大きな欠陥がない限り、ある程度は訓練誤差は減ります。 くどいようですが、訓練データに対して誤差が減ることを目標としたパラメータ更新のかけかたをしているからです。
 一方でテスト誤差は、学習の直接的な対象になっているデータ、つまり訓練データとは全く違うデータに対する誤差です。なので、テスト誤差は訓練誤差と違い、必ずしも減少することは保証されません。 これが訓練誤差との大きな違いで、意識すべき点です。言い換えれば、訓練誤差が減っていても、テスト誤差も減っていなければ意味がなく、「正しく学習ができた」とは決して言えません。
 ここから「過学習」を別の視点で見ることができます。
このように、訓練時のバッチ数を経るごとに、テストもそれに応じて実施したとすると、誤差の時間的推移をグラフにすることができます。 もし理想的に訓練ができているなら、訓練誤差とテスト誤差はほぼ同じ水準で推移するはずです。 しかしながら、上のように、テスト誤差が訓練誤差を大幅に上回り減らないような状況に陥ることがしばしばあります。 これが過学習が起きている場合の典型的な状況です。
 先ほどの場合、訓練誤差もテスト誤差も同程度に減少しているため、訓練データのみならず、未知のデータに対しても対応できるよう、うまく訓練ができたと考えられます。

正答率の算出

これまでは誤差が減ることを確認してきましたが、これはうまく訓練できたことの「目安」に過ぎません。 結局のところ、誤差が小さくなったのは素晴らしいことですが、あなたが「誤差が0.05になった」とみんなに自慢しても、一体それがどれくらいうまくいっているもので、どう凄いのか、人間には何の見当もつかないのです。 それどころか、このネットワークがどれくらいできる子であるのかは、あなたにもわからないことでしょう。 我々が知りたいのは、パラメータを上手く更新するために導入された誤差というより、実際にどれくらいの割合で正解しているのかを示す指標です。つまり、実用上の直接的な指標に成りうる、正答率(accuracy)を算出したいのです。
 誤差の出し方は簡単です。ネットワークの出力ユニットのうち、最大のユニットと、正解ラベルを比較して、どのくらいそれが一致しているかを調べれば原理的には分かります。 Pythonでは簡単にこれが書けますが、今回はCaffeの実行ファイルでやりたいので、別の方法を探します。 大変幸運なことに、Caffeでは、この上で書いたような正答率を自動で算出してくれる層、 Accuracy層というものが用意されています。 Caffeは便宜上誤差関数や活性化関数、この正答率もlayer、つまり見かけ上層として定義しますが、ニューラルネットの構造上層に含まれないというのはすでに前回も説明しました。 ここではCaffeでlayerとして定義するものはとりあえず「層」と称しておきますが、注意しましょう。
 早速train.prototxtの最後に次の記述を追加しましょう。
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
}
書式は loss と一緒で、ネットワークの出力層を最初の bottom に、入力層から持ってきた正解ラベルを次の bottom に指定し、その正答率の出力名を top として指定します。 これで、テスト時の正答率、訓練時の正答率が表示されるようになります。念の為、それを反映した train.prototxt を以下からダウンロードできるようにしておきます。
train.prototxt
これで同じように訓練を実行すると、次のような結果が得られたことと思います。
I0318 15:49:35.439347  3487 caffe.cpp:212] Starting Optimization
I0318 15:49:35.439359  3487 solver.cpp:287] Solving LeNet
I0318 15:49:35.439368  3487 solver.cpp:288] Learning Rate Policy: fixed
I0318 15:49:35.439735  3487 solver.cpp:340] Iteration 0, Testing net (#0)
I0318 15:49:36.599722  3487 solver.cpp:408]     Test net output #0: accuracy = 0.0753
I0318 15:49:36.599763  3487 solver.cpp:408]     Test net output #1: loss = 2.39124 (* 1 = 2.39124 loss)
I0318 15:49:36.610008  3487 solver.cpp:236] Iteration 0, loss = 2.37326
I0318 15:49:36.610028  3487 solver.cpp:252]     Train net output #0: accuracy = 0.109375
I0318 15:49:36.610044  3487 solver.cpp:252]     Train net output #1: loss = 2.37326 (* 1 = 2.37326 loss)
I0318 15:49:36.610056  3487 sgd_solver.cpp:106] Iteration 0, lr = 0.01
I0318 15:49:39.517323  3487 solver.cpp:340] Iteration 200, Testing net (#0)
I0318 15:49:40.628067  3487 solver.cpp:408]     Test net output #0: accuracy = 0.8854
I0318 15:49:40.628106  3487 solver.cpp:408]     Test net output #1: loss = 0.426777 (* 1 = 0.426777 loss)
I0318 15:49:40.637663  3487 solver.cpp:236] Iteration 200, loss = 0.385224
I0318 15:49:40.637682  3487 solver.cpp:252]     Train net output #0: accuracy = 0.859375
I0318 15:49:40.637696  3487 solver.cpp:252]     Train net output #1: loss = 0.385224 (* 1 = 0.385224 loss)
I0318 15:49:40.637706  3487 sgd_solver.cpp:106] Iteration 200, lr = 0.01
I0318 15:49:43.707788  3487 solver.cpp:340] Iteration 400, Testing net (#0)
I0318 15:49:44.952904  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9158
I0318 15:49:44.952952  3487 solver.cpp:408]     Test net output #1: loss = 0.300111 (* 1 = 0.300111 loss)
I0318 15:49:44.962651  3487 solver.cpp:236] Iteration 400, loss = 0.23237
I0318 15:49:44.962678  3487 solver.cpp:252]     Train net output #0: accuracy = 0.921875
I0318 15:49:44.962702  3487 solver.cpp:252]     Train net output #1: loss = 0.23237 (* 1 = 0.23237 loss)
I0318 15:49:44.962713  3487 sgd_solver.cpp:106] Iteration 400, lr = 0.01
I0318 15:49:48.135368  3487 solver.cpp:340] Iteration 600, Testing net (#0)
I0318 15:49:49.241222  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9212
I0318 15:49:49.241266  3487 solver.cpp:408]     Test net output #1: loss = 0.258399 (* 1 = 0.258399 loss)
I0318 15:49:49.250757  3487 solver.cpp:236] Iteration 600, loss = 0.187386
I0318 15:49:49.250776  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:49:49.250789  3487 solver.cpp:252]     Train net output #1: loss = 0.187386 (* 1 = 0.187386 loss)
I0318 15:49:49.250800  3487 sgd_solver.cpp:106] Iteration 600, lr = 0.01
I0318 15:49:52.166229  3487 solver.cpp:340] Iteration 800, Testing net (#0)
I0318 15:49:53.302460  3487 solver.cpp:408]     Test net output #0: accuracy = 0.94
I0318 15:49:53.302505  3487 solver.cpp:408]     Test net output #1: loss = 0.204675 (* 1 = 0.204675 loss)
I0318 15:49:53.313238  3487 solver.cpp:236] Iteration 800, loss = 0.268695
I0318 15:49:53.313271  3487 solver.cpp:252]     Train net output #0: accuracy = 0.890625
I0318 15:49:53.313285  3487 solver.cpp:252]     Train net output #1: loss = 0.268695 (* 1 = 0.268695 loss)
I0318 15:49:53.313297  3487 sgd_solver.cpp:106] Iteration 800, lr = 0.01
I0318 15:49:56.422940  3487 solver.cpp:340] Iteration 1000, Testing net (#0)
I0318 15:49:57.551894  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9497
I0318 15:49:57.551937  3487 solver.cpp:408]     Test net output #1: loss = 0.174766 (* 1 = 0.174766 loss)
I0318 15:49:57.561357  3487 solver.cpp:236] Iteration 1000, loss = 0.176971
I0318 15:49:57.561375  3487 solver.cpp:252]     Train net output #0: accuracy = 0.921875
I0318 15:49:57.561388  3487 solver.cpp:252]     Train net output #1: loss = 0.176971 (* 1 = 0.176971 loss)
I0318 15:49:57.561399  3487 sgd_solver.cpp:106] Iteration 1000, lr = 0.01
I0318 15:50:00.478062  3487 solver.cpp:340] Iteration 1200, Testing net (#0)
I0318 15:50:01.584522  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9567
I0318 15:50:01.584563  3487 solver.cpp:408]     Test net output #1: loss = 0.153239 (* 1 = 0.153239 loss)
I0318 15:50:01.594053  3487 solver.cpp:236] Iteration 1200, loss = 0.107422
I0318 15:50:01.594072  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:50:01.594086  3487 solver.cpp:252]     Train net output #1: loss = 0.107422 (* 1 = 0.107422 loss)
I0318 15:50:01.594099  3487 sgd_solver.cpp:106] Iteration 1200, lr = 0.01
I0318 15:50:04.536718  3487 solver.cpp:340] Iteration 1400, Testing net (#0)
I0318 15:50:05.648345  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9607
I0318 15:50:05.648490  3487 solver.cpp:408]     Test net output #1: loss = 0.143523 (* 1 = 0.143523 loss)
I0318 15:50:05.658092  3487 solver.cpp:236] Iteration 1400, loss = 0.070514
I0318 15:50:05.658118  3487 solver.cpp:252]     Train net output #0: accuracy = 0.984375
I0318 15:50:05.658133  3487 solver.cpp:252]     Train net output #1: loss = 0.070514 (* 1 = 0.070514 loss)
I0318 15:50:05.658144  3487 sgd_solver.cpp:106] Iteration 1400, lr = 0.01
I0318 15:50:08.604581  3487 solver.cpp:340] Iteration 1600, Testing net (#0)
I0318 15:50:09.768698  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9606
I0318 15:50:09.768741  3487 solver.cpp:408]     Test net output #1: loss = 0.138688 (* 1 = 0.138688 loss)
I0318 15:50:09.778146  3487 solver.cpp:236] Iteration 1600, loss = 0.301987
I0318 15:50:09.778169  3487 solver.cpp:252]     Train net output #0: accuracy = 0.90625
I0318 15:50:09.778192  3487 solver.cpp:252]     Train net output #1: loss = 0.301987 (* 1 = 0.301987 loss)
I0318 15:50:09.778203  3487 sgd_solver.cpp:106] Iteration 1600, lr = 0.01
I0318 15:50:12.721812  3487 solver.cpp:340] Iteration 1800, Testing net (#0)
I0318 15:50:13.858204  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9628
I0318 15:50:13.858247  3487 solver.cpp:408]     Test net output #1: loss = 0.131014 (* 1 = 0.131014 loss)
I0318 15:50:13.867835  3487 solver.cpp:236] Iteration 1800, loss = 0.061839
I0318 15:50:13.867854  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:50:13.867877  3487 solver.cpp:252]     Train net output #1: loss = 0.0618389 (* 1 = 0.0618389 loss)
I0318 15:50:13.867887  3487 sgd_solver.cpp:106] Iteration 1800, lr = 0.01
I0318 15:50:16.832558  3487 solver.cpp:340] Iteration 2000, Testing net (#0)
I0318 15:50:17.974463  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9657
I0318 15:50:17.974515  3487 solver.cpp:408]     Test net output #1: loss = 0.116509 (* 1 = 0.116509 loss)
I0318 15:50:17.984093  3487 solver.cpp:236] Iteration 2000, loss = 0.0983078
I0318 15:50:17.984113  3487 solver.cpp:252]     Train net output #0: accuracy = 0.984375
I0318 15:50:17.984127  3487 solver.cpp:252]     Train net output #1: loss = 0.0983077 (* 1 = 0.0983077 loss)
I0318 15:50:17.984139  3487 sgd_solver.cpp:106] Iteration 2000, lr = 0.01
I0318 15:50:20.956470  3487 solver.cpp:340] Iteration 2200, Testing net (#0)
I0318 15:50:22.085554  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9634
I0318 15:50:22.085597  3487 solver.cpp:408]     Test net output #1: loss = 0.119031 (* 1 = 0.119031 loss)
I0318 15:50:22.095201  3487 solver.cpp:236] Iteration 2200, loss = 0.122837
I0318 15:50:22.095221  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:50:22.095235  3487 solver.cpp:252]     Train net output #1: loss = 0.122837 (* 1 = 0.122837 loss)
I0318 15:50:22.095247  3487 sgd_solver.cpp:106] Iteration 2200, lr = 0.01
I0318 15:50:25.087008  3487 solver.cpp:340] Iteration 2400, Testing net (#0)
I0318 15:50:26.217252  3487 solver.cpp:408]     Test net output #0: accuracy = 0.971
I0318 15:50:26.217293  3487 solver.cpp:408]     Test net output #1: loss = 0.0998345 (* 1 = 0.0998345 loss)
I0318 15:50:26.226907  3487 solver.cpp:236] Iteration 2400, loss = 0.0464337
I0318 15:50:26.226927  3487 solver.cpp:252]     Train net output #0: accuracy = 0.984375
I0318 15:50:26.226943  3487 solver.cpp:252]     Train net output #1: loss = 0.0464336 (* 1 = 0.0464336 loss)
I0318 15:50:26.226956  3487 sgd_solver.cpp:106] Iteration 2400, lr = 0.01
I0318 15:50:29.160692  3487 solver.cpp:340] Iteration 2600, Testing net (#0)
I0318 15:50:30.286012  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9693
I0318 15:50:30.286054  3487 solver.cpp:408]     Test net output #1: loss = 0.100496 (* 1 = 0.100496 loss)
I0318 15:50:30.295588  3487 solver.cpp:236] Iteration 2600, loss = 0.231967
I0318 15:50:30.295606  3487 solver.cpp:252]     Train net output #0: accuracy = 0.9375
I0318 15:50:30.295629  3487 solver.cpp:252]     Train net output #1: loss = 0.231966 (* 1 = 0.231966 loss)
I0318 15:50:30.295639  3487 sgd_solver.cpp:106] Iteration 2600, lr = 0.01
I0318 15:50:33.266854  3487 solver.cpp:340] Iteration 2800, Testing net (#0)
I0318 15:50:34.404389  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9701
I0318 15:50:34.404433  3487 solver.cpp:408]     Test net output #1: loss = 0.0984428 (* 1 = 0.0984428 loss)
I0318 15:50:34.414026  3487 solver.cpp:236] Iteration 2800, loss = 0.00701111
I0318 15:50:34.414044  3487 solver.cpp:252]     Train net output #0: accuracy = 1
I0318 15:50:34.414058  3487 solver.cpp:252]     Train net output #1: loss = 0.00701095 (* 1 = 0.00701095 loss)
I0318 15:50:34.414072  3487 sgd_solver.cpp:106] Iteration 2800, lr = 0.01
I0318 15:50:37.345834  3487 solver.cpp:340] Iteration 3000, Testing net (#0)
I0318 15:50:38.494946  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9672
I0318 15:50:38.494997  3487 solver.cpp:408]     Test net output #1: loss = 0.10778 (* 1 = 0.10778 loss)
I0318 15:50:38.504477  3487 solver.cpp:236] Iteration 3000, loss = 0.111363
I0318 15:50:38.504495  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:50:38.504518  3487 solver.cpp:252]     Train net output #1: loss = 0.111363 (* 1 = 0.111363 loss)
I0318 15:50:38.504529  3487 sgd_solver.cpp:106] Iteration 3000, lr = 0.01
I0318 15:50:41.457626  3487 solver.cpp:340] Iteration 3200, Testing net (#0)
I0318 15:50:42.603052  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9751
I0318 15:50:42.603094  3487 solver.cpp:408]     Test net output #1: loss = 0.0839751 (* 1 = 0.0839751 loss)
I0318 15:50:42.612717  3487 solver.cpp:236] Iteration 3200, loss = 0.050921
I0318 15:50:42.612737  3487 solver.cpp:252]     Train net output #0: accuracy = 0.984375
I0318 15:50:42.612751  3487 solver.cpp:252]     Train net output #1: loss = 0.0509207 (* 1 = 0.0509207 loss)
I0318 15:50:42.612762  3487 sgd_solver.cpp:106] Iteration 3200, lr = 0.01
I0318 15:50:45.554730  3487 solver.cpp:340] Iteration 3400, Testing net (#0)
I0318 15:50:46.702071  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9736
I0318 15:50:46.702113  3487 solver.cpp:408]     Test net output #1: loss = 0.0880515 (* 1 = 0.0880515 loss)
I0318 15:50:46.711730  3487 solver.cpp:236] Iteration 3400, loss = 0.0499841
I0318 15:50:46.711750  3487 solver.cpp:252]     Train net output #0: accuracy = 1
I0318 15:50:46.711763  3487 solver.cpp:252]     Train net output #1: loss = 0.0499839 (* 1 = 0.0499839 loss)
I0318 15:50:46.711777  3487 sgd_solver.cpp:106] Iteration 3400, lr = 0.01
I0318 15:50:49.650635  3487 solver.cpp:340] Iteration 3600, Testing net (#0)
I0318 15:50:50.776473  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9728
I0318 15:50:50.776513  3487 solver.cpp:408]     Test net output #1: loss = 0.0872698 (* 1 = 0.0872698 loss)
I0318 15:50:50.786027  3487 solver.cpp:236] Iteration 3600, loss = 0.137819
I0318 15:50:50.786046  3487 solver.cpp:252]     Train net output #0: accuracy = 0.9375
I0318 15:50:50.786068  3487 solver.cpp:252]     Train net output #1: loss = 0.137819 (* 1 = 0.137819 loss)
I0318 15:50:50.786079  3487 sgd_solver.cpp:106] Iteration 3600, lr = 0.01
I0318 15:50:53.725615  3487 solver.cpp:340] Iteration 3800, Testing net (#0)
I0318 15:50:54.864505  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9769
I0318 15:50:54.864557  3487 solver.cpp:408]     Test net output #1: loss = 0.0733028 (* 1 = 0.0733028 loss)
I0318 15:50:54.874624  3487 solver.cpp:236] Iteration 3800, loss = 0.0461295
I0318 15:50:54.874644  3487 solver.cpp:252]     Train net output #0: accuracy = 0.984375
I0318 15:50:54.874657  3487 solver.cpp:252]     Train net output #1: loss = 0.0461295 (* 1 = 0.0461295 loss)
I0318 15:50:54.874667  3487 sgd_solver.cpp:106] Iteration 3800, lr = 0.01
I0318 15:50:57.826640  3487 solver.cpp:340] Iteration 4000, Testing net (#0)
I0318 15:50:58.953855  3487 solver.cpp:408]     Test net output #0: accuracy = 0.976
I0318 15:50:58.953897  3487 solver.cpp:408]     Test net output #1: loss = 0.0742581 (* 1 = 0.0742581 loss)
I0318 15:50:58.963500  3487 solver.cpp:236] Iteration 4000, loss = 0.109244
I0318 15:50:58.963520  3487 solver.cpp:252]     Train net output #0: accuracy = 0.953125
I0318 15:50:58.963533  3487 solver.cpp:252]     Train net output #1: loss = 0.109244 (* 1 = 0.109244 loss)
I0318 15:50:58.963546  3487 sgd_solver.cpp:106] Iteration 4000, lr = 0.01
I0318 15:51:01.900107  3487 solver.cpp:340] Iteration 4200, Testing net (#0)
I0318 15:51:03.026459  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9772
I0318 15:51:03.026500  3487 solver.cpp:408]     Test net output #1: loss = 0.0725421 (* 1 = 0.0725421 loss)
I0318 15:51:03.036160  3487 solver.cpp:236] Iteration 4200, loss = 0.0680813
I0318 15:51:03.036180  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:51:03.036195  3487 solver.cpp:252]     Train net output #1: loss = 0.0680811 (* 1 = 0.0680811 loss)
I0318 15:51:03.036233  3487 sgd_solver.cpp:106] Iteration 4200, lr = 0.01
I0318 15:51:05.996453  3487 solver.cpp:340] Iteration 4400, Testing net (#0)
I0318 15:51:07.130614  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9776
I0318 15:51:07.130656  3487 solver.cpp:408]     Test net output #1: loss = 0.072042 (* 1 = 0.072042 loss)
I0318 15:51:07.140278  3487 solver.cpp:236] Iteration 4400, loss = 0.075286
I0318 15:51:07.140300  3487 solver.cpp:252]     Train net output #0: accuracy = 0.96875
I0318 15:51:07.140313  3487 solver.cpp:252]     Train net output #1: loss = 0.0752859 (* 1 = 0.0752859 loss)
I0318 15:51:07.140326  3487 sgd_solver.cpp:106] Iteration 4400, lr = 0.01
I0318 15:51:10.100457  3487 solver.cpp:340] Iteration 4600, Testing net (#0)
I0318 15:51:11.233594  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9794
I0318 15:51:11.233638  3487 solver.cpp:408]     Test net output #1: loss = 0.0656571 (* 1 = 0.0656571 loss)
I0318 15:51:11.243300  3487 solver.cpp:236] Iteration 4600, loss = 0.0248723
I0318 15:51:11.243322  3487 solver.cpp:252]     Train net output #0: accuracy = 1
I0318 15:51:11.243336  3487 solver.cpp:252]     Train net output #1: loss = 0.0248722 (* 1 = 0.0248722 loss)
I0318 15:51:11.243350  3487 sgd_solver.cpp:106] Iteration 4600, lr = 0.01
I0318 15:51:14.214659  3487 solver.cpp:340] Iteration 4800, Testing net (#0)
I0318 15:51:15.341974  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9799
I0318 15:51:15.342015  3487 solver.cpp:408]     Test net output #1: loss = 0.0657724 (* 1 = 0.0657724 loss)
I0318 15:51:15.351678  3487 solver.cpp:236] Iteration 4800, loss = 0.0904344
I0318 15:51:15.351699  3487 solver.cpp:252]     Train net output #0: accuracy = 0.984375
I0318 15:51:15.351713  3487 solver.cpp:252]     Train net output #1: loss = 0.0904343 (* 1 = 0.0904343 loss)
I0318 15:51:15.351727  3487 sgd_solver.cpp:106] Iteration 4800, lr = 0.01
I0318 15:51:18.285661  3487 solver.cpp:461] Snapshotting to binary proto file _iter_5000.caffemodel
I0318 15:51:18.297734  3487 sgd_solver.cpp:269] Snapshotting solver state to binary proto file _iter_5000.solverstate
I0318 15:51:18.308661  3487 solver.cpp:320] Iteration 5000, loss = 0.0756349
I0318 15:51:18.308693  3487 solver.cpp:340] Iteration 5000, Testing net (#0)
I0318 15:51:19.444846  3487 solver.cpp:408]     Test net output #0: accuracy = 0.9814
I0318 15:51:19.444896  3487 solver.cpp:408]     Test net output #1: loss = 0.0615246 (* 1 = 0.0615246 loss)
I0318 15:51:19.444908  3487 solver.cpp:325] Optimization Done.
I0318 15:51:19.444916  3487 caffe.cpp:215] Optimization Done.
見てください。 net output が #0 と #1 に増えています。 accuracy が正答率で、loss が誤差関数の値です。 最初のテスト正答率は 0.0753 、つまり 7.53% しかなかったことがわかります。つまり、ほぼ当てずっぽうです。 しかしながら、5,000バッチ学習した後には、なんとテスト正答率は 98% にもなっていることが分かります。これは大変大きな進歩と言えます。 これなら「私のネットワークは手書き文字を98%識別できる」と他人に自慢しても分かってもらえるでしょう。

今回のまとめ

 今回は、訓練誤差とテスト誤差について説明した上で、それぞれの正答率の出し方についても紹介しました。 そして、Caffeにて用意されている実行ファイルを使い、訓練する方法を説明しました。 次は、訓練により出来上がった caffemodel を使って、実際の一般データを識別させる方法、つまり、deploy.prototxtの書き方とPyCaffeでの使い方について見ていきます。

その他の記事

コメント

名前 :
電子メール :
URL :
コメント