scikit-learnで学習した分類器を保存する場合、joblib.dumpを使用するが、これだと、大量のnpyファイルが作られる。この場合、joblib.dumpのcompressを使うとよい。まず、例えば以下のような、train.pyがあるとする。
#!/usr/bin/env python # -*- coding: utf-8 -*- from sklearn.datasets import load_svmlight_file from sklearn.multiclass import OneVsRestClassifier from sklearn.svm import LinearSVC from sklearn.externals import joblib def main(): # MNISTの訓練データセットを読み込む。 tr_samples, tr_labels = load_svmlight_file('mnist.scale') # one-versus-restで線形SVM分類器を学習する。 # n_jobsを-1にするとパラレルで実行してくれる。 classifier = OneVsRestClassifier(LinearSVC(), n_jobs=-1) classifier.fit(tr_samples, tr_labels) # 学習した分類器を保存する。 joblib.dump(classifier, 'svc.pkl') if __name__ == '__main__': main()
これを実行すると、大量のnpyファイルが作られる。まあ美しくない。
$ ./train.py $ ls -1 svc.pkl_01.npy svc.pkl_02.npy svc.pkl_03.npy ... svc.pkl_51.npy svc.pkl train.py mnist.scale mnist.scale.t
学習した分類器を一つのファイルに保存したい場合は、joblib.dumpの部分でcompress引数にTrueを指定する。compressは0から9の整数をとり、値が大きくなるほど圧縮率が高まる。 Trueを指定するとcompress=3と同じになる。拡張子はなんでも良いけど、「圧縮しましたよ」ということで「.cmp」をつけてみた。
joblib.dump(classifier, 'svc.pkl.cmp', compress=True)
これを実行すると、学習した分類器が、たった一つのファイルにまとめられる。
$ ./train.py $ ls -1 svc.pkl.cmp train.py mnist.scale mnist.scale.t
読み込みは、圧縮しない場合と同様で、joblib.loadで良い。例えば以下のような、test.pyを用意する。
#!/usr/bin/env python # -*- coding: utf-8 -*- from sklearn.datasets import load_svmlight_file from sklearn.externals import joblib from sklearn.metrics import accuracy_score def main(): # MNISTのテストデータセットを読み込む。 te_samples, te_labels = load_svmlight_file('mnist.scale.t') # 学習した分類器を読み込む。 classifier = joblib.load('svc.pkl.cmp') # パラメータを表示してみる。 print classifier # ラベルを推定する。 pr_labels = classifier.predict(te_samples) # Accuracyを計算してみる。 print accuracy_score(te_labels, pr_labels) if __name__ == '__main__': main()
これを実行すると、one-versus-restな線形SVM分類器がちゃんと読み込まれているのがわかる。
$ ./test.py OneVsRestClassifier(estimator=LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, loss=l2, multi_class=ovr, penalty=l2, random_state=None, tol=0.0001, verbose=0), estimator__C=1.0, estimator__class_weight=None, estimator__dual=True, estimator__fit_intercept=True, estimator__intercept_scaling=1, estimator__loss=l2, estimator__multi_class=ovr, estimator__penalty=l2, estimator__random_state=None, estimator__tol=0.0001, estimator__verbose=0, n_jobs=-1) 0.918
圧縮されているので、ファイルサイズもそれなりに小さい。 libsvmやliblinearをコマンドで使うと、重みとかパラメータが書かれたテキストファイルが作られる。 MNISTぐらいだと大したことないけど、特徴ベクトルの次元数が大きいと、ファイルサイズも大きくなってツラい。 そういう意味でも良い。
$ liblinear-train -q -s 2 mnist.scale mnist.scale.model $ ls -l mnist.scale.model | awk '{print $4"\t"$8}' 147K mnist.scale.model $ ls -l svc.pkl.cmp | awk '{print $4"\t"$8}' 55K svc.pkl.cmp