こんにちは。
今回は、線形回帰(単回帰)を最小二乗法を使って行う方法について書いていきます。
単回帰は回帰の中でも、簡単なので覚えるといいと思います。
それでは書いていきます。
線形回帰(単回帰)の考え方
前提
まず、以下のように実験などでデータが取れたとします。
この時に、なんとなく線が引けそうなので、線が引きたいと思います。
単回帰では、その線の式を以下のように考えます。
見てわかるように、単純な一次関数ですね。
式を見ると、とが求まれば、線の式がわかりそうです。
最小二乗法
最小二乗法では、上の式のとを各点との誤差が小さくなるように求めます。
例えば、下の図の緑矢印の大きさが誤差にあたります。
今回は上図のようにy軸方向の誤差を最小とするように考えます。
ここで、赤点の位置を とすると、
その点と の誤差の大きさは次のようになります。
このままでは、この値が正の時と負の時があって扱いずらいので、二乗して正のみになるようにします。
また、これは一点のみについての話なので、仮に赤点が全部でN点あったとすると、それらの誤差の2乗の和は以下のようになります。
結局は、この式の値を最小化するということになります。
上の式を展開すると、
となります。
この式が最小になるとき、 , での偏微分の値が0となるので、
, で偏微分して、
で偏微分 :
で偏微分 :
これを、連立方程式とみなして、解くと以下のようになります。
ここで、 , はそれぞれ , の平均値としています。
小まとめ
- のように点がたくさんあって、それに直線を引きたい
- 直線を引くには、誤差の二乗の和を最小化する(最小二乗法)
- 誤差の二乗の和を最小化するには、偏微分をする
- 結果として、以下のようになる
C言語でコードを書く
今回は以下のような点を与えます。
x | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
y | 1.16 | 5.07 | 5.22 | 6.59 | 10.92 | 11.52 | 13.11 | 17.09 | 16.66 | 20.6 |
Excelでみると、以下のようになります。
Excelの近似曲線で入れた式も出しています。
コードは以下のように書きました。
#include <stdio.h> int main(void){ // 入力点 double xs[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; double ys[10] = {1.16, 5.07, 5.22, 6.59, 10.92, 11.52, 13.11, 17.09, 16.66, 20.6}; // xとyの平均を求める double x_sum = 0.0; double y_sum = 0.0; for(int i=0; i<10; i++){ x_sum = x_sum + xs[i]; y_sum = y_sum + ys[i]; } double x_ave = x_sum / 10.0; double y_ave = y_sum / 10.0; // aの値を求める double a_top = 0.0; double a_bottom = 0.0; for(int i=0; i<10; i++){ a_top = a_top + (xs[i]-x_ave)*(ys[i]-y_ave); a_bottom = a_bottom + (xs[i]-x_ave)*(xs[i]-x_ave); } double a = a_top / a_bottom; // bの値を求める double b = y_ave - a*x_ave; // aとbの結果を表示する printf("a: %lf\n", a); printf("b: %lf\n", b); }
これを実行すると、以下のような結果が得られます。
Excelで実行した結果とあっていることが確認できました。
今回はこれで終わります。