リッジ回帰
線形回帰で最小化する目的関数に、パラメータの大きさの項(正則化項)を足したものを最小化する回帰がリッジ回帰である。
- 目的関数 : E(w)=∥y−X~w∥2+λ∥w∥2
であり、∇E=0 より
- ∇E=2X~TX~w−2X~Ty+2λw=2[(X~TX~+λI)w−X~Ty]=0
- よって w=(X~TX~+λI)−1X~Ty
が得られる。
リッジ回帰を実装する
import numpy as np
from scipy import linalg
class RidgeRegression:
def __init__(self, lambda_=1.):
self.lambda_ = lambda_
self.w_ = None
def fit(self, X, t):
Xtil = np.c_[np.ones(X.shape[0]), X]
c = np.eye(Xtil.shape[1])
A = np.dot(Xtil.T, Xtil) + self.lambda_ * c
b = np.dot(Xtil.T, t)
self.w_ = linalg.solve(A, b)
def predict(self, X):
if X.ndim == 1:
X = X.reshape(1, -1)
Xtil = np.c_[np.ones(X.shape[0]), X]
return np.dot(Xtil, self.w_)
線形回帰との比較
import numpy as np
from scipy import linalg
class LinearRegression:
def __init__(self):
self.w_ = None
def fit(self, X, t):
Xtil = np.c_[np.ones(X.shape[0]), X]
A = np.dot(Xtil.T, Xtil)
b = np.dot(Xtil.T, t)
self.w_ = linalg.solve(A, b)
def predict(self, X):
if X.ndim == 1:
X = X.reshape(1, -1)
Xtil = np.c_[np.ones(X.shape[0]), X]
return np.dot(Xtil, self.w_)
使用例
1変数の例
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (10, 8)
x = np.array([1, 2, 4, 6, 7])
y = np.array([1, 3, 3, 5, 4])
model = RidgeRegression(1.)
model.fit(x, y)
b, a = model.w_
plt.scatter(x, y, color="k")
xmax = x.max()
plt.plot([0, xmax], [b, b+a*xmax], color="k")
plt.show()
2変数(平面へのあてはめ)の例
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
plt.rcParams["figure.figsize"] = (10, 8)
n = 100
scale = 10
np.random.seed(0)
X = np.random.random((n, 2)) * scale
w0 = 1
w1 = 2
w2 = 3
y = w0 + w1 * X[:, 0] + w2 * X[:, 1] + np.random.randn(n)
model = RidgeRegression(1.)
model.fit(X, y)
xmesh, ymesh = np.meshgrid(np.linspace(0, scale, 20), np.linspace(0, scale, 20))
zmesh = (model.w_[0] + model.w_[1] * xmesh.ravel() + model.w_[2] * ymesh.ravel()).reshape(xmesh.shape)
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.scatter(X[:, 0], X[:, 1], y, color="k")
ax.plot_wireframe(xmesh, ymesh, zmesh, color="r")
plt.show()
線形回帰との比較
サンプル数を変えながら、線形回帰とリッジ回帰のあてはめを並べて比較する。
import numpy as np
import matplotlib.pyplot as plt
# 普通の線形回帰との比較
x = np.arange(12)
y = 1 + 2 * x
y[2] = 20
y[4] = 0
xmin = 0
xmax = 12
ymin = -1
ymax = 25
fig, axes = plt.subplots(nrows=2, ncols=5)
for i in range(5):
axes[0, i].set_xlim([xmin, xmax])
axes[0, i].set_ylim([ymin, ymax])
axes[1, i].set_xlim([xmin, xmax])
axes[1, i].set_ylim([ymin, ymax])
xx = x[:2 + i * 2]
yy = y[:2 + i * 2]
axes[0, i].scatter(xx, yy, color="k")
axes[1, i].scatter(xx, yy, color="k")
model = LinearRegression()
model.fit(xx, yy)
xs = [xmin, xmax]
ys = [model.w_[0] + model.w_[1] * xmin, model.w_[0] + model.w_[1] * xmax]
axes[0, i].plot(xs, ys, color="k")
model = RidgeRegression(10.)
model.fit(xx, yy)
xs = [xmin, xmax]
ys = [model.w_[0] + model.w_[1] * xmin, model.w_[0] + model.w_[1] * xmax]
axes[1, i].plot(xs, ys, color="k")
plt.show()
上が線形回帰、下がリッジ回帰。リッジ回帰はサンプル数が少ないときに、例外的なデータ(外れ値)からの影響を受けにくいという性質がある。