Chainerのインストール環境が整ったので、まずはChainerのチュートリアルを実行した。
ニューラルネットワークのチュートリアルといえばやっぱりMNISTだ。TensorFlowでもMNISTは最初に実行するチュートリアルになっている。
上記の解説記事に書いてあるように、まずはtrain_mnist.pyを実行して動作を観察する。
引数の処理
parser = argparse.ArgumentParser(description='Chainer example: MNIST') parser.add_argument('--initmodel', '-m', default='', help='Initialize the model from given file') parser.add_argument('--resume', '-r', default='', help='Resume the optimization from snapshot') parser.add_argument('--net', '-n', choices=('simple', 'parallel'), default='simple', help='Network type') parser.add_argument('--gpu', '-g', default=-1, type=int, help='GPU ID (negative value indicates CPU)') parser.add_argument('--epoch', '-e', default=20, type=int, help='number of epochs to learn') parser.add_argument('--unit', '-u', default=1000, type=int, help='number of units') parser.add_argument('--batchsize', '-b', type=int, default=100, help='learning minibatch size')
- initmodel: 初期モデルをロードする。指定した場合は、以下でロードされる。
if args.initmodel: print('Load model from', args.initmodel) serializers.load_npz(args.initmodel, model)
- resume: optimizerをロードする。すでに学習済みのモデルをロードすることになる?
if args.resume: print('Load optimizer state from', args.resume) serializers.load_npz(args.resume, optimizer)
- net : ネットワークの並列処理の可否を指定する?GPU指定があるときはどちらも有効化する。MnistMLP()を呼び出すか、MnistMLPParallel()を呼び出すかの違いになっているようだ。
if args.net == 'simple': model = L.Classifier(net.MnistMLP(784, n_units, 10)) if args.gpu >= 0: cuda.get_device(args.gpu).use() model.to_gpu() xp = np if args.gpu < 0 else cuda.cupy elif args.net == 'parallel': cuda.check_cuda_available() model = L.Classifier(net.MnistMLPParallel(784, n_units, 10)) xp = cuda.cupy
n_epoch = args.epoch
- unit : データの更新単位を指定する。
n_units = args.unit
これ、最終的にどこに効くかというと、
if args.net == 'simple': model = L.Classifier(net.MnistMLP(784, n_units, 10)) if args.gpu >= 0: cuda.get_device(args.gpu).use() model.to_gpu() xp = np if args.gpu < 0 else cuda.cupy elif args.net == 'parallel': cuda.check_cuda_available() model = L.Classifier(net.MnistMLPParallel(784, n_units, 10)) xp = cuda.cupy
の部分になるのだが、n_unitsにより中間レイヤの数が決まるように見える。
- batchsize : バッチサイズを指定する。
Learning Loopの詳細
詳しくはソースコードを見るのが一番良いのだが、概略を示すと以下のようになる。
# Setup optimizer optimizer = optimizers.Adam() # Adam : SGDの更新式: [https://ja.scribd.com/doc/260859670/30minutes-Adam] optimizer.setup(model) # Learning loop for epoch in six.moves.range(1, n_epoch + 1): # n_epoch回数分学習を繰替えす # x, t変数作成 先に定義した x_train, y_train から切り出す。 for i in six.moves.range(0, N, batchsize): # バッチサイズのステップで、Nまで繰替えす optimizer.update(model, x, t) # モデルを更新 # 必要に応じてグラフ描画 # 精度の計算
実行結果
仮想マシン上で実行しているのだが結構な時間がかかる。数時間がかかっているだろうか。
$ time python ./train_mnist.py GPU: -1 # unit: 1000 # Minibatch-size: 100 # epoch: 20 Network type: simple load MNIST dataset epoch 1 graph generated train mean loss=0.19138759135, accuracy=0.942583334881, throughput=156.836722845 images/sec test mean loss=0.101782948093, accuracy=0.967800005674 epoch 2 train mean loss=0.073480642344, accuracy=0.977633343637, throughput=171.438272947 images/sec test mean loss=0.0949596984277, accuracy=0.970700005293 epoch 3 ...