如何解释glmnet?

机器算法验证 r 回归 正则化 网络
2022-02-09 13:26:44

我正在尝试拟合具有大约 60 个预测变量和 30 个观察值的多元线性回归模型,因此我使用glmnet包进行正则化回归,因为 p>n。

我一直在阅读文档和其他问题,但我仍然无法解释结果,这是一个示例代码(有 20 个预测变量和 10 个观察值来简化):

我创建了一个矩阵 x,其中 num rows = num 观察值和 num cols = num 个预测变量和一个表示响应变量的向量 y

> x=matrix(rnorm(10*20),10,20)
> y=rnorm(10)

我拟合了一个 glmnet 模型,将 alpha 作为默认值(= 1 表示 lasso 惩罚)

> fit1=glmnet(x,y)
> print(fit1)

我知道随着 lambda 值的减小(即惩罚),我得到了不同的预测

Call:  glmnet(x = x, y = y) 

        Df    %Dev   Lambda
  [1,]  0 0.00000 0.890700
  [2,]  1 0.06159 0.850200
  [3,]  1 0.11770 0.811500
  [4,]  1 0.16880 0.774600
   .
   .
   .
  [96,] 10 0.99740 0.010730
  [97,] 10 0.99760 0.010240
  [98,] 10 0.99780 0.009775
  [99,] 10 0.99800 0.009331
 [100,] 10 0.99820 0.008907

现在我预测我的 Beta 值,例如,选择从glmnet

> predict(fit1,type="coef", s = 0.008907)

21 x 1 sparse Matrix of class "dgCMatrix"
                  1
(Intercept) -0.08872364
V1           0.23734885
V2          -0.35472137
V3          -0.08088463
V4           .         
V5           .         
V6           .         
V7           0.31127123
V8           .         
V9           .         
V10          .         
V11          0.10636867
V12          .         
V13         -0.20328200
V14         -0.77717745
V15          .         
V16         -0.25924281
V17          .         
V18          .         
V19         -0.57989929
V20         -0.22522859

相反,如果我选择 lambda

cv <- cv.glmnet(x,y)
model=glmnet(x,y,lambda=cv$lambda.min)

所有变量都是 (.)。

疑问和问题:

  1. 我不确定如何选择 lambda。
  2. 我应该使用非 (.) 变量来拟合另一个模型吗?就我而言,我想保留尽可能多的变量。
  3. 我如何知道 p 值,即哪些变量可以显着预测响应?

我为我糟糕的统计知识道歉!谢谢你的帮助。

2个回答

这是一个不直观的事实——你实际上不应该给 glmnet 一个单一的 lambda 值。这里的文档:

不要为 lambda 提供单个值(对于 CV 之后的预测,请改用 predict())。而是提供递减的 lambda 值序列。glmnet 依赖于它的热启动来提高速度,而且拟合整个路径通常比计算单个拟合更快。

cv.glmnet正如您在示例中提到的那样,将帮助您选择 lambda。glmnet 包的作者建议cv$lambda.1se不要使用cv$lambda.min,但实际上我在后者方面取得了成功。

运行 cv.glmnet 后,您不必重新运行 glmnet!网格 ( cv$lambda) 中的每个 lambda 都已运行。这种技术称为“热启动”,您可以在此处了解更多信息。从介绍中解释,Warm Start 技术通过使用不同优化问题(例如,具有较大 lambda 的 glmnet)的解决方案作为后续优化问题(例如,具有较小 lambda 的 glmnet)的起始值来减少迭代方法的运行时间)。

要从中提取所需的运行cv.glmnet.fit,请尝试以下操作:

small.lambda.index <- which(cv$lambda == cv$lambda.min)
small.lambda.betas <- cv$glmnet.fit$beta[, small.lambda.index]

修订(2017 年 1 月 28 日)

无需像我上面那样破解 glmnet 对象;s = "lambda.min"在下面接受@alex23lemm的建议并将s = "lambda.1se"或其他数字(例如s = .007)传递给coefpredict请注意,您的系数和预测取决于此值,该值由交叉验证设置。使用种子可重复性!并且不要忘记,如果您不提供"s"incoefpredict,您将使用默认的s = "lambda.1se". 在看到它在小数据情况下工作得更好后,我已经热身到该默认值。s = "lambda.1se"也倾向于提供更多的正则化,所以如果你使用 alpha > 0,它也会倾向于更简约的模型。您还可以在 plot.glmnet 的帮助下选择 s 的数值以达到介于两者之间的某个位置(只是不要忘记对 x 轴的值求幂!)。

Q1) 我不确定如何选择 lambda。Q2) 我应该使用非 (.) 变量来拟合另一个模型吗?就我而言,我想保留尽可能多的变量。

根据@BenOgorek's great answer,通常您让拟合使用整个 lambda 序列,然后在提取最佳系数时使用 lambda.1se 值(与您所做的不同)。

只要您遵循以下三个警告,就不要反对正则化或调整模型:如果省略了一个变量,那是因为它给出了较低的整体惩罚。警告是:

  1. 为了使正则化系数有意义,请确保您事先明确地标准化了变量的均值和标准差scale()不要依赖glmnet(standardize=T)有关理由,请参阅Lasso 之前的标准化真的有必要吗?; 基本上,具有大值的变量可能会在正则化中受到不公平的惩罚。

  2. 为了可重现,set.seed使用几个随机种子运行并检查正则化系数的稳定性。

  3. 如果您想要不那么苛刻的正则化,即包含更多变量,请使用 alpha < 1(即适当的弹性网)而不是简单的 ridge。我建议您将 alpha 从 0 扫描到 1。如果您要这样做,那么为了避免过度拟合超参数 alpha 和回归误差,您必须使用交叉验证,即使用cv.glmnet()而不是简单glmnet()

.

for (alpha in c(0,.1,.3,.5,.7,.9,1)) {
  fit <- cv.glmnet(..., alpha=alpha, nfolds=...)
  # Look at the CVE at lambda.1se to find the minimum for this alpha value...
}

如果您想使用 CV 自动执行此类网格搜索,您可以自己编写代码,也可以在 glmnet 之上使用 caret 包;插入符号做得很好。对于cv.glmnet nfolds参数值,如果您的数据集很小,请选择 3(最小值),如果数据集很大,请选择 5 或 10。

Q3) 我如何知道 p 值,即哪些变量可以显着预测响应?

不要,它们没有意义正如在为什么不建议从 glmnet 模型中获取回归系数的统计摘要信息中详细解释的那样?

让我们cv.glmnet()自动选择变量。上面的警告。当然,响应变量的分布应该是正常的(假设您使用的是family='gaussian')。