こんにちは、えんせきです。
先日、モデルのパラメータを自分でも好き放題変えられるようになった。(転移学習的な意味で)
ensekitt.hatenablog.com
今まではExtensionsで自動的に保存されるやつを使っていたけど、他のタイミングでも保存するのでモデルの保存の仕方をまとめておく。
つまりなにしたの?
Chainer(3.2.0時点)で学習済のモデルを保存して、保存したモデルを読み込む。
NPZとHDF5という保存の形式
ChainerではNPZとHDF5という保存の形式がサポートされている
Serializers — Chainer 3.2.0 documentation
自分はPythonで完結させることが多いのでNPZばかり使っている。
NPZとは
NPZはNumpyのシリアライズ手法。
Chainerが動作する環境だったら使える。numpyから使う時のnumpy.savez()は既に揃っているデータにしか使えないので、シリアル化には2段階の操作が必要になる。最初にオブジェクト(ここではモデル)をフラットな辞書型にパッキングして、次にnpz形式にシリアル化する。
保存の対象
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みたいな名前の付け方にしている。