静かなる名辞

pythonとプログラミングのこと

複数の目的変数で回帰を行う方法

はじめに

 回帰分析を行う際、複数の目的変数に対して回帰をしたい場合があります。普通のモデルではできないのでちょっと面食らいますが、やり方は色々あるようです。

 目次

目的変数の数だけ回帰モデルを作る方法

 単純に考えると、一つの目的変数を出力する回帰モデルを目的変数の数だけ用意してやれば、所要を達しそうです。

 python+sklearnを使えば、これに対応したモデルが最初から用意されています。

sklearn.multioutput.MultiOutputRegressor — scikit-learn 0.19.1 documentation

 コンストラクタには好きな回帰モデルを渡してあげることができます。それが目的変数の数だけコピーされ、内部で束ねられて回帰に使われます*1

複数の目的変数に対応したモデルを使う

 上の方法は単純ですが、回帰モデルの中には自然に複数の出力に対応しているものもあります。

 そういったモデルを使うことにどんなメリットがあるのか? というと、まず目的変数の数だけ回帰モデルを作るのと比べて無駄が減るので、計算コストがケチれる可能性があります(あくまでも「可能性」の話)。また、複数存在する目的変数の間に何らかの相関性があれば、それも踏まえて上手く学習することでモデルの性能が上がる可能性があります(こちらもあくまでも「可能性」)。

 そういった複数の目的変数に対応したモデルを幾つか紹介します。すべては網羅しきれないので、その点はご承知ください。

正準相関分析

 正準相関分析はこの手の話で出てくる代表的なモデルです。単純な手法ですが、けっこう奥深いといえば奥深いです。

 参考(過去に書いた記事):【python】正準相関分析(Canonical Correlation Analysis)を試してみる - 静かなる名辞

 これの良いところは、説明変数と目的変数*2のそれぞれでPCAみたく新たな軸を張り、次元削減を行ってくれることです。説明変数ン百次元、目的変数20次元みたいなケースだったとしても、次元削減の効果で「わかりやすい」結果が得られる可能性があります。つまり、現象を説明するモデルとしては非常に適しています。

 欠点は、回帰モデルとして考えると性能が高いと言えるかは微妙なこと、非線形への対応は基本的にはないことです。カーネルPCAみたくカーネル法非線形対応させたモデルもありますが、良さげなライブラリが見当たらないのと、そこまでするなら他の手法を使いたいという気持ちがあるので紹介しません。

 sklearnのモデルはこれです。上に書いた通りカーネル正準相関の実装はありません。

sklearn.cross_decomposition.CCA — scikit-learn 0.19.1 documentation

 predictメソッドでXからYを予測できるので、普通に回帰に使えます。 

 入出力が割と線形なデータで、「説明」を重視したいときは使えると思います。

ランダムフォレスト回帰

 なぜかランダムフォレスト回帰は複数出力に対応しています。解説論文を見つけたので貼っておきます。興味のある方はどうぞ(私は読んでいません)。

 とにかく使いたければsklearnのRandomForestRegressorはそのまま使えます。目的変数も説明変数と同様に配列で入れてあげてください。

3.2.4.3.2. sklearn.ensemble.RandomForestRegressor — scikit-learn 0.19.1 documentation

多層パーセプトロンニューラルネットワーク回帰)

 ニューラルネットですからできて当然。複数出力にするためにやることといったら出力層ユニット数を増やすだけですから、一番シンプルかもしれません。これもsklearnのがそのまま使えます。

sklearn.neural_network.MLPRegressor — scikit-learn 0.19.1 documentation

まとめ

 複数の目的変数に対して回帰を行う場合について、2種類の方法を説明しました。

  • 単純に目的変数の数だけ回帰モデルを用意する方法
  • 複数の目的変数を出力できるモデルを用いる方法

 どちらが良いかは一概には言えません。データや目的に応じて、あるいは実際に走らせてみて評価指標や計算コストを勘案して考える必要があります。複数の目的変数に最初から対応したモデルの方が良いような気もしますが、そうとも言えないんじゃという話もあったりします。

 でもまあ、色々な選択肢があることは良いことです。なのでまあ、いろいろ勘案して選べば良いでしょう。適当ですがこんな感じでシメます。

*1:ということだと思う・・実装読んでいないので断言しかねます

*2:回帰の記事なのでそう呼ぶが、ぶっちゃけ妥当ではない。CCAの枠組みではどっちがどっちでも大して構わないのだし