プロジェクトで「多ラベルの回帰予測」をしなければならないことになりました。
※機械の自動運転なのですが、調整する値が20個ほどある
ですが、多ラベル出力に対応していないregressorが結構あるので
その時に使ったscikit-learnのMultiOutputRegressorについて書いていきます!
回帰予測で他ラベル出力するには
回帰予測で他ラベル出力するにはいくつか方法があります。
1. 元々他ラベル出力に対応しているRegressorを採用する
→scikit-learnのRandomForestが代表的ですが、もともと他ラベル出力に対応しているものがあります。
これを使えば、複数のラベルが入ったデータを学習データとして与えても大丈夫!
2. ニューラルネットワークを使う
→ニューラルネットワークは隠れ層や出力層の数を変えられるため、当然出力層の数を変えれば多ラベル出力も可能です。
(私はニューラルネットワークを使ったことがないクソ雑魚のため、この案はスルーしました)
3. scikit-learnのMultiOutputRegressorを使う
→これを使えば多ラベル出力に対応していないRegressorも出力させることができます。
RandomForest おっそ...
いや、これなんですよね...
上の方法を見たとき「いや、じゃあRandomForest使えよ」って思いませんでした?
私も最初RandomForestで頑張ってたわけなんですが学習遅くね...?ということなんですよ。
精度は別に悪くないと思うんですけどね。
そこで、kaggleで使ったことのあるLightGBMを使ってみたところ、クッソ爆速。
「じゃあ、LightGBMに変えよー!」と思ったらLightGBMは多ラベル出力に対応してないんですね...
そのままデータを渡して学習させようとするとValueErrorになってしまいます。
ValueError: DataFrame for label cannot have multiple columns
そういう時にMultiOutputRegressorなんすわぁ
そういう「使いたいRegressorがあるけど多ラベル出力に対応してない」時に使えるのがMultiOutputRegressor
!!
使い方は正直めちゃくちゃ簡単です。
例えばLightBGMで以下のように書いて、y
がラベルだとしますよね?
import lightgbm as lgb
params={'learning_rate': 0.05,
'objective':'mae',
'metric':'mae',
'num_leaves': 7,
'verbose': 0,
'bagging_fraction': 0.7,
'feature_fraction': 0.7
}
reg = lgb.LGBMRegressor(**params, n_estimators=500)
reg.fit(x, y)
これが、こう!
from sklearn.multioutput import MultiOutputRegressor
import lightgbm as lgb
params={'learning_rate': 0.5,
'objective':'mae',
'metric':'mae',
'num_leaves': 9,
'verbose': 0,
'bagging_fraction': 0.7,
'feature_fraction': 0.7
}
reg = MultiOutputRegressor(lgb.LGBMRegressor(**params, n_estimators=500))
reg.fit(x, y)
そう!LightGBMのオブジェクト作成するところをMultiOutputRegressor()
で包むだけです。
これだけで、多ラベルデータを学習・予測できるようになります。やったぜ。
課題?
MultiOutputRegressor使っていて問題とまでは言いませんが感じたことを書いていきます。
各ラベルの予測モデルよりは精度が落ちている気がする
これ、当たり前といえば当たり前な気がしますがそんな気がします。
MultiOuputRegressorを使わずに、ラベルの数だけモデルを作って予測させた場合と比べると
やはり少しですが精度が落ちてます。
これは、モデルをひとつにすることで、本来必要ないデータも学習することになるからだと思います。
あるラベルでは必要ないデータでも、他のラベルの学習に必要なデータであれば全て学習データに含める必要があります。
結果的に、各ラベル単位で見ると無駄に多い学習データを使っていることになります。
MultiOuputRegressorの内部的な仕組みとしては、ラベルの数だけ独立して予測させているようなので
やはり不要なデータが増えているのが要因なんでしょうなあ。
feature_importanceが使えない
これも仕方ないのかもしれませんが、特徴量選択によく使うので使えないのは困ります。
私はfeature_importanceを見るためだけに各ラベルごとのモデルを作って見てました。二度手間。
(上でも書いたように、内部的にはラベルごとに独立で動いているので結果はほとんど同じはず)
for文ぶん回して放っておくだけなので言う程手間でもないんですが、
やはりMultiOuputRegressorで包んだやつから直接見れたらラクなのになーとは思っちゃいますね。
終わり
とはいえとはいえ、導入も物凄く簡単で便利なので、ぜひ使ってみてくださいー!