2
4

More than 3 years have passed since last update.

深層学習/正則化の効果を見える化する

Last updated at Posted at 2019-12-26

1.はじめに

 深層学習の勉強を始めました。今回は、正則化について、簡単にまとめてみます。

2.データの作成

 方程式 $y=-x^3+x^2+x$ を元に、x は -10〜10を50分割した値、y は方程式にそのxを代入した結果に 0〜0.05の乱数を加えた値としてデータを作成します。

from sklearn.preprocessing import PolynomialFeatures
from sklearn import linear_model
import numpy as np
import matplotlib.pyplot as plt

# データの生成
np.random.seed(0)
X = np.linspace(-10, 10, 50)
Y_truth = 0.001 * (-X **3 + X**2 + X)
Y = Y_truth + np.random.normal(0, 0.05, len(X))

plt.figure(figsize=(5, 5))
plt.plot(X, Y_truth, color='gray')
plt.plot(X, Y, '.', color='k')
plt.show()

スクリーンショット 2019-12-26 15.31.05.png
作成したデータです。実線が真の値(方程式の値)、点が実際に観測する値(yにノイズを加えた値)という想定です。

3.多項式回帰の導入

 過学習は自由度が高いほど起こりやすいので、あえて30次元の多項式回帰を導入します。

# グラフ表示
def graph(Y_lr, name):
    plt.figure(figsize=(6, 6))
    plt.plot(X, Y_truth, color='gray', label='truth')
    plt.plot(xs, Y_lr, color='r', markersize=2, label=name)
    plt.plot(X, Y, '.', color='k')
    plt.legend()
    plt.ylim(-1, 1)
    plt.show()

# 表示設定
xs = np.linspace(-10, 10, 200)  

# 多項式回帰の導入    
poly = PolynomialFeatures(degree=30, include_bias=False)  
X_poly = poly.fit_transform(X[:, np.newaxis])   

 グラフ表示や表示の設定をした後、PolynomialFeaturesをインスタンス化し、フィットしています。次元は30次元(degree=30)です。

4.正則化なし

 まず、正則化なしで多項式回帰を行います。

# 正則化なし           
lr0 = linear_model.LinearRegression(normalize=True)
lr0.fit(X_poly, Y)
Y_lr0 = lr0.predict(poly.fit_transform(xs[:, np.newaxis]))
graph(Y_lr0, 'No Regularization')

スクリーンショット 2019-12-26 15.32.47.png

 30次元の多項式と自由度が高いので、数多くの点を器用に通過することが出来てしまい、典型的な過学習に陥っています。真の値とは掛け離れてしまって、これでは汎化性能は望めません。

5.L2正則化

 L2正則化とは、Ridge(リッジ)回帰で知られた手法で、係数が大きくなり過ぎない様に制限を加えるもので、パラメータのL2ノルムを損失に加えます(Cは定数)。
$L(W)+c|w|^2$

# L2正則化
lr2 = linear_model.Ridge(normalize=True, alpha=0.5)
lr2.fit(X_poly, Y)
Y_lr2 = lr2.predict(poly.fit_transform(xs[:, np.newaxis]))
graph(Y_lr2, 'L2')

スクリーンショット 2019-12-26 15.33.51.png
まあまあ、上手く回帰出来ている感じです。

6.L1正則化

 L1正則化とは、Lasso(ラッソ)回帰で知られた手法で、同様に係数が大きくなり過ぎない様に制限を加えるもので、パラメータのL1ノルムを損失に加えます(Cは定数)。
$L(W)+c|w|$

# L1正則化
lr1 = linear_model.LassoLars(normalize=True, alpha=0.001)
lr1.fit(X_poly, Y)
Y_lr1 = lr1.predict(poly.fit_transform(xs[:, np.newaxis]))
graph(Y_lr1, 'L1')

スクリーンショット 2019-12-26 15.34.43.png
ジャストフィットにかなり近い形です。L1正則化と比較すると、L2正則化の方がより上手く回帰出来ている様です。

7.次元係数の比較

 正則化なし、L2正則化、L1正則化それぞれ30個の次元係数を比較します(次元が低い方から並べています)。

import pandas as pd
result = []
for i in range(len(lr0.coef_)):
      tmp = lr0.coef_[i], lr2.coef_[i], lr1.coef_[i]
      result.append(tmp)
df = pd.DataFrame(result)
df.columns = ['No Regularization', 'L2', 'L1']
print(df)

スクリーンショット 2019-12-26 15.43.05.png
 L2はNo Regularizationと比べて係数が小さくなっているのが分かると思います。L1はさらに、完全に0のところが多い表現(スパースな表現)になっています。

 L1正則化は、過学習抑制+次元削減も出来るのは、嬉しいですね。

2
4
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
2
4