nanoseeingの技術系ブログ

機械学習・競プロなど。アウトプットが目的。

ラッソ回帰(L1ノルム)による正則化【機械学習アウトプット第4回】

復習

重回帰分析において、損失関数は下記で表された。

 L=(\boldsymbol{y}-\boldsymbol{Xw})^{T}(\boldsymbol{y}-\boldsymbol{Xw})


この損失関数にパラメータ \boldsymbol{w}が小さくなるように罰則項を与えることが、「正則化」の一種であった。

また、 L_{p} ノルムとは、

 ‖\boldsymbol{x}‖_{p} = \sqrt[p]{\sum_{i=1}^{n} {|x_{i}|}^{p}}


で表され、

損失関数に、L2ノルム(いわゆるユークリッド距離) ‖\boldsymbol{w}‖_{2} を罰則項として与えた回帰問題をリッジ回帰といった。

ラッソ回帰とは

L1ノルムは、下記で表される。

 ‖\boldsymbol{w}‖_{1} = \sum_{i=1}^{n} {|w_{i}|}


ゆえに、このL1ノルムを罰則項として与えた損失関数は、

 L=(\boldsymbol{y}-\boldsymbol{Xw})^{T}(\boldsymbol{y}-\boldsymbol{Xw}) + \alpha\sum_{i=1}^{n} {|w_{i}|}


となり、この損失関数を最小化する回帰問題がラッソ回帰である。

以下、Lを最小化する問題を解くわけだが、罰則項に絶対値が含まれるため、解析的に偏微分することが難しい。 よって、「座標降下法」などのアルゴリズムを用いて最適なパラメータを求める必要がある。

…が、面倒なのでsklearnの実装だけやってみる。

自作データのプロット

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

np.random.seed(seed=32)
plot_num = 1000

x1 = np.random.rand(plot_num) * 10 - 5 
x2 = np.random.rand(plot_num) * 10 - 5 
y = 3 * x1 - 2 * x2 + 7
y += 5 * np.random.randn(plot_num)

x1 = x1.reshape(-1, 1)
x2 = x2.reshape(-1, 1)
y = y.reshape(-1, 1)
fig = plt.figure(figsize=(6, 6))
ax = Axes3D(fig)
ax.plot(x1.ravel(), x2.ravel(), y.ravel(), marker=".", linestyle='None')
plt.show()

f:id:nanoseeing:20210205172006p:plain

sklearnで予測

import sklearn.linear_model as lm

X = np.concatenate([x1, x2], axis=1)

lasso = lm.Lasso(alpha=1.0)
lasso.fit(X, y)
print(lasso.intercept_)
print(lasso.coef_)
>>
[6.88137878]
[ 2.90263201 -1.97552597]

予測値を可視化

x1_p = np.linspace(-5,5,10).reshape(-1,1)
x2_p = np.linspace(-5,5,10).reshape(-1,1)
y_pred = lasso.predict(np.concatenate([x1_p, x2_p], axis=1)).ravel()
xx1, xx2 = np.meshgrid(x1_p.ravel(), x2_p.ravel())
zz, _ = np.meshgrid(y_pred, y_pred)

fig = plt.figure(figsize=(6, 6))
ax = Axes3D(fig)
ax.plot(x1.ravel(), x2.ravel(), y.ravel(), marker=".", linestyle='None')
ax.plot_surface(xx1, xx2, zz, alpha = 0.3)
plt.show()

f:id:nanoseeing:20210205171955p:plain

以上。3次元平面を書くのが難しかった。

参考サイト