L1 ベースのモデルを用いた疎信号回帰

Machine LearningMachine LearningBeginner
今すぐ練習

This tutorial is from open-source community. Access the source code

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、L1 ベースの回帰モデルを使用して高次元で疎な信号を処理する方法を示します。特に、3 つの一般的な L1 ベースのモデル:Lasso、Automatic Relevance Determination (ARD)、および ElasticNet を比較します。これらのモデルの適合時間、R2 スコア、および推定係数の疎性の観点からの性能を示すために、合成データセットを使用します。

VM のヒント

VM の起動が完了したら、左上隅をクリックして ノートブック タブに切り替え、Jupyter Notebook を使用して練習します。

時々、Jupyter Notebook が読み込み完了するまで数秒待つ必要があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。

学習中に問題に直面した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/linear_model("Linear Models") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/metrics("Metrics") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/linear_model -.-> lab-49187{{"L1 ベースのモデルを用いた疎信号回帰"}} sklearn/model_selection -.-> lab-49187{{"L1 ベースのモデルを用いた疎信号回帰"}} sklearn/metrics -.-> lab-49187{{"L1 ベースのモデルを用いた疎信号回帰"}} ml/sklearn -.-> lab-49187{{"L1 ベースのモデルを用いた疎信号回帰"}} end

合成データセットの生成

まず、サンプル数が特徴量の総数より少ないデータセットを生成します。これにより、解が一意でない、つまり未定義系が生じ、通常の最小二乗法を単独で適用することができません。正則化は目的関数にペナルティ項を導入し、最適化問題を修正し、系の未定義な性質を軽減するのに役立ちます。正弦波信号の符号が交互になる線形結合であるターゲット y を生成します。X の 100 個の周波数のうち、最も低い 10 個の周波数のみを使用して y を生成し、その他の特徴量は情報を提供しません。これにより、ある程度の L1 ペナルティが必要な高次元疎な特徴空間が生成されます。

import numpy as np

rng = np.random.RandomState(0)
n_samples, n_features, n_informative = 50, 100, 10
time_step = np.linspace(-2, 2, n_samples)
freqs = 2 * np.pi * np.sort(rng.rand(n_features)) / 0.01
X = np.zeros((n_samples, n_features))

for i in range(n_features):
    X[:, i] = np.sin(freqs[i] * time_step)

idx = np.arange(n_features)
true_coef = (-1) ** idx * np.exp(-idx / 10)
true_coef[n_informative:] = 0  ## sparsify coef
y = np.dot(X, true_coef)

## introduce random phase using numpy.random.random_sample
## add some gaussian noise using numpy.random.normal
for i in range(n_features):
    X[:, i] = np.sin(freqs[i] * time_step + 2 * (rng.random_sample() - 0.5))
    X[:, i] += 0.2 * rng.normal(0, 1, n_samples)

y += 0.2 * rng.normal(0, 1, n_samples)

## split the data into train and test sets using train_test_split from sklearn
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, shuffle=False)

Lasso

このステップでは、Lasso 回帰モデルを使用してデータセットの疎な係数を推定する方法を示します。正則化パラメータ alpha の固定値を使用します。実際には、最適なパラメータ alpha は、LassoCVTimeSeriesSplit 交差検証戦略を渡すことで選択する必要があります。この例を簡単で高速に実行するために、ここでは直接 alpha の最適値を設定します。

from sklearn.linear_model import Lasso
from sklearn.metrics import r2_score
from time import time

t0 = time()
lasso = Lasso(alpha=0.14).fit(X_train, y_train)
print(f"Lasso fit done in {(time() - t0):.3f}s")

y_pred_lasso = lasso.predict(X_test)
r2_score_lasso = r2_score(y_test, y_pred_lasso)
print(f"Lasso r^2 on test data : {r2_score_lasso:.3f}")

Automatic Relevance Determination (ARD)

ARD 回帰は、Lasso のベイジアン版です。必要に応じて、誤差分散を含むすべてのパラメータに対する区間推定を生成することができます。信号にガウスノイズが含まれている場合に適したオプションです。

from sklearn.linear_model import ARDRegression

t0 = time()
ard = ARDRegression().fit(X_train, y_train)
print(f"ARD fit done in {(time() - t0):.3f}s")

y_pred_ard = ard.predict(X_test)
r2_score_ard = r2_score(y_test, y_pred_ard)
print(f"ARD r^2 on test data : {r2_score_ard:.3f}")

ElasticNet

ElasticNet は、Lasso 回帰と Ridge 回帰の中間的な手法であり、L1 と L2 のペナルティを組み合わせています。正則化の量は、2 つのハイパーパラメータ l1_ratioalpha によって制御されます。l1_ratio = 0 の場合、ペナルティは純粋な L2 となり、モデルは Ridge 回帰と同等になります。同様に、l1_ratio = 1 は純粋な L1 ペナルティであり、モデルは Lasso 回帰と同等になります。0 < l1_ratio < 1 の場合、ペナルティは L1 と L2 の組み合わせになります。

from sklearn.linear_model import ElasticNet

t0 = time()
enet = ElasticNet(alpha=0.08, l1_ratio=0.5).fit(X_train, y_train)
print(f"ElasticNet fit done in {(time() - t0):.3f}s")

y_pred_enet = enet.predict(X_test)
r2_score_enet = r2_score(y_test, y_pred_enet)
print(f"ElasticNet r^2 on test data : {r2_score_enet:.3f}")

結果のプロットと分析

このステップでは、ヒートマップを使用して、それぞれの線形モデルの真の係数と推定係数の疎性を視覚化します。

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from matplotlib.colors import SymLogNorm

df = pd.DataFrame(
    {
        "True coefficients": true_coef,
        "Lasso": lasso.coef_,
        "ARDRegression": ard.coef_,
        "ElasticNet": enet.coef_,
    }
)

plt.figure(figsize=(10, 6))
ax = sns.heatmap(
    df.T,
    norm=SymLogNorm(linthresh=10e-4, vmin=-1, vmax=1),
    cbar_kws={"label": "coefficients' values"},
    cmap="seismic_r",
)
plt.ylabel("linear model")
plt.xlabel("coefficients")
plt.title(
    f"Models' coefficients\nLasso $R^2$: {r2_score_lasso:.3f}, "
    f"ARD $R^2$: {r2_score_ard:.3f}, "
    f"ElasticNet $R^2$: {r2_score_enet:.3f}"
)
plt.tight_layout()

まとめ

Lasso は、疎なデータを効果的に回復することが知られていますが、高度に相関のある特徴に対してはうまく機能しません。実際、いくつかの相関のある特徴がターゲットに寄与する場合、Lasso はそれらのうちの 1 つだけを選択してしまいます。疎で相関のない特徴の場合、Lasso モデルがより適しています。

ElasticNet は、係数にいくらかの疎性を導入し、それらの値をゼロに収束させます。したがって、ターゲットに寄与する相関のある特徴が存在する場合、モデルはそれらの重みを正確にゼロに設定せずに減らすことができます。これは、純粋な Lasso よりも疎性の低いモデルになり、非予測的な特徴も捕捉する可能性があります。

ARDRegression は、ガウスノイズを処理する際には優れていますが、相関のある特徴を処理することはできず、事前分布を適合させるために時間がかかります。