在本例中,评估了线性模型中正则化参数的影响,该模型被称为弹性网络(ElasticNet)。为了进行这种评估,使用了验证曲线(ValidationCurveDisplay),该曲线显示了模型在不同正则化参数值下的训练和测试分数。一旦确定了最优的正则化参数,就会将模型的真实系数和估计系数进行比较,以确定模型是否能够从噪声输入数据中恢复系数。
生成了一个回归数据集,该数据集相对于样本数量具有许多特征。然而,只有10%的特征是信息性的。在这种情况下,通常使用暴露L1惩罚的线性模型来恢复一组稀疏的系数。
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
n_samples_train, n_samples_test, n_features = 150, 300, 500
X, y, true_coef = make_regression(
n_samples=n_samples_train + n_samples_test,
n_features=n_features,
n_informative=50,
shuffle=False,
noise=1.0,
coef=True,
random_state=42,
)
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
train_size=n_samples_train,
test_size=n_samples_test,
shuffle=False
)
在这里,不使用只暴露L1惩罚的模型。相反,使用了一个弹性网络模型,该模型暴露了L1和L2惩罚。固定了l1_ratio参数,以便模型找到的解仍然是稀疏的。因此,这种类型的模型试图找到一个稀疏的解,但同时也试图将所有系数缩小到零。此外,强制模型的系数为正,因为知道make_regression生成的响应具有正信号。因此,使用这种先验知识来获得更好的模型。
from sklearn.linear_model import ElasticNet
enet = ElasticNet(
l1_ratio=0.9,
positive=True,
max_iter=10_000
)
为了评估正则化参数的影响,使用了一个验证曲线。这个曲线显示了模型在不同正则化参数值下的训练和测试分数。正则化alpha是一个应用于模型系数的参数:当它趋于零时,不应用正则化,模型试图以最少的误差拟合训练数据。然而,当特征噪声时,它会导致过拟合。当alpha增加时,模型系数受到限制,因此模型不能像以前那样紧密地拟合训练数据,避免了过拟合。然而,如果应用了太多的正则化,模型就会欠拟合数据,无法正确捕捉信号。验证曲线有助于在两个极端之间找到一个好的折衷:模型没有被正则化,因此足够灵活以拟合信号,但不要太灵活以至于过拟合。ValidationCurveDisplay允许在一系列alpha值上显示训练和验证分数。
import numpy as np
from sklearn.model_selection import ValidationCurveDisplay
alphas = np.logspace(-5, 1, 60)
disp = ValidationCurveDisplay.from_estimator(
enet,
X_train,
y_train,
param_name="alpha",
param_range=alphas,
scoring="r2",
n_jobs=2,
score_type="both",
)
disp.ax_.set(
title=r"Validation Curve for ElasticNet (R$^2$ Score)",
xlabel=r"alpha (regularization strength)",
ylabel="R$^2$ Score",
)
test_scores_mean = disp.test_scores.mean(axis=1)
idx_avg_max_test_score = np.argmax(test_scores_mean)
disp.ax_.vlines(
alphas[idx_avg_max_test_score],
disp.ax_.get_ylim()[0],
test_scores_mean[idx_avg_max_test_score],
color="k",
linewidth=2,
linestyle="--",
label=f"Optimum on test\n$\\alpha$ = {alphas[idx_avg_max_test_score]:.2e}",
)
_ = disp.ax_.legend(loc="lower right")
现在已经确定了最优的正则化参数,可以比较真实系数和估计系数。首先,将正则化参数设置为最优值,并在训练数据上拟合模型。此外,将显示此模型的测试分数。
enet.set_params(alpha=alphas[idx_avg_max_test_score])
.fit(X_train, y_train)
print(f"Test score: {enet.score(X_test, y_test):.3f}")
测试分数:0.884
现在,绘制真实系数和估计系数。
import matplotlib.pyplot as plt
fig, axs = plt.subplots(ncols=2, figsize=(12, 6), sharex=True, sharey=True)
for ax, coef, title in zip(axs, [true_coef, enet.coef_], ["True", "Model"]):
ax.stem(coef)
ax.set(
title=f"{title} Coefficients",
xlabel="Feature Index",
ylabel="Coefficient Value",
)
fig.suptitle("Comparison of the coefficients of the true generative model and\nthe estimated elastic net coefficients")
plt.show()