Python: シリアライズって、偉大だったんだ・・・
今までずっと*1学習したモデルとかは
パラメータをテキストに書き出して再度読み込ませていました。
が、それってダメだったんですね。
いや、ダメじゃないんだけど。
シリアライズ、覚えました。
経緯
今、scikit-learnのSVMパッケージ
http://scikit-learn.org/stable/modules/svm.html#svm
を使っているのですが、それで沢山のSVMモデルを学習して、
後で再利用するということが必要です。
そこで、SVMインスタンスの内部パラメータをファイルに書き出して再読み込みしようとしたところ、動きませんでした。
幸い、近くにscikit-learnのコントリビュータがいるのでどうすればいいか聴いたところ、
シリアライズしなよ
ということでした。
scikit-learnにおける、モデルのシリアライズのやり方
http://scikit-learn.org/0.10/tutorial.html#model-persistence
に書いてありますが、これは少し冗長なようです。
以下で十分。
>>> from sklearn import svm >>> from sklearn import datasets >>> clf = svm.SVC() >>> iris = datasets.load_iris() >>> X, y = iris.data, iris.target >>> clf.fit(X, y) SVC(C=1.0, cache_size=200, coef0=0.0, degree=3, gamma=0.25, kernel='rbf', probability=False, scale_C=False, shrinking=True, tol=0.001)
>>> from sklearn.externals import joblib # do seriarize >>> joblib.dump(clf, 'svm.learned')
>>> .....
>>> clf2 = joblib.load('svm.learned') # do deseriarize
シリアライズのご利益
- 早い: バイナリなので、読み込みも書出しも早いです。
- 軽い: 例えば実際の局面では10000次元程度の線形SVMをつかったのですが、svmインスタンスのパラメータ全てをテキストに書くと259K byte。いっぽうシリアライズしたモデルは799 byte。300分の1になってる・・・
- 間違いが起こらない: 自分でモデルのパラメータをテキストファイルに書き出して、再度読ませると、その読み書きのメソッドを書く過程でバグが混入します。でもシリアライズだとそのままオブジェクト(インスタンス)を再現するのでそんな事が起こります。安心です
- 簡単に状態を再現できる: 上記の理由から、例えば学習中のモデルとか、事後分布と全パラメータの最終結果なんかを、簡単にプログラム内で再現させることができます。特に、ライブラリにモデル化をお任せしている場合には有効ですね。
シリアライズのあかんところ
まだ、こういう状況に遭遇していませんが、きっと以下のような問題があります
- 人の目で読めない: バイナリなので。例えばこれはどんな特徴量が効いているのかな、とか、クラスタリング結果はどうなのかな、とかの時に、いちいちプログラムを起動して、プログラム内で読ませないといけません。
- その言語(プログラム)じゃないと読めない: Javaの計算結果をシリアライズしても、それをmatlabやPythonに持って行ってよむことができません*2。さらに言えば同じJavaでも、まったく同じクラス構造を定義していなければ読めません。自分の研究専用の実装とかでやっていると、あまり嬉しくないのかも・・・??
結論
たとえばMCMCの計算過程を途中でシリアライズしてdump, 別の温度のMCMCに放り込んで、とかはすごくやり易くなりますね。あとデータサイズ小さいなら、例えばmatlabやPythonならば、今までの結果保存に加えて最終結果のシリアライズinstanceがあればお絵かきや評価などもやり易いかも知れません