scikit-learn

【scikit-learn】線形回帰の正則化手法 ~ラッソ(Lasso)回帰、リッジ(Ridge)回帰、ElasticNet回帰~

【scikit-learn】線形回帰の正則化手法 _ラッソ(Lasso)回帰、リッジ(Ridge)回帰、ElasticNet回帰_

Pythonの機械学習ライブラリであるscikit-learnには線形回帰に正則化を適用した各種手法が実装されています。正則化が適用されている手法としてラッソ(Lasso)回帰リッジ(Ridge)回帰ElasticNet回帰について使用方法を解説します。

線形回帰と正則化

回帰分析とは、予測したいデータに対して、既に与えられているデータから関係性を予測することを言います。この時に$x^{2}$、$x^{3}$のような累乗の形がない線形の式で予測する方法のことを線形回帰と言います。

scikit-learnのLinearRegressionを使用した線形回帰の方法については、「LinearRegressionで線形回帰をする方法」でまとめていますので興味があれば参考にしてください。

機械学習の分野では、学習データに対して過度にモデルが適合してしまうことを過学習と言います。未知のデータに対する予測の誤差を汎化誤差と言いますが、過学習が起こると汎化誤差が大きくなってしまいます。そして、汎化誤差が大きくならないようにモデルに手を加えることを正則化と言います。

線形回帰にも正則化が適用されている手法があり、L1正則化を適用したものをラッソ(Lasso)回帰、L2正則化を適用したものをリッジ(Ridge)回帰、L1正則化とL2正則化を組み合わせたものをElasticNet回帰と言います。なお、L1正則化やL2正則化については、「L1正則化とL2正則化の概要と効果」で式の意味や効果についてまとめていますので興味があれば参考にしてください。

ラッソ(Lasso)回帰、リッジ(Ridge)回帰、ElasticNet回帰については、Pythonの機械学習ライブラリであるscikit-learnで既に実装がされており、簡単に利用ができます。本記事では、scikit-learnを用いてラッソ(Lasso)回帰、リッジ(Ridge)回帰、ElasticNet回帰を実行する基本的な使い方について紹介します。

scikit-learnでの各種手法の使い方 ~ラッソ(Lasso)回帰、リッジ(Ridge)回帰、ElasticNet回帰~

以降では、scikit-learnを用いてラッソ(Lasso)回帰、リッジ(Ridge)回帰、ElasticNet回帰を実行する基本的な使い方について解説していきます。

ラッソ(Lasso)回帰

実装例

ラッソ(Lasso)回帰とは、L1正則化を用いて線形回帰を正則化する回帰モデルです。scikit-learnでは、sklearn.linear_model.Lassoで実装がされています。以下に実装例を紹介します。

import numpy as np
from sklearn.datasets import make_regression
from sklearn.linear_model import Lasso
from sklearn.model_selection import train_test_split


def main():
    """メイン関数"""
    np.random.seed(123)
    np.set_printoptions(precision=3, suppress=True)

    # ===== 線形回帰を行うためのデータを生成する
    bias = 5.0
    noise = 50.0
    x, y, coef = make_regression(
        n_samples=100,
        n_features=10,
        n_informative=5,
        n_targets=1,
        coef=True,
        bias=bias,
        noise=noise,
    )
    print(f"true coef: {coef}")
    print(f"true bias: {bias:.3f}")

    # 学習用データとテスト用データを分割する
    train_x, test_x, train_y, test_y = train_test_split(x, y)

    # ===== Lasso回帰モデルを生成する
    model = Lasso(alpha=1.0)

    # ===== モデルを学習する
    model.fit(train_x, train_y)

    # 推定結果の表示
    print(f"coef: {model.coef_}")
    print(f"bias: {model.intercept_:.3f}")
    print(f"R2: {model.score(test_x, test_y):.3f}")


if __name__ == "__main__":
    main()
【実行結果】
true coef: [ 0.    79.45   0.    18.045  0.    22.194 74.221  0.     0.    69.981]
true bias: 5.000
coef: [-1.322 78.107  5.754 25.559 -4.134 30.474 76.132  3.364  0.    69.677]
bias: 6.504
R2: 0.844

実装内容の解説

上記で紹介した実装例の各部分ごとに内容を説明していきます。

必要モジュールのインポート

from sklearn.linear_model import Lasso

Lasso回帰を使用するには、sklearn.linear_modelからLassoをインポートします。

データセットの用意

    # ===== 線形回帰を行うためのデータを生成する
    bias = 5.0
    noise = 50.0
    x, y, coef = make_regression(
        n_samples=100,
        n_features=10,
        n_informative=5,
        n_targets=1,
        coef=True,
        bias=bias,
        noise=noise,
    )
    print(f"true coef: {coef}")
    print(f"true bias: {bias:.3f}")

    # 学習用データとテスト用データを分割する
    train_x, test_x, train_y, test_y = train_test_split(x, y)

今回は、sklearn.datasets.make_regressionを使って線形回帰用のデータを用意します。各引数は以下の通りです。

  • n_samples: データ数
  • n_features: 特徴数
  • n_informative: 特徴のうち説明に寄与する変数の数
  • n_targets: 目的値
  • coef: データを生成した線形モデルの係数を返却するか否か(True: 返却)
  • bias: バイアス値
  • noise: データに加えるガウスノイズの標準偏差
  • random_state:乱数のシード

乱数のシードはnp.random.seedで設定していますが、make_regressionのrandom_state引数で指定することも可能です。

また、train_test_splitで学習用データとテスト用データを分割しています。

Lasso回帰モデルの生成と学習

    # ===== Lasso回帰モデルを生成する
    model = Lasso(alpha=1.0)

    # ===== モデルを学習する
    model.fit(train_x, train_y)

    # 推定結果の表示
    print(f"coef: {model.coef_}")
    print(f"bias: {model.intercept_:.3f}")
    print(f"R2: {model.score(test_x, test_y):.3f}")

上記の部分でLasso回帰モデルを生成して学習しています。alphaが正規化項の強さを決めるハイパーパラメータです。省略するとdefaultで1.0が指定されます。このパラメータを色々変えつつ実行してみてください。

学習はfitメソッドで実行し、テストデータでの評価(決定係数$R^{2}$)は、scoreメソッドで計算しています。通常の線形回帰のLinearRegression()がLasso()に変わっただけなので簡単ですね。

Note

sklearn.linear_model.Lassoの公式ドキュメントはこちらを参照してください。

リッジ回帰(Ridge)回帰

実装例

リッジ(Ridge)回帰とは、L2正則化を用いて線形回帰を正則化する回帰モデルです。scikit-learnでは、sklearn.linear_model.Ridgeで実装がされています。以下に実装例を紹介します。

import numpy as np
from sklearn.datasets import make_regression
from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split


def main():
    """メイン関数"""
    np.random.seed(123)
    np.set_printoptions(precision=3, suppress=True)

    # ===== 線形回帰を行うためのデータを生成する
    bias = 5.0
    noise = 50.0
    x, y, coef = make_regression(
        n_samples=100,
        n_features=10,
        n_informative=5,
        n_targets=1,
        coef=True,
        bias=bias,
        noise=noise,
    )
    print(f"true coef: {coef}")
    print(f"true bias: {bias:.3f}")

    # 学習用データとテスト用データを分割する
    train_x, test_x, train_y, test_y = train_test_split(x, y)

    # ===== Ridge回帰モデルを生成する
    model = Ridge(alpha=1.0)

    # ===== モデルを学習する
    model.fit(train_x, train_y)

    # 推定結果の表示
    print(f"coef: {model.coef_}")
    print(f"bias: {model.intercept_:.3f}")
    print(f"R2: {model.score(test_x, test_y):.3f}")


if __name__ == "__main__":
    main()
【実行結果】
true coef: [ 0.    79.45   0.    18.045  0.    22.194 74.221  0.     0.    69.981]
true bias: 5.000
coef: [-2.864 78.568  7.093 25.949 -5.22  31.006 76.181  4.424  1.229 70.14 ]
bias: 7.117
R2: 0.845

実装内容の解説

上記で紹介した実装例の各部分ごとに内容を説明していきます。Lasso回帰で説明している部分については省略します。

必要モジュールのインポート

from sklearn.linear_model import Ridge

Ridge回帰を使用するには、sklearn.linear_modelからRidgeをインポートします。

Ridge回帰モデルの生成と学習

    # ===== Ridge回帰モデルを生成する
    model = Ridge(alpha=1.0)

上記の部分でRidge回帰モデルを生成しています。alphaが正規化項の強さを決めるハイパーパラメータです。省略するとdefaultで1.0が指定されます。このパラメータを色々変えつつ実行してみてください。

学習(fit)等の実行方法については、Lasso回帰のコードと全く同じです。

Note

sklearn.linear_model.Ridgeの公式ドキュメントはこちらを参照してください。

ElasticNet回帰

実装例

ElasticNet回帰とは、L1正則化とL2正則化を組み合わせて正則化項を作るモデルです。scikit-learnでは、sklearn.linear_model.ElasticNetで実装がされています。以下に実装例を紹介します。

import numpy as np
from sklearn.datasets import make_regression
from sklearn.linear_model import ElasticNet
from sklearn.model_selection import train_test_split


def main():
    """メイン関数"""
    np.random.seed(123)
    np.set_printoptions(precision=3, suppress=True)

    # ===== 線形回帰を行うためのデータを生成する
    bias = 5.0
    noise = 50.0
    x, y, coef = make_regression(
        n_samples=100,
        n_features=10,
        n_informative=5,
        n_targets=1,
        coef=True,
        bias=bias,
        noise=noise,
    )
    print(f"true coef: {coef}")
    print(f"true bias: {bias:.3f}")

    # 学習用データとテスト用データを分割する
    train_x, test_x, train_y, test_y = train_test_split(x, y)

    # ===== ElasticNet回帰モデルを生成する
    model = ElasticNet(alpha=1.0, l1_ratio=0.7)

    # ===== モデルを学習する
    model.fit(train_x, train_y)

    # 推定結果の表示
    print(f"coef: {model.coef_}")
    print(f"bias: {model.intercept_:.3f}")
    print(f"R2: {model.score(test_x, test_y):.3f}")


if __name__ == "__main__":
    main()
【実行結果】
true coef: [ 0.    79.45   0.    18.045  0.    22.194 74.221  0.     0.    69.981]
true bias: 5.000
coef: [ 2.5   60.05   2.82  18.707 -7.325 22.637 62.551 -0.551 -0.667 53.213]
bias: -2.243
R2: 0.800

実装内容の解説

上記で紹介した実装例の各部分ごとに内容を説明していきます。Lasso回帰で説明している部分については省略します。

必要モジュールのインポート

from sklearn.linear_model import ElasticNet

ElasticNet回帰を使用するには、sklearn.linear_modelからElasticNetをインポートします。

ElasticNet回帰モデルの生成と学習

    # ===== ElasticNet回帰モデルを生成する
    model = ElasticNet(alpha=1.0, l1_ratio=0.7)

上記の部分でElasticNet回帰モデルを生成しています。alphaが正規化項の強さを決めるハイパーパラメータです。省略するとdefaultで1.0が指定されます。

ElasticNetでは、l1_ratioを設定することでL1正則化とL2正則化項の効果の割合を指定することができます。例えば、l1_ratio=0.7のように設定するとL1正則化の割合が70%、L2正則化が30%の強さで効果があるように設定ができます。なお、l1_ratioを指定しない場合は、l1_ratio=0.5になり、つまりはL1正則化が50%、L2正則化が50%という効果になります。

学習(fit)等の実行方法については、Lasso回帰やRidge回帰のコードと全く同じです。

Note

sklearn.linear_model.ElasticNetの公式ドキュメントはこちらを参照してください。

まとめ

Pythonの機械学習ライブラリであるscikit-learnには線形回帰に正則化を適用した各種手法が実装されています。正則化が適用されている手法としてラッソ(Lasso)回帰リッジ(Ridge)回帰ElasticNet回帰について使用方法を解説しました。

Lasso回帰がL1正則化、Ridge回帰がL2正則化、ElasticNetはL1とL2を組み合わせたものになります。

L1正則化は、重要なパラメータを残して不要なパラメータを0にする(スパースにする)効果があり、L2正則化はパラメータを全体的に小さくする効果があります。目的に応じてLasso回帰、Ridge回帰、ElasticNet回帰を使いつつ比べてみるといいでしょう。なお、L1正則化やL2正則化の式や効果ついては、「L1正則化とL2正則化の概要と効果」で式の意味や効果についてまとめていますので興味があれば参考にしてください。