LoginSignup
1
1

More than 1 year has passed since last update.

リッジとラッソをざっくりまとめてみた

Last updated at Posted at 2021-07-22

はじめに

現在私は、学部4年生で卒業研究の真っ最中です。
そんな中、リッジとラッソについて、上手くゼミで説明できませんでした。(反省………汗汗)
もう自分なりに再構成してまとめてやろうと思い、今回記事を書く決意をしました。

完全に自分用なのでご容赦ください。

リッジとラッソの目的

まずは「どのような目的でリッジやラッソを行うのか」というところです。
ここをはっきりさせます。

キーワードとしては「正則化」です。
正則化とは、過学習(過剰適合)を防ぐことです。
つまり、リッジとラッソを行うことで、過学習(過剰適合)を防ぐことができます。

では、「過学習」とは何でしょうか。
過学習(過剰適合)とは言い換えると「過度に複雑なモデル」の状態のことです。
例えば、以下の関数同士を比べると複雑さは以下の通りです。

  • 1次関数(直線)←単純
  • 2次関数(放物線)←複雑

そして言い換えると、過学習(過剰適合)を防ぐことは「モデルの表現を制約」することと同義になります。

まとめると、リッジやラッソを行うことで「モデルの表現を制約」できます。

次に、よく見られる具体例として、線形モデルでのリッジ回帰とラッソ回帰を見ていきます。

リッジ回帰とラッソ回帰

①線形モデル

教師あり学習ですので、入力ベクトル$\boldsymbol{x} \in \mathbb{R}^d$と正解値$y \in \mathbb{R}$のペアのデータが観測された場合を考えます。
今回は例ですので、5次元$(d=5)$のベクトル$\boldsymbol{x}=(x_1, x_2, x_3, x_4, x_5)$としましょう。
つまり、今回の観測されたデータセット集合$S$は以下になります。
$$
S=\{(x_1, y_1), (x_2, y_2), (x_3, y_3), (x_4, y_4), (x_5, y_5)\}
$$
このとき、予測値$\hat{y}$を以下のように表現するのが線形モデルです。
$$
\hat{y} = a\boldsymbol{x}+b
$$
※回帰係数:①傾き$a$②切片$b$
回帰係数を定めることで予測値が決まります。
つまり、回帰係数を求めていくわけですが、多くの場合で「パラメータ」と表現しています。
したがって、回帰係数をパラメータ$θ$を用いた表現に変えます。
$$
\hat{y} = θ_1\boldsymbol{x}+θ_0
$$
パラメータを求めることが目的です。

②線形回帰(最小二乗法)

パラメータを求めていくわけですが、判断基準として正解値$y$と予測値$\hat{y}$の誤差を最小にするパラメータを求めるのが最小二乗法です。

具体的な数値での最小二乗法

線形モデルでの設定を具体的な数値にします。
データセット集合$S$を以下のように定めます。
$$
S=\{(1, 2), (2, 2), (3, 4), (4, 4), (5, 5)\}
$$
$xy$平面にプロットとしてみてください。
誤差が最小になる直線はどのような直線でしょうか。

sample1.py
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
#OLSモジュール
import statsmodels.api as sm
S = np.array([[1,2],[2,2],[3,4],[4,4],[5,5]])#値を変更させてみましょう
print("データセット集合S: {}".format(S.shape))
X = S[:,0]#変数Xに格納
print("入力データ: {}".format(X))
y = S[:,1]#変数yに格納
print("出力データ(正解値): {}".format(y))
XC = sm.add_constant(X)#切片
#正解値のプロット
plt.scatter(S[:,0], S[:,1])#データセット集合
plt.xlabel("input")
plt.ylabel("output")

#線形回帰(最小二乗法)
lr = sm.OLS(y, XC).fit()#フィッティング
print("パラメータ(切片, 傾き): {}".format(lr.params))#パラメータ推定

n=100
tx = np.linspace(X.min(), X.max(), n)#xの予測点生成
txc = sm.add_constant(tx)#切片
y_lr_pred = lr.predict(txc)#予測
plt.plot(tx, y_lr_pred, "r--")#プロット
plt.show()

qiita_sample1.png

上記のプログラム(Python)を実行した場合、パラメータは以下のように求められます。

  • $θ_0$(切片):1.0  $θ_1$(傾き):0.8

$$
\hat{y}=0.8x_i+1.0 (i=1,2,3,4,5)
$$

例えば$x_1=1$を入力した場合、正解値$y_1=2$に対して予測値$\hat{y}=1.8$となります。
この誤差はどのくらい許容できるでしょうか。
これはモデルの評価です。
今回は詳細を省きますが、非常に重要です。

1次式の場合で、リッジ回帰とラッソ回帰を見ていきます。

リッジ回帰(本題)

さあいよいよ本題です。
1次式(単純)では、パラメータが求まるとモデルが定まります。
これは、2次式(複雑)でも同様です。

つまり、パラメータに制約を加えることで、モデルを制約できるわけです。
具体的な制約の仕方は、正則化項を追加します。

正則化項を追加するとモデルが単純になるためです。
単純になる理由を述べます。
2次式(複雑)
$$
θ_2x_i^2+θ_1x_i+θ_0
$$

1次式(単純)
$$
θ_1x_i+θ_0
$$

⚠モデルを単純にするということは、制約をつけてパラメータを0に近づけているということです。
例えば、極端な話ですが、2次式(複雑)で$θ_2=0$となった場合、モデルは1次式(単純)になります。
正則化項を加えることで、「大きなパラメータの値が取りにくくなる」ということです。
また、通常は切片$θ_0$を正則化項に含めません。

1次式の場合を考えます。
※多項式の場合は$Σ$を用いて表現します。

正則化項(リッジ)
$$
α θ_{1}^2
$$

  • リッジは傾きの絶対値を縮小します。

ここで、$α$は正則化パラメータであり、$α$を大きくすると、モデルの表現力を抑えることができます。

sample2.py
#リッジ0.01
alpha=0.01; rp=np.r_[0, np.repeat(alpha/n, 1)]
ri001 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=0)
print("正則化パラメータ0.01 パラメータ(切片, 傾き): {}".format(ri001.params))#パラメータ推定
y_ri001_pred = ri001.predict(txc)#予測
plt.plot(tx, y_ri001_pred, "g--")#プロット
#リッジ10
alpha=10; rp=np.r_[0, np.repeat(alpha/n, 1)]
ri10 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=0)
print("正則化パラメータ10 パラメータ(切片, 傾き): {}".format(ri10.params))#パラメータ推定
y_ri10_pred = ri10.predict(txc)#予測
plt.plot(tx, y_ri10_pred, "b--")#プロット
#リッジ100
alpha=100; rp=np.r_[0, np.repeat(alpha/n, 1)]
ri100 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=0)
print("正則化パラメータ100 パラメータ(切片, 傾き): {}".format(ri100.params))#パラメータ推定
y_ri100_pred = ri100.predict(txc)#予測
plt.plot(tx, y_ri100_pred, "b--")#プロット
#リッジ10000
alpha=10000; rp=np.r_[0, np.repeat(alpha/n, 1)]
ri10000 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=0)
print("正則化パラメータ10000 パラメータ(切片, 傾き): {}".format(ri10000.params))#パラメータ推定
y_ri10000_pred = ri10000.predict(txc)#予測
plt.plot(tx, y_ri10000_pred, "y--")#プロット
plt.show()

qiita_sample2.png

$α$が大きくなるほど、傾きが0に近づいていることがわかります。
傾きの絶対値を縮小しています。

ラッソ回帰(本題)

1次式の場合を考えます。
※多項式の場合は$Σ$を用いて表現します。

正則化項(ラッソ)
$$
α |θ_{1}|
$$

  • ラッソは傾きを完全に0にします。
sample3.py
#ラッソ0.01
alpha=0.01; rp=np.r_[0, np.repeat(alpha/n, 1)]
la001 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=1)
print("正則化パラメータ0.01 パラメータ(切片, 傾き): {}".format(la001.params))#パラメータ推定
y_la001_pred = la001.predict(txc)#予測
plt.plot(tx, y_la001_pred, "g--")#プロット
#ラッソ10
alpha=10; rp=np.r_[0, np.repeat(alpha/n, 1)]
la10 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=1)
print("正則化パラメータ10 パラメータ(切片, 傾き): {}".format(la10.params))#パラメータ推定
y_la10_pred = la10.predict(txc)#予測
plt.plot(tx, y_la10_pred, "b--")#プロット
#ラッソ100
alpha=100; rp=np.r_[0, np.repeat(alpha/n, 1)]
la100 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=1)
print("正則化パラメータ100 パラメータ(切片, 傾き): {}".format(la100.params))#パラメータ推定
y_la100_pred = la100.predict(txc)#予測
plt.plot(tx, y_la100_pred, "b--")#プロット
#ラッソ10000
alpha=10000; rp=np.r_[0, np.repeat(alpha/n, 1)]
la10000 = sm.OLS(y, XC).fit_regularized(alpha=rp, L1_wt=1)
print("正則化パラメータ10000 パラメータ(切片, 傾き): {}".format(la10000.params))#パラメータ推定
y_la10000_pred = la10000.predict(txc)#予測
plt.plot(tx, y_la10000_pred, "y--")#プロット
plt.show()

qiita_sample3.png

$α=10000$の場合、傾きが完全に0になっていることがわかります。
傾きを完全に0にしています。

おわりに

今回は、リッジとラッソについてまとめてみました。
理解のために、やや強引な表現もあったと思いますが、他の文献と読み比べて修正していただけると幸いです。
また、内容の間違いや誤字等ありましたら、Twitter(@gobugobu__rin)のDMまで、教えていただけると幸いです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1