概要
今までのレッスンで学んできたのは、すべてアウトプットが離散的(2値)だったが、数値を推定するものを回帰という。例えば、年齢から、年収を予測するようなもの。
下記の図の、赤い丸から直線を引くこと。

Slope:直線の傾き
Intercept:切片
Coding it up!
上記のage-net worth問題を回帰で解く。
このプログラミングはUdacityに埋め込んであるpythonで、ブラウザで行う。ちなみにpython2系です。
import numpy
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
from studentRegression import studentReg
from class_vis import prettyPicture, output_image
from ages_net_worths import ageNetWorthData
ages_train, ages_test, net_worths_train, net_worths_test = ageNetWorthData()
reg = studentReg(ages_train, net_worths_train)#studentReg()にてregression
plt.clf()
plt.scatter(ages_train, net_worths_train, color="b", label="train data")
plt.scatter(ages_test, net_worths_test, color="r", label="test data")
plt.plot(ages_test, reg.predict(ages_test), color="black")
plt.legend(loc=2)
plt.xlabel("ages")
plt.ylabel("net worths")
plt.savefig("test.png")
output_image("test.png", "png", open("test.png", "rb").read())
def studentReg(ages_train, net_worths_train):
### import the sklearn regression module, create, and train your regression
### name your regression reg
### your code goes here!
from sklearn import datasets, linear_model
reg = linear_model.LinearRegression()
reg.fit(ages_train, net_worths_train)
return reg
青い点がトレーニングデータで、赤い点がテストデータ。linear regression(線形回帰)が引いた線が、直線。いい感じにひけてますねー。テストデータはトレーニングデータで引いた回帰式が、どのくらい正しいか評価するのに使う(reg.score())。テストデータでスコアが低いと、過学習しているということ。
よく使うAttributesとmethodsの紹介
.coef_ : 回帰式の係数出力 .intercept_ : 切片を出力 .score(ages_test, Net_worths_tests) : テストデータでの精度出す。 .score(ages_train, net_worths_train) : トレーニングデータでの精度出して、テストデータと比べ、過学習か判定する。回帰式の評価の仕方
どうやって回帰式:y = ax + b のa,bを決めているかというと、
\sum_{全トレーニングデータ} (トレーニングポイント-推定値)
を最小化しているみたい。
最小化する方法はいくつかあって、有名なのは
・Ordinary Least Squares(OLS):最小二乗回帰
・Gradient descent:最急降下法
最小二乗法:Ordinary Least Squares(OLS)
最小二乗法の場合、実際にどうやって回帰式を求めているのかは
最小二乗法の意味と計算方法 - 回帰直線の求め方がわかりやすかった。
下記引用(数式かくの面倒だったので、スクリーンショト画像です)

詳しくは上記リンク先参照。
なぜ誤差の計算の仕方が「絶対値の引き算」ではなく「二乗の引き算」なのかは、下記図参照。二乗しないと収束しないんですね。
r sqeared:決定係数
学習して得られた回帰線をどうやって評価するか?すぐ思いつくのは評価方法に、SSE(Sum of Squared Error)を使うことだが、これだと、データ数が多ければ、それだけSSEも大きくなってしまう。そこで出てくるのは決定係数。
入力特徴量と出力の関係をどの程度よく表しているかを表現する。1に近いほどよく表している。
学習した予測器の評価に使う値。なのでclf.score(X,y)のメソッドで使える。
ここがすごくわかりやすかったです。
27-4. 決定係数と重相関係数
簡潔に言うと、
R^2 = \frac{\sum_{i=1}^{n}{(データのyの平均から推定値がどれだけ差があるか)^2}}{\sum_{i=1}^{n}{(データのy平均値と各データのyがどれだけ差があるか)^2}}
ポイントは、各データに対する推定値の平均からの差分(回帰変動)を各データの生のyの平均からの差分(全変動)で割っているので、データ数と比例して大きくならない点ですね。二乗しているのはおそらく、そうしないと二乗誤差の時と同じように収束しないからでしょう。
Multi-variate regression:多変量回帰
今までは入力-出力の関係が1vs1の場合を話ししてきたが、複数vs1の場合もある。
Mini-project
Enronデータセットを使って、さまざまな特徴量から、ボーナスの額を推定する回帰を行う。
後半には、outlier(外れ値)が、回帰に与える影響を見ていく。
参考はsklearn正式ドキュメントsklearn.linear_model.LinearRegression
### list the features you want to look at--first item in the
### list will be the "target" feature
features_list = ["bonus","salary",]
data = featureFormat( dictionary, features_list, remove_any_zeroes=True)
target, features = targetFeatureSplit( data )
### training-testing split needed in regression, just like classification
from sklearn.cross_validation import train_test_split
feature_train, feature_test, target_train, target_test = train_test_split(features, target, test_size=0.5, random_state=42)
train_color = "b"
test_color = "r"
### Your regression goes here!
### Please name it reg, so that the plotting code below picks it up and
### plots it correctly. Don't forget to change the test_color above from "b" to
### "r" to differentiate training points from test points.
# print(dictionary.items())
from sklearn import linear_model
reg = linear_model.LinearRegression()
print("**feature_train**\n"+str(feature_train))
print("**target_train**\n"+str(target_train))
reg.fit(feature_train,target_train)
print("slope:"+str(reg.coef_))
print("intercept:"+str(reg.intercept_))
score_tr = reg.score(feature_train,target_train)
print("score_train:"+str(score_tr))
score_te = reg.score(feature_test,target_test)
print("score_test:"+str(score_te))
Your regression goes here!以下を書いた。
<出力>
**feature_train**
[array([415189.]), array([243293.]), array([213625.]), array([184899.]), array([248546.]), array([221003.]), array([197091.]), array([261516.]), array([309946.]), array([248146.]), array([213999.]), array([278601.]), array([304110.]), array([269076.]), array([262663.]), array([272880.]), array([240189.]), array([339288.]), array([278601.]), array([265214.]), array([201955.]), array([251654.]), array([365038.]), array([330546.]), array([76399.]), array([229284.]), array([261879.]), array([329078.]), array([211844.]), array([267102.]), array([239502.]), array([211788.]), array([170941.]), array([273746.]), array([182245.]), array([262788.]), array([304588.]), array([271442.]), array([314288.])]
**target_train**
[1000000.0, 1500000.0, 1000000.0, 325000.0, 850000.0, 70000.0, 400000.0, 750000.0, 700000.0, 600000.0, 5249999.0, 800000.0, 2000000.0, 650000.0, 700000.0, 750000.0, 1250000.0, 8000000.0, 1350000.0, 600000.0, 4175000.0, 1100000.0, 1100000.0, 900000.0, 100000.0, 400000.0, 1000000.0, 750000.0, 200000.0, 1200000.0, 500000.0, 1700000.0, 350000.0, 1000000.0, 200000.0, 1000000.0, 2500000.0, 3100000.0, 800000.0]
slope:[5.44814029]
intercept:-102360.5432938796
score_train:0.04550919269952436
score_test:-1.48499241736851

トレーニングデータで学習して傾きと切片出して、テストデータで直線引いてる。
Video44
3行目の
features_list = ["bonus","salary",]
を
features_list = ["bonus",“long_term_incentive”,]
に書き換えればよい。コードは上記。
<出力>
feature_train
[array([200000.]), array([100000.]), array([69223.]), array([1586055.]), array([1617011.]), array([300000.]), array([974293.]), array([156250.]), array([1617011.]), array([1294981.]), array([694862.]), array([300000.]), array([422158.]), array([323466.]), array([175000.]), array([125000.]), array([2234774.]), array([554422.]), array([335349.]), array([71023.]), array([554422.]), array([554422.]), array([75000.]), array([2035380.]), array([983346.]), array([275000.]), array([304805.])]
target_train
[325000.0, 750000.0, 1700000.0, 1200000.0, 2000000.0, 1000000.0, 1350000.0, 100000.0, 1500000.0, 3000000.0, 2600000.0, 700000.0, 600000.0, 400000.0, 200000.0, 400000.0, 200000.0, 100000.0, 600000.0, 600000.0, 1100000.0, 2000000.0, 300000.0, 8000000.0, 1150000.0, 300000.0, 4175000.0]
slope:[1.19214699]
intercept:554478.7562150093
score_train:0.21708597125777662
score_test:-0.5927128999498639

トレーニングデータへのスコアは下がったが、テストデータに対しては上がっている。スコアだけを見ると特徴量としてはlong_term_incentiveのほうが優れていることがわかる。
Video46:外れ値
外れ値(Outliner)の影響を見てみるために、トレーニングデータに外れ値があると、どの程度回帰線が変化するのか見てみる。
外れ値があるテストデータ(赤)でトレーニングして(テストデータとトレーニングデータデータを入れ替えている)、プロットする為に、下記コードを足すよう指示あり。
reg.fit(feature_test, target_test)
plt.plot(feature_train, reg.predict(feature_train), color="b")
print("slope_new:"+str(reg.coef_))
を下のほうに足した。
### draw the scatterplot, with color-coded training and testing points
import matplotlib.pyplot as plt
for feature, target in zip(feature_test, target_test):
plt.scatter( feature, target, color=test_color )
for feature, target in zip(feature_train, target_train):
plt.scatter( feature, target, color=train_color )
### labels for the legend
plt.scatter(feature_test[0], target_test[0], color=test_color, label="test")
plt.scatter(feature_test[0], target_test[0], color=train_color, label="train")
### draw the regression line, once it's coded
try:
plt.plot( feature_test, reg.predict(feature_test) )
except NameError:
pass
### Video46で足すように指示されたコード###
reg.fit(feature_test, target_test)
plt.plot(feature_train, reg.predict(feature_train), color="b")
print("slope_new:"+str(reg.coef_))
######
plt.xlabel(features_list[1])
plt.ylabel(features_list[0])
plt.legend()
plt.show()
左下に、短い回帰線が追加されている。トレーニングデータに対して、プロットしているので、回帰線の長さが、短いのはご愛敬。
確かに一番右の外れ値に影響されて、回帰線がかなり寝ているのがわかる。
感想
今回復習と記録のために2回目受けてみた。
最小二乗法で誤差計算しないと、回帰線が一意に決まらないことが直観的に示せたのは良かった!
決定係数は完全に忘れていたので、復習してよかった。
調べた英単語
constraint・・・n, 強制、圧 迫、束縛、制約
arbitrary・・・n, 任意の、恣意(しい)的な、勝手な
discrete・・・n, 分離した、不連続の(continuous vs discrete)
coefficient・・・n, 係数
shortcoming・・・n, 短所、欠点
hefty・・・adj, かなりの、重い、屈強な
ex)hefty bonus


