EnsekiTT Blog

EnsekiTTが書くブログです。

転ばぬ先のChainerでモデルを保存する話

こんにちは、えんせきです。
先日、モデルのパラメータを自分でも好き放題変えられるようになった。(転移学習的な意味で)
ensekitt.hatenablog.com

今まではExtensionsで自動的に保存されるやつを使っていたけど、他のタイミングでも保存するのでモデルの保存の仕方をまとめておく。

つまりなにしたの?

Chainer(3.2.0時点)で学習済のモデルを保存して、保存したモデルを読み込む。

追記(2017年12月17日)

私はいつも同じマシンで動かしているので、ModelやOptimizerをGPUのまま保存していますが、他で使うならCPUに変換して保存したほうが良い。

model.to_cpu()
# とか
optimizer.to_cpu()

を入れればできる。
読み込むときは逆に

model.to_gpu(デバイス番号)
# とか
optimizer.to_gpu(デバイス番号)

GPUに戻せる。

f:id:ensekitt:20171214005317j:plain
*1

NPZとHDF5という保存の形式

ChainerではNPZとHDF5という保存の形式がサポートされている
Serializers — Chainer 3.2.0 documentation
自分はPythonで完結させることが多いのでNPZばかり使っている。

NPZとは

NPZはNumpyのシリアライズ手法。
Chainerが動作する環境だったら使える。numpyから使う時のnumpy.savez()は既に揃っているデータにしか使えないので、シリアル化には2段階の操作が必要になる。最初にオブジェクト(ここではモデル)をフラットな辞書型にパッキングして、次にnpz形式にシリアル化する。

HDF5とは

HDF5は、データを格納および管理するデータモデルで、そのライブラリやファイルフォーマットそのものを指す。
データ型には制限がなく、割りと大量かつ複雑なデータ用に設計されているらしい。
HDF5はポータブルで別の処理系にのせることもできるからPythonで作ってMatlabで読むとかもできる。

保存の対象

model

モデルそのもの。学習結果とモデルの構造が保存されるので、これを学習ではなく活用のアプリから読み出してやれば、活用できる。

optimizer

最適化インスタンス。学習の途中経過とか勾配情報が保存されるので、これを保存しておくと後で効率よく学習を再開できる。

NPZのSaveとLoad

Save

model = myConvNN()
model.to_cpu()
chainer.serializers.save_npz('my_model.npz', model, compression=True)

'my_model.npz'はfileオプションで書き込むファイル名
modelはobjオプションで書き込むオブジェクト
compression=TrueはZipで圧縮するかのオプションでデフォルトTrue

Load

model = myConvNN()
chainer.serializers.load_npz('my_model.npz', model, path='', strict=True)
model.to_gpu(デバイス番号)

'my_model.npz'はfileオプションで読み込むファイル名
modelはobjオプションで読み込むオブジェクト
path=''はシリアライズしてあるものの中の階層を指定する。先の方式でSaveしてあるならそのまま読み出すなら指定しなくて良い。
strict=Trueは指定されたNPZファイルに期待した形で格納されていない場合にエラーを投げる。Falseの場合は、無視して読み込む。デフォルトTrue

HDF5のSaveとLoad

Save

model = myConvNN()
model.to_cpu()
chainer.serializers.save_hdf5('my_model.npz', model, compression=4)

'my_model.npz'はfilenameオプションで書き込むファイル名
modelはobjオプションで書き込むオブジェクト
compression=数字はGzipの圧縮レベルを決める。デフォルトは4になっている。
gzipコマンドのデフォルトは6だった気がするので、コマンドのデフォルトからちょっと圧縮率を妥協して、高速化を推奨している?)

Load

model = myConvNN()
chainer.serializers.load_hdf5('my_model.npz', model)
model.to_gpu(デバイス番号)

'my_model.npz'はfilenameオプションで読み込むファイル名
modelはobjオプションで読み込むオブジェクト

こまめなモデルの保存を

今回紹介したスニペットだと上書きしてしまうので、何度も学習したり保存したりを繰り返す場合は、何かしら名前を分けると良いと思う。
自分はいつもタイムスタンプと何かあればコメントを入れて、yyyymmdd_HHMMSS_[comment]_model.npzみたいな名前の付け方にしている。

一晩の電気代を処理系の停止でうっかり消さないようにしよう

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。