2020年1月14日火曜日

Eigenで重回帰分析をやってみる。

おじさんのおうちのポストに「今あなたのお手持ちのマンションを売ると○○○○万円です。」というチラシがよく入っています。

どうも全ての部屋毎に違う値が入っているらしい。
これ、どうやって計算しているんだろね。
なんでおじさんちの値段がわかるの?

https://www.ydc.co.jp/column/mi/mieruka02.html

いろいろ調べると、重回帰分析というやつをやればマンションの価格を求められるらしい。
行列を最小二乗法でいろいろ計算するっぽい。
だけど答えを求めるには逆行列と転置行列の掛け算をするだけじゃないか。
これ、マンションの売買データだけあればだれでも作れるぞ。

ということで、本日はC/C++言語で重回帰分析をやってみます。
C/C++で行列の計算を行う場合は、Googleが作ったEigenというライブラリを使えば簡単。
前にも書きましたが、Eigenはヘッダーのみで構成されているライブラリなので、インストールとかしないで、ヘッダーをインクルードするだけで使えます。
便利だねぇ。

ネットでEigenで重回帰分析やっている人を検索しましたが一人しかいませんでした。
http://cpp-kai.doorblog.jp/archives/2340422.html
さみしいねぇ。ひとりってどういうことよ。
これだとこの人があっているかどうかもわからないじゃないか。

Xt = X.transpose();
beta = (Xt*X).inverse()*Xt*y;

重要なのはこの2行。
たったこれだけで重回帰分析ができるのですね。

これを参考にしながら、ここにある体重と身長、腹囲、胸囲のエクセルでの重回帰分析をC++でやってみました。
https://udemy.benesse.co.jp/ai/multiple-regression-analysis.html

-----------------
-0.152591
  1.13726
 0.148569
-----------------

まぁ行列のサイズ変えるだけなんで簡単。
計算してみるとなんかエクセルと計算が合わない。

調べてみると定数項を0にするかどうかで係数の計算結果が違うらしい。
定数項を0の場合、とりあえずエクセルと計算値が一致。できた。

でも定数がある場合ってどうやって計算するんだろ?
ここがネットでやっている人が一人しかいない場合つらい。
なにをやっても必ずどこかではまるデータ解析。

ちょー調べてみると、入力行列の一番左の列に全部1を入れるとよいらしい。
よく考えると計算上そうだよね。

おーこれで日本初?切片付きの重回帰分析をEigenでできた。
エクセルとも完全一致。

重回帰分析ってeigenを使うと数行でできるのね。
これを体重じゃなくてマンションのデータでやれば価格がわかるんですね。
これが出来ると履歴書に「マンションの査定をすることができる」とかかけるんでしょうか?

今日はC++言語で重回帰分析でした。
次は相関係数やろうかなぁ。

-----------------
#include "Eigen_Core"
#include "Eigen_LU"
#include <iostream>

using namespace std;

int main(int argc, char* argv[])
{
#if 0
//切片なし
Eigen::Matrix<double, 10, 3> X;
X <<
177.5, 88.2, 95.2,
173.0, 75.6, 83.3,
168.8, 70.2, 78.3,
165.5, 67.0, 75.6,
164.5, 62.4, 72.3,
160.2, 60.0, 69.9,
170.2, 69.4, 77.9,
180.2, 80.2, 88.2,
182.3, 88.3, 93.5,
160.3, 62.0, 74.9;
Eigen::Matrix<double, 10, 1> y;
y <<
82.3,
70.4,
65.3,
66.2,
54.1,
55.0,
58.8,
77.7,
92.8,
60.4;
Eigen::Matrix<double, 3, 10> Xt;
Xt = X.transpose();
Eigen::Matrix<double, 3, 1> beta;
#else
//切片あり
Eigen::Matrix<double, 10, 4> X;
X <<
1, 177.5, 88.2, 95.2,
1, 173.0, 75.6, 83.3,
1, 168.8, 70.2, 78.3,
1, 165.5, 67.0, 75.6,
1, 164.5, 62.4, 72.3,
1, 160.2, 60.0, 69.9,
1, 170.2, 69.4, 77.9,
1, 180.2, 80.2, 88.2,
1, 182.3, 88.3, 93.5,
1, 160.3, 62.0, 74.9;
Eigen::Matrix<double, 10, 1> y;
y <<
82.3,
70.4,
65.3,
66.2,
54.1,
55.0,
58.8,
77.7,
92.8,
60.4;
Eigen::Matrix<double, 4, 10> Xt;
Xt = X.transpose();
Eigen::Matrix<double, 4, 1> beta;
#endif
beta = (Xt*X).inverse()*Xt*y;
std::cout << beta << std::endl;

return 0;
}
-----------------



0 件のコメント:

コメントを投稿