ステージ2-2: 線形回帰、グラフ描画の練習 (linear_model.LinearRegression, pl.scatter, pl.plot) (情報工学実験 3 : データマイニング班)
目次- 想定環境
- データセットの用意, グラフ描画 (np.linspace + np.polyval + pl.figure + pl.scatter + pl.plot + pl.show)
回帰モデルの動作を確認するため、様子を見やすいシンプルなデータセットを人工的に用意する。具体的には「1次式 y=ax+b」を用いたデータセット (x_base, y_base) と、出力yにノイズを付与したデータセット (x_base, y_noise) の2種類を用意し、どのようなデータになっているかを描画確認する。
- 最小二乗法
用意した2種類のデータセットに対し、最小二乗法により傾きと切片を求める。
- 線形回帰で推定 (linear_model.LinearRegression)
用意した2種類のデータセットに対し、線形回帰によりモデルを構築する。また、どのような境界面を生成したのかを描画して確認する。
- 参考サイト一覧
想定環境
- OS: Mac OS X 10.8.x (10.7.x以降であれば同じ方法で問題無いはず)
- Python: 2.7.x
- Mercurial: 2.2
- Scikit-learn: 0.13.1 (sklearn.__version__)
- matplotlib: 1.3.x (matplotlib.__version__)
- numpy: 1.8.0 (numpy.version)
- scipy: 0.13.0 (scipy.version)
データセットの用意
# 1次元サンプルを -5〜+5 の範囲でn分割して用意 #ここでは、分割数 = 事例数。 import numpy as np n = 50 x_base = np.linspace(-5, 5, n) # 1次式(y = a*x +b) で出力を用意。 # 今回は y = 0.8*x - 4 とする。 a = 0.8 b = -4 y_base = np.polyval([a, b], x_base) # 生成したデータセット(x_base, y_base) を散布図出力して確認 # pl.scatter(): s=点のサイズ import pylab as pl pl.figure() pl.scatter(x_base, y_base, s=2) pl.show() # y1_base にノイズを付与したデータセットを用意 # 0.5倍してるのはガウシアン分布のままだと、 # 元の値(y_base)に対してノイズの割合が大きすぎるため。 y_noise = y_base + np.random.normal(size=n) * 0.5 pl.figure() pl.scatter(x_base, y_noise, s=2) pl.show() # y_noise と実モデル(y=0.8*x-4)を同時に描画 # この実モデルを y_base や y_noise から推定したい。 pl.figure() pl.plot(x_base, y_base) pl.scatter(x_base, y_noise, s=2) pl.show()
最小二乗法
# 上記リンクを参考に、 # ノイズがない場合 (x_base, y_base) と、 # ノイズがある場合 (x_base, y_noise) における a,b を算出せよ。
線形回帰で推定、グラフ描画の練習 (linear_model.LinearRegression)
# x_base は1サンプル=1数値として列挙されている。
# 1サンプルを1リストとして表現するため、型変換。
# さらに、このままでは一部の機能が使えないため、np.ndarray() に変換。
# オブジェクトの方は type() で確認可能。
data_list = [[x_base[i]] for i in range(len(x_base))]
data = np.array(data_list)
target = y_base
# 線形回帰モデルを準備
from sklearn import linear_model
regr = linear_model.LinearRegression()
# 手動で fitting してみる
# LinearRegression(): coef_に傾き、intercept_に切片が得られる。
np.random.seed(0)
indices = np.random.permutation(len(data))
half = len(data)/2
data_train = data[indices[:half]]
data_test = data[indices[half:]]
target_train = target[indices[:half]]
target_test = target[indices[half:]]
regr.fit(data_train, target_train)
regr.score(data_test, target_test)
print "(LinearRegression:base) coef_=%s, intercept=%s" % (regr.coef_, regr.intercept_)
# ノイズデータでも fitting してみる
target = y_noise
target_train = target[indices[:half]]
target_test = target[indices[half:]]
regr.fit(data_train, target_train)
regr.score(data_test, target_test)
print "(LinearRegression:noise) coef_=%s, intercept=%s" % (regr.coef_, regr.intercept_)
# ノイズデータに対してシンプルに交差検定してみる
from sklearn import cross_validation
np.random.seed(0)
kfold = cross_validation.KFold(n=len(data), n_folds=2, shuffle=True)
scores = cross_validation.cross_val_score(regr, data, target, cv=kfold, n_jobs=-1)
print "scores =", scores
print "max = %s, ave = %s, min = %s" % (scores.max(), scores.mean(), scores.min())
# 交差検定しながら fitting 状況を描画
pl.figure()
pl.scatter(data, target, s=2)
for train_indices, test_indices in kfold:
train_data = [data[i] for i in train_indices]
train_target = [target[i] for i in train_indices]
regr.fit(train_data, train_target)
test_indices.sort()
test_data = [data[i] for i in test_indices]
test_target = [target[i] for i in test_indices]
estimated = regr.predict(test_data)
pl.plot(test_data, estimated)
pl.show()