-Python- 罰則付き回帰

最小二乗法は予測値と実際の値の誤差の二乗和を最小にする手法です.この最小にする対象として,誤差だけでなくモデルの複雑度を加味するようにしたのが罰則付き回帰です.モデルの複雑度の繁栄の刺せ方によって,Ridge回帰やLasso回帰といった手法が用いられます.以下の例ではRidge回帰を用います.
Ridge回帰モデルは,sklearn.linear_model.Ridge()に実装されており,使い方は LinearRegression() と同じです.

 
# import modules
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
 
# data of y = 4 * x**3 - 3 * x**2 + 2 * x - 1
x = np.random.rand(100, 1)          # Make 100 random numbers up to 0-1
x = x * 2 - 1                       # Change the value range to -2 - 2
 
y = 4 * x**3 - 3 * x**2 + 2 * x - 1
 
# Add a random number with standard normal distribution \
#                        (average 0, standard deviation 1)
y += np.random.randn(100, 1)
 
# Make learning data
x_train = x[:30]
y_train = y[:30]
 
# Make Test data
x_test = x[30:]
y_test = y[30:]
 
# Learning
X_Train = np.c_[x_train**9, x_train**8, x_train**7,
                x_train**6, x_train**5, x_train**4,
                x_train**3, x_train**2, x_train]
 
model = linear_model.Ridge()
model.fit(X_Train, y_train)
 
# Verification
X_TEST = np.c_[x_test**9, x_test**8, x_test**7,
                x_test**6, x_test**5, x_test**4,
                x_test**3, x_test**2, x_test]
 
# Graph
print(model.coef_)
print(model.intercept_)
print(model.score(X_Train, y_train))
 
plt.scatter(x_train, y_train, marker='+')
plt.scatter(x_train, model.predict(X_Train))
 
plt.show()
 

実行結果は以下のようになります.

[[ 0.4914022  -0.18617938  0.73513288 -0.23548331  1.06127729 -0.53097235
   1.49892161 -1.53395841  2.54767229]]
[-1.25234151]
0.8813692698077086

学習時のR^2決定係数は0.8813692698077086とLinearRegressionに比べて低くなっていますが,グラフにプロットされている予測値()は元データ(+)の分布の中央を通っているように見えます.
さらに,以下のようにテストデータを与えてみます.

 
# import modules
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
 
# data of y = 4 * x**3 - 3 * x**2 + 2 * x - 1
x = np.random.rand(100, 1)          # Make 100 random numbers up to 0-1
x = x * 2 - 1                       # Change the value range to -2 - 2
 
y = 4 * x**3 - 3 * x**2 + 2 * x - 1
 
# Add a random number with standard normal distribution \
#                        (average 0, standard deviation 1)
y += np.random.randn(100, 1)
 
# Make learning data
x_train = x[:30]
y_train = y[:30]
 
# Make Test data
x_test = x[30:]
y_test = y[30:]
 
# Learning
X_Train = np.c_[x_train**9, x_train**8, x_train**7,
                x_train**6, x_train**5, x_train**4,
                x_train**3, x_train**2, x_train]
 
model = linear_model.Ridge()
model.fit(X_Train, y_train)
 
# Verification
X_TEST = np.c_[x_test**9, x_test**8, x_test**7,
                x_test**6, x_test**5, x_test**4,
                x_test**3, x_test**2, x_test]
 
# Graph
print(model.coef_)
print(model.intercept_)
print(model.score(X_Train, y_train))
print(model.score(X_TEST, y_test))
 
plt.scatter(x_test, y_test, marker = '+')
plt.scatter(x_test, model.predict(X_TEST))
 
plt.show()
 

実行結果は以下のようになります.

[[ 0.38843023 -0.55130234  0.56768651 -0.72042453  0.87364256 -1.00025784
   1.46539778 -1.32060933  2.80755604]]
[-0.98218834]
0.8953738176703632
0.8428247561482345

テストデータでも,予測値()は元データ(+)の分布の中央を通っています. R^2決定係数も罰則を付けていない時に比べて改善されています.