質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

1回答

2607閲覧

Pythonで作成した機械学習の学習機をサイズを抑えて保存する方法

i113

総合スコア74

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

0グッド

0クリップ

投稿2019/06/19 06:12

前提・実現したいこと

scikit-learnのRandomForestRegressorで機械学習を行っています。
特徴量は16個で予測値は1個です。
1000000サンプルでトレーニングしたモデルをpickleで保存したところ、容量が4.8GBになりました。
また3000000サンプルにしたところ8.3GBになりました。サンプル数に応じて学習機の容量が増えているように思えます。
モデルの複雑さを制御するパラメータはいじっていません。
機械学習については最近勉強を始めたばかりの初心者ですので、素人考えになりますが、
モデルの複雑さが変わらないのに、サンプル数が増えただけで学習機の容量が増えるというのが釈然としません。
もしpickleで保存するさいに予測に必要ない情報(トレーニングデータなど)も一緒に保存しているのなら、
除いてから保存したいのですが、そのようなことは可能でしょうか?

該当のソースコード

python

1from sklearn.ensemble import RandomForestRegressor 2import pickle 3forest = RandomForestRegressor(n_estimators=198, max_features=10, max_depth=20, n_jobs=22, random_state=1) 4forest.fit(X_train_1million, y_train_1million) 5print("Training set score: {:.2f}".format(forest.score(X_train_1million, y_train_1million))) 6print("Test set score: {:.2f}".format(forest.score(X_test, y_test))) 7pickle.dump(forest, open('/home/Forest1M.pickle', 'wb')) 8 9Training set score: 0.98 10Test set score: 0.93 11Forest1M.pickle | 4,800,958 KB 12

python

1from sklearn.ensemble import RandomForestRegressor 2import pickle 3forest = RandomForestRegressor(n_estimators=198, max_features=10, max_depth=20, n_jobs=22, random_state=1) 4forest.fit(X_train_3million, y_train_3million) 5print("Training set score: {:.2f}".format(forest.score(X_train_3million, y_train_3million))) 6print("Test set score: {:.2f}".format(forest.score(X_test, y_test))) 7pickle.dump(forest, open('/home/Forest3M.pickle', 'wb')) 8 9Training set score: 0.97 10Test set score: 0.93 11Forest3M.pickle | 8,281,566 KB 12

補足情報(FW/ツールのバージョンなど)

Python3、Jupyter Labを使用

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

アルゴリズム的には、データそのものを内部に保持する必要はないはずです。実装を見ていないので、もしかしたら保持してしまう実装になっているかもしれませんけど(基本的には考えづらい)。

ランダムフォレストの場合、パラメータを変えなくても、サンプル数を増やせばモデルの複雑性が上がるということはありえます。データの細かい分布がわかるようになりますし、増えた情報を保持させるために木の各枝が深くなるからです(max_depthは最大の深さを制限するだけですので、max_depthに達しない枝が実際にはたくさん存在します。サンプル数が増えるとそういう枝が減り、max_depthに達した枝が増えます)。

全体で8GBということは木1つあたり40MBほど使っていることになる訳ですが、決定木は最大で1(2^0)+2+4+8+16+32+...+524288(2^19)=1048575の中間ノードを保持しないといけなくなります(木の深さの計算方法の絡みで厳密な数字が間違っている可能性はありますが、概数ではこんなものです。また、あくまでも「最大」の数字で、もっと効率よく保持できれば、あるいは逆に効率が悪くてどこかの枝に偏ってその枝が最大深さに達すれば、当然その分だけ減ります。今回くらいデータ量が多いと、ほぼこれくらい要ると思いますが)。そしたらノード1つで数byte~数十byteくらいの感覚なので、まあそんなもんじゃね? ということです。


こういうケースではjoblib.dumpが良いかもしれません。圧縮して書き出すことが可能です。これでたぶん1/10くらいに減るでしょう。

https://joblib.readthedocs.io/en/latest/generated/joblib.dump.html

別途joblibを入れてもいいですし、実はsklearnの中に入っていて(バンドルされていて)from sklearn.externals import joblibでimportすることも可能です。

投稿2019/06/19 07:24

編集2019/06/19 12:45
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

i113

2019/06/19 09:25

どうもありがとうございます。 試しにmax_depth=4にしたところサンプル数を変えても保存サイズが変化しなくなりました。 またjoblibを使って保存サイズを減らすことにも成功しました。
hayataka2049

2019/06/19 12:37 編集

そもそも1000000サンプルを完全に区別するのに20bit、3000000サンプルなら22bit要るので、最良の効率でも木の深さの限界に達しますね。実際には浅いとこと深いとこがある訳ですが…… 逆に言うと、木の深さ20でも8GBとかせいぜい10GBくらいでほぼ飽和するはずです。ただ、でかいですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問