MXNet チュートリアル : 画像分類

MXNet チュートリアル : 画像分類 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
日時 : 02/24/2017

* 本ページは、MXNet 本家サイトの Image Classification Tutorial を翻訳した上で適宜、補足説明したものです:
    http://mxnet.io/tutorials/computer_vision/image_classification.html

Image Classification – 畳込みニューラルネットワークを使用して現実世界の物体の様々な画像を分類する例です。

* サンプルコードの動作確認はしておりますが、適宜、追加改変しています。

 

このチュートリアルでは、画像に信頼スコア (confidence scores) でラベルを割り当てます。

このチュートリアルのためのソースコードは GitHub から得てください。

 

トレーニング

特定のデータセット上でモデルをトレーニングするには、$train\_dataset.py$ を使用します。例えば :

  • mnist で MLP をトレーニングするためには、このコマンドを使用します :
    python train_mnist.py
    
  • 各 epoch でモデルをセーブするためには、このコマンドを使用します :
    mkdir model; python train_mnist.py --model-prefix model/mnist
    
  • epoch 8 でセーブされたモデルからトレーニングを再開するためには、このコマンドを使用します :
    python train_mnist.py --model-prefix model/mnist --load-epoch 8
    
  • 他の初期学習率を選択して全ての half epoch 毎に 0.9 で減衰させるためには、このコマンドを使用します :
    python train_mnist.py --lr .1 --lr-factor .9 --lr-factor-epoch .5
    
  • mnist 上で畳込みニューラルネットワークを GPU 0 を使用してトレーニングするためには、このコマンドを使用します :
    python train_mnist.py --network lenet --gpus 0
    
  • 複数の GPU を使用するためには、リストを指定します; 例えば : —gpus 0,1,3.
  • 更なるオプションを見るには、–help を使用してください。

 
* 訳注 : 以下は mnist を mlp モデルで 20 epochs トレーニングした際のログです。checkpoint の保存もしています :

2017-02-25 09:49:14,148 Node[0] start with arguments Namespace(batch_size=64, disp_batches=100, gpus=None, kv_store='device', load_epoch=None, lr=0.05, lr_factor=0.1, lr_step_epochs='10', model_prefix='models/mnist', mom=0.9, monitor=0, network='mlp', num_classes=10, num_epochs=20, num_examples=60000, num_layers=None, optimizer='sgd', test_io=0, top_k=0, wd=0.0001)
2017-02-25 09:49:15,006 Node[0] Epoch[0] Batch [100]	Speed: 17758.14 samples/sec	Train-accuracy=0.780322
2017-02-25 09:49:15,368 Node[0] Epoch[0] Batch [200]	Speed: 17706.37 samples/sec	Train-accuracy=0.900156
2017-02-25 09:49:15,700 Node[0] Epoch[0] Batch [300]	Speed: 19271.93 samples/sec	Train-accuracy=0.924531
2017-02-25 09:49:16,033 Node[0] Epoch[0] Batch [400]	Speed: 19212.92 samples/sec	Train-accuracy=0.934375
2017-02-25 09:49:16,387 Node[0] Epoch[0] Batch [500]	Speed: 18120.87 samples/sec	Train-accuracy=0.944531
2017-02-25 09:49:16,729 Node[0] Epoch[0] Batch [600]	Speed: 18689.96 samples/sec	Train-accuracy=0.948906
2017-02-25 09:49:17,065 Node[0] Epoch[0] Batch [700]	Speed: 19040.31 samples/sec	Train-accuracy=0.950469
2017-02-25 09:49:17,418 Node[0] Epoch[0] Batch [800]	Speed: 18180.69 samples/sec	Train-accuracy=0.952812
2017-02-25 09:49:17,770 Node[0] Epoch[0] Batch [900]	Speed: 18162.74 samples/sec	Train-accuracy=0.950156
2017-02-25 09:49:17,897 Node[0] Epoch[0] Train-accuracy=0.954814
2017-02-25 09:49:17,898 Node[0] Epoch[0] Time cost=3.281
2017-02-25 09:49:17,910 Node[0] Saved checkpoint to "models/mnist-0001.params"
2017-02-25 09:49:18,181 Node[0] Epoch[0] Validation-accuracy=0.960291
...
2017-02-25 09:50:22,608 Node[0] Epoch[19] Batch [100]	Speed: 19424.26 samples/sec	Train-accuracy=1.000000
2017-02-25 09:50:22,965 Node[0] Epoch[19] Batch [200]	Speed: 17954.07 samples/sec	Train-accuracy=0.999844
2017-02-25 09:50:23,365 Node[0] Epoch[19] Batch [300]	Speed: 15995.49 samples/sec	Train-accuracy=0.999687
2017-02-25 09:50:23,708 Node[0] Epoch[19] Batch [400]	Speed: 18690.76 samples/sec	Train-accuracy=0.999687
2017-02-25 09:50:24,063 Node[0] Epoch[19] Batch [500]	Speed: 18027.42 samples/sec	Train-accuracy=0.999844
2017-02-25 09:50:24,400 Node[0] Epoch[19] Batch [600]	Speed: 19009.43 samples/sec	Train-accuracy=1.000000
2017-02-25 09:50:24,735 Node[0] Epoch[19] Batch [700]	Speed: 19087.96 samples/sec	Train-accuracy=0.999531
2017-02-25 09:50:25,098 Node[0] Epoch[19] Batch [800]	Speed: 17637.86 samples/sec	Train-accuracy=0.999687
2017-02-25 09:50:25,456 Node[0] Epoch[19] Batch [900]	Speed: 17902.30 samples/sec	Train-accuracy=0.999375
2017-02-25 09:50:25,581 Node[0] Epoch[19] Train-accuracy=1.000000
2017-02-25 09:50:25,581 Node[0] Epoch[19] Time cost=3.304
2017-02-25 09:50:25,591 Node[0] Saved checkpoint to "models/mnist-0020.params"
2017-02-25 09:50:25,832 Node[0] Epoch[19] Validation-accuracy=0.983678

以下は GPU 上でのトレーニングのログです :

INFO:root:start with arguments Namespace(batch_size=64, disp_batches=100, gpus='0', kv_store='device', load_epoch=None, lr=0.05, lr_factor=0.1, lr_step_epochs='10', model_prefix=None, mom=0.9, monitor=0, network='mlp', num_classes=10, num_epochs=20, num_examples=60000, num_layers=None, optimizer='sgd', test_io=0, top_k=0, wd=0.0001)
INFO:root:Epoch[0] Batch [100]  Speed: 49910.28 samples/sec     Train-accuracy=0.774288
INFO:root:Epoch[0] Batch [200]  Speed: 52118.94 samples/sec     Train-accuracy=0.911875
INFO:root:Epoch[0] Batch [300]  Speed: 49846.52 samples/sec     Train-accuracy=0.931250
INFO:root:Epoch[0] Batch [400]  Speed: 52170.39 samples/sec     Train-accuracy=0.937500
INFO:root:Epoch[0] Batch [500]  Speed: 50266.65 samples/sec     Train-accuracy=0.944375
INFO:root:Epoch[0] Batch [600]  Speed: 48508.34 samples/sec     Train-accuracy=0.946562
INFO:root:Epoch[0] Batch [700]  Speed: 48906.84 samples/sec     Train-accuracy=0.947969
INFO:root:Epoch[0] Batch [800]  Speed: 51169.35 samples/sec     Train-accuracy=0.950937
INFO:root:Epoch[0] Batch [900]  Speed: 50815.89 samples/sec     Train-accuracy=0.956094
INFO:root:Epoch[0] Train-accuracy=0.956503
INFO:root:Epoch[0] Time cost=1.477
INFO:root:Epoch[0] Validation-accuracy=0.956011
...
INFO:root:Epoch[19] Batch [100] Speed: 51768.25 samples/sec     Train-accuracy=0.999691
INFO:root:Epoch[19] Batch [200] Speed: 52185.71 samples/sec     Train-accuracy=0.999531
INFO:root:Epoch[19] Batch [300] Speed: 48955.09 samples/sec     Train-accuracy=0.999531
INFO:root:Epoch[19] Batch [400] Speed: 50415.05 samples/sec     Train-accuracy=1.000000
INFO:root:Epoch[19] Batch [500] Speed: 49099.71 samples/sec     Train-accuracy=1.000000
INFO:root:Epoch[19] Batch [600] Speed: 49625.81 samples/sec     Train-accuracy=0.999375
INFO:root:Epoch[19] Batch [700] Speed: 51004.17 samples/sec     Train-accuracy=0.999844
INFO:root:Epoch[19] Batch [800] Speed: 50453.24 samples/sec     Train-accuracy=0.999844
INFO:root:Epoch[19] Batch [900] Speed: 50429.83 samples/sec     Train-accuracy=1.000000
INFO:root:Epoch[19] Train-accuracy=1.000000
INFO:root:Epoch[19] Time cost=1.190
INFO:root:Epoch[19] Validation-accuracy=0.982484

 

分散トレーニング

トレーニングを速くするためには、複数のコンピュータを使用してモデルをトレーニングします。

  • 2つの workers を使用してローカル・コンピュータ上で分散トレーニングを素早くテストします :
  ../../tools/launch.py -n 2 python train_mnist.py --kv-store dist_sync

* 訳注: このテストは正常には実行できませんでした。

SGD dist_sync あるいは asynchronous SGD dist_async を利用することができます。

  • SSH を使って接続可能な幾つかのコンピュータを持つならば、そしてこの mxnet フォルダが(NFS としてマウントされ、tutorial for Ubuntu 参照)これらのコンピュータ上でアクセス可能であるならば、最初にそれらのホスト名をファイルに保存することでこれらのコンピュータ上でジョブを実行します、例えば :
$ cat hosts
172.30.0.172
172.30.0.171
  • それからこのファイルを -H で渡します :

../../tools/launch.py -n 2 -H hosts python train_mnist.py –kv-store dist_sync

  • もし mxnet フォルダが他のコンピュータで利用可能でないならば、mxnet ライブラリをこの examples フォルダにコピーします :
cp -r ../../python/mxnet .
cp -r ../../lib/libmxnet.so mxnet

それから実行する前に他のコンピュータ /tmp/mxnet にフォルダを同期します :

  ../../tools/launch.py -n 2 -H hosts --sync-dir /tmp/mxnet python train_mnist.py --kv-store dist_sync

更なる launch オプション、例えば、YARN を使う、そして分散トレーニング・プログラムをどうのように書くかについての情報については、この チュートリアル を参照してください。

 

予測を生成する

予測を生成するためには幾つかのオプションがあります :

貴方自身のデータセットを使用する

MXNet にデータを供給するためには2つの方法があります :

  • 全てのサンプルを一つあるいはそれ以上のコンパクトな $recordio$ ファイルにパックします。更なる情報については、この step-by-step チュートリアルdocumentation を参照してください。パッキングの間に画像リストをシャッフルすることを見過ごす一般的なミスを回避します。これはトレーニングを失敗させる原因となります。例えば、軽度は幾つかのラウンドで 0.001 を保持します。

    Note: mnist と cifar10 のような小さなデータセットは自動的にダウンロードします。

  • メモリに簡単にロードできる小さなデータセットについては、ここに例を示します :
from sklearn.datasets import fetch_mldata
from sklearn.utils import shuffle
mnist = fetch_mldata('MNIST original', data_home="./mnist")
# shuffle data
X, y = shuffle(mnist.data, mnist.target)
# split dataset
train_data = X[:50000, :].astype('float32')
train_label = y[:50000]
val_data = X[50000: 60000, :].astype('float32')
val_label = y[50000:60000]
# Normalize data
train_data[:] /= 256.0
val_data[:] /= 256.0
# create a numpy iterator
batch_size = 100
train_iter = mx.io.NDArrayIter(train_data, train_label, batch_size=batch_size, shuffle=True)
val_iter = mx.io.NDArrayIter(val_data, val_label, batch_size=batch_size)
# create model as usual: model = mx.model.FeedForward(...)
model.fit(X = train_iter, eval_data = val_iter)

 

パフォーマンスを改善する

次の要因が本質的にパフォーマンスを改善します :

  • CPU プロセッサを使用している場合に限っては高速なバックエンド。高速な BLAS ライブラリ, e.g., openblas, atlas, 及び mkl, が必要です。Nvidia GPU のためには、CUDNN を使用することを強く推奨します。
  • 入力データ :
    • データ・フォーマット。$rec$ フォーマットを使用します。
    • デコードに使用されるスレッドの数。デフォルトでは、MXNet は 4 CPU スレッドを画像デコードのために使用し、これは秒毎に 1 Kb 画像以上をしばしばデコードできます。ローエンドな CPU あるいは非常にパワフルな GPU を使用しているのであれば、スレッドの数を増やすことができます。
    • データ・ストレージの位置。任意のローカルあるいは分散ファイルシステム (HDFS, Amzon S3) は優れているでしょう。もし複数のコンピュータが network shared file system (NFS) から同時にデータを読む場合には、けれども、問題に遭遇するかもしれません。
    • バッチサイズ。GPU メモリが収容できる最大のサイズを使用することを勧めます。大き過ぎる値は収束を遅くするかもしれません。安全なバッチサイズは CIFAR 10 のためにはおよそ 200; ImageNet のためには 1K、バッチサイズは 1 Kb を超えられます。
  • もし一つ以上の GPU を使用しているならば、正確な (= right ) kvstore。更なる情報のためには、このガイド を参照。
    • 単一のコンピュータのためには、デフォルトの `local` でしばしば十分です。100 MB より大きいモデルのためには、AlexNet と VGG のような、local_allreduce_device を使用することを望むかもしれません。local_allreduce_device は他のオプションよりも GPU メモリをより使用します。
    • 複数のコンピュータのためには、最初に `dist_sync` を使用することを試みることを勧めます。モデルが非常に大きいか多くの数のコンピュータを使用するのであれば、dist_async を利用することを望むかもしれません。

 

結果

結果の表・グラフ等については、原文 を参照してください :

 

Next Steps

 

以上