如何解释glmnet?


36

我正在尝试使用约60个预测变量和30个观察值来拟合多元线性回归模型,所以我使用glmnet软件包进行正则回归,因为p> n。

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

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

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

我适合一个glmnet模型,将alpha保留为默认值(套索罚分= 1)

> 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值,即哪些变量可以显着预测响应?

很抱歉,我的统计知识不佳!并感谢您的任何帮助。


也许看看CRAN软件包hdi,它为高维模型提供了推论...
Tom Wenseleers 17-4-6

有关使用的方法的完整说明,请参考本文:projecteuclid.org/euclid.ss/1449670857
Tom Wenseleers

Answers:


40

这是一个不直观的事实-实际上您不应该为glmnet赋予单个lambda值。从这里的文档:

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

cv.glmnet正如您在示例中提到的那样,它将帮助您选择lambda。glmnet软件包的作者建议使用cv$lambda.1se而不是cv$lambda.min,但是在实践中,我已经成功地使用了后者。

运行cv.glmnet之后,您无需重新运行glmnet!网格(cv$lambda)中的每个lambda 已经运行。该技术称为“暖启动”,您可以在此处了解更多信息。从引言的角度讲,“热启动”技术通过使用不同的优化问题(例如,具有较大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]

修订(1/28/2017)

无需像我上面那样破解glmnet对象;采取下面@ alex23lemm的意见和通过s = "lambda.min"s = "lambda.1se"或一些其他数目(例如,s = .007)同时coefpredict。请注意,您的系数和预测取决于此值,该值是通过交叉验证设置的。使用种子来提高可重复性!而且请不要忘记,如果您不提供"s"in coefpredict,则将使用默认值s = "lambda.1se"。看到默认值在小数据情况下可以更好地工作后,我已经对其进行了热身。s = "lambda.1se"也倾向于提供更多的正则化,因此,如果您使用的alpha> 0,则也倾向于使用更简约的模型。您还可以在plot.glmnet的帮助下选择一个s的数值,以介于两者之间(只是不要忘记对x轴的值求幂!)。


1
谢谢!这有帮助...您可能对问题2和3有答案吗?
爱丽丝

3
不用担心。(。)代表零。自从使用Lasso以来,您已经指定要使用“稀疏”解决方案(即,很多零)。如果希望它们都具有值,请将alpha设置为0。现在,您已从套索转换为Ridge回归。glmnet的p值在​​概念上很棘手。举例来说,如果您用Google搜索“套索的p值”,则会看到很多近期的研究和争论。我什至读过一篇文章(源于失忆症),作者认为p值对套索和山脊回归等偏向回归没有意义。
Ben Ogorek

6
提取与给出最小cvm的lambda值相关的系数的另一种方法是:small.lambda.betas <- coef(cv, s = "lambda.min")
alex23lemm 2015年

1
@BenOgorek,精彩更新!另一个有用的参考是Friedman J,Hastie T,Hoefling H,TibshiraniR。路径坐标优化。应用统计年鉴。2007; 2(1):302–332。(arxiv.org/pdf/0708.1485.pdf
dv_bn

1
@erosennin,检查cv.glmnet的lambda参数:“可选的用户提供的lambda序列;默认为NULL,并且glmnet选择自己的序列。” 您将要使用热启动的原则,减少对你感兴趣的范围内之前开始拉姆达的一些较大值的序列。
本Ogorek

2

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

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

只要遵循以下三个注意事项,就不要对正则化进行调整或对模型进行调整:如果省略了变量,则是因为它给出了较低的总体损失。注意事项是:

  1. 为了使正规化的系数有意义,请确保事先使用scale();显式标准化了变量的均值和标准差。不要依靠glmnet(standardize=T)。有关合理性的信息,请参阅在套索之前真的有必要进行标准化吗?; 基本上,具有大值的变量可能会在正则化中受到不公平的惩罚。

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

  3. 如果要减少苛刻的正则化,即包含更多变量,请使用alpha <1(即适当的弹性网),而不要使用简单的岭。我建议您将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上使用插入符号包。插入符号可以很好地做到这一点。对于cv.glmnet nfolds参数值,如果数据集较小,则选择3(最小值),如果数据集较大,则选择5或10。

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

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

只需让cv.glmnet()变量自动选择即可。有上述警告。当然,响应变量的分布应该是正常的(假设您正在使用family='gaussian')。


感谢您的宝贵意见!我还体验到标准化变量本身似乎可以工作,而不是使用glmnet(standardize = T)。
米歇尔

我有一个@smci问题,关于cvglmnet返回的beta值。我了解到,它们是Lambda尝试值的每个网格点处的beta值。但是,是每个lambda值返回的beta值(1)来自10倍的平均系数值(假设我使用10foldCV),(2)来自给出最佳准确性的倍数的beta值,还是(3)来自在整个数据集上重新运行模型?
米歇尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.