• ホーム
  • Chainer
  • ChainerCVのデモンストレーションプログラムを読んでみた

ChainerCVのデモンストレーションプログラムを読んでみた

ChainerCVの物体認識(SSD)のデモンストレーションのファイルを読んでみました。

目次

  1. 本編
  2. 引数の解釈
  3. モデルのインスタンスを作る
  4. 学習用のデータセットを作る
  5. 評価用のデータセットを作る
  6. オプティマイザーを作る
  7. アップデーターを作る
  8. トレーナーを作る
  9. 学習の実行
  10. まとめ

本編

ChainerCVのSSDのデモンストレーションの、 学習についてのデモのコード train.py を読んでみます。

まず全体を見渡してみます。

最初に大量のimportがあります。次にクラスや関数の定義があって、最後に実行します。

クラスと関数は3つ定義されていて、それぞれこのような役割のようです。

class MultiboxTrainChain(chainer.Chain):
# モデル(ネットワーク)の定義

class Transform(object):
# データの拡張方法の定義

def main():
# 実行部分をまとめたもの

main部分を読んでみて、このプログラムが何をしているのか見てみます。

引数の解釈

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--model', choices=('ssd300', 'ssd512'), default='ssd300')
    parser.add_argument('--batchsize', type=int, default=32)
    parser.add_argument('--iteration', type=int, default=120000)
    parser.add_argument('--step', type=int, nargs='*', default=[80000, 100000])
    parser.add_argument('--gpu', type=int, default=-1)
    parser.add_argument('--out', default='result')
    parser.add_argument('--resume')
args = parser.parse_args()

argparseモジュールを使って、引数をパースします。パースした結果はargsというオブジェクトに入れています。

モデルのインスタンスを作る

if args.model == 'ssd300':
        model = SSD300(n_fg_class=len(voc_bbox_label_names), pretrained_model='imagenet')
    elif args.model == 'ssd512':
        model = SSD512(n_fg_class=len(voc_bbox_label_names), pretrained_model='imagenet')

    model.use_preset('evaluate')
    train_chain = MultiboxTrainChain(model)
    if args.gpu >= 0:
        chainer.cuda.get_device_from_id(args.gpu).use()
model.to_gpu()

コマンドライン引数で指定されたモデルがssd300だったらSSD300の、ssd512だったらSSD512のモデルを選択して、modelという名前でインスタンスを作ります。

そのモデルのuse_presetというメソッドを実行します。引数がevaluateなので評価用のプリセットにするのでしょうか。

train_chainという名前で、MultiboxTrainChainクラスのインスタンスを作ります。前述のクラスですね。

コマンドライン引数のGPUの項目が0以上の場合は、指定されたIDのGPUを選択して、モデルをGPUへ転送します。

学習用のデータセットを作る

train = TransformDataset(ConcatenatedDataset(VOCBboxDataset(year='2007', split='trainval'), VOCBboxDataset(year='2012', split='trainval')), Transform(model.coder, model.insize, model.mean))
train_iter = chainer.iterators.MultiprocessIterator(train, args.batchsize)

trainという名前で、学習用のデータセットを作ります。

Pascal VOC 2007と2012のデータセットをダウンロードして、結合して、Transformクラスで定義したデータ拡張をしたデータセットを作っているようですね。

作ったデータセットからコマンドライン引数のバッチサイズの大きさでイテレーターを作ります。

評価用のデータセットを作る

test = VOCBboxDataset(year='2007', split='test', use_difficult=True, return_difficult=True)
test_iter = chainer.iterators.SerialIterator(test, args.batchsize, repeat=False, shuffle=False)

Pascal VOC 2007データセットから評価用のデータセットを作ります。

シリアルイテレーターを使って、バッチサイズに合わせたイテレーターを作ります。

オプティマイザーを作る

# initial lr is set to 1e-3 by ExponentialShift
optimizer = chainer.optimizers.MomentumSGD()
optimizer.setup(train_chain)
for param in train_chain.params():
    if param.name == 'b':
        param.update_rule.add_hook(GradientScaling(2))
    else:
        param.update_rule.add_hook(WeightDecay(0.0005))

オプティマイザーオブジェクトを作ります。最適化手法として、ここではモーメンタムSGDを選択しています。

アップデーターを作る

updater = training.updaters.StandardUpdater(train_iter, optimizer, device=args.gpu)

モデルのパラメータ更新用のアップデーターを作ります。

トレーナーを作る

trainer = training.Trainer(updater, (args.iteration, 'iteration'), args.out)
trainer.extend(extensions.ExponentialShift('lr', 0.1, init=1e-3), trigger=triggers.ManualScheduleTrigger(args.step, 'iteration'))

trainer.extend(DetectionVOCEvaluator(test_iter, model, use_07_metric=True, label_names=voc_bbox_label_names), trigger=triggers.ManualScheduleTrigger(args.step + [args.iteration], 'iteration'))

log_interval = 10, 'iteration'
trainer.extend(extensions.LogReport(trigger=log_interval))
trainer.extend(extensions.observe_lr(), trigger=log_interval)
trainer.extend(extensions.PrintReport(['epoch', 'iteration', 'lr', 'main/loss', 'main/loss/loc', 'main/loss/conf', 'validation/main/map']), trigger=log_interval)
trainer.extend(extensions.ProgressBar(update_interval=10))

trainer.extend(extensions.snapshot(), trigger=triggers.ManualScheduleTrigger(args.step + [args.iteration], 'iteration'))
trainer.extend(extensions.snapshot_object(model, 'model_iter_{.updater.iteration}'), trigger=(args.iteration, 'iteration'))

アップデーターと実行回数の情報を渡して、Trainerクラスのインスタンスを作ります。

そして、そのトレーナーのオプションをいろいろ設定します。

学習の実行

if args.resume:
    serializers.load_npz(args.resume, trainer)

trainer.run()

コマンドライン引数でresumeが設定されている場合は、そのファイルを読み込んでネットワークにパラメータをセットします。つまり、以前の学習結果を読み込んで、続きの学習をするわけですね。

そしてトレーナーのrunメソッドを呼んで学習を実行します。

まとめ

つまりこのプログラムは、Pascal VOC 2007と2012のデータセットを読み込んで、データ拡張した上で、既存のモデルに対して学習を行うわけです。

流れはChainerの画像認識のチュートリアルとすごく似てますが、下記を調べないといけないですかね。

  1. データセットの様式
  2. 学習用のモデルのクラスの書き方
  3. ChainerCVのリンク(SSD300/SSD512)の使い方

広告

Chainerカテゴリの投稿