变量的顺序改变了 glmnet 中的估计系数

Posted

技术标签:

【中文标题】变量的顺序改变了 glmnet 中的估计系数【英文标题】:Order of variables changes estimated coefficients in glmnet 【发布时间】:2016-10-24 06:24:49 【问题描述】:

我正在使用 R 中的 glmnet 包,在尝试重现“旧”分类器时遇到了问题。如果解释变量被置换(比如以相反的顺序),来自 cv.glmnet 的结果系数不等于使用未置换设计矩阵的系数。

例如,考虑以下数据:

library(glmnet)
set.seed(1)

#Set initial parameters
n <- 100
p <- 1000

#Simulate data
x <- matrix(rnorm(n * p), nrow = n, ncol = p)
colnames(x) <- as.character(1:p)
beta <- rnorm(n = p, mean = 2, sd = 2)
beta[rbinom(p, size = 1, prob = 0.5) == 0] <- 0
y <- x %*% beta + rnorm(100, sd = 0.1)

然后对设计矩阵 x 和 x 的置换版本运行带有 LASSO 惩罚 (alpha = 1) 的 glmnet。

#Set parameters for cross validation with cv.glmnet
lambda <- exp(seq(-1, 1, length.out = 100))
alpha <- 1
foldid <- rep(1:10, each = 10)

#Run cross validation
fit <- cv.glmnet(x = x, y = y, family = "gaussian", alpha = alpha, 
                 lambda = lambda, 
                 foldid = foldid)

#Save coefficients
coef1 <- as.matrix(coef(fit, s = "lambda.min"))

#Run cross validation with rearranged design matrix
order <- ncol(x):1
fit2 <- cv.glmnet(x = x[,order], y = y, family = "gaussian", alpha = alpha, 
                  lambda = lambda, 
                  foldid = foldid)

#Save coefficients
coef2 <- as.matrix(coef(fit2, s = "lambda.min"))
coef2 <- coef2[rownames(coef1),]

然后比较系数、交叉验证误差和线性预测变量。

> summary(coef2 - coef1)
       1             
 Min.   :-0.2738963  
 1st Qu.: 0.0000000  
 Median : 0.0000000  
 Mean   : 0.0003739  
 3rd Qu.: 0.0000000  
 Max.   : 0.3643040

> min(fit$cvm)
[1] 4584.373
> min(fit2$cvm)
[1] 4596.626

> summary(cbind(1,x) %*% coef2 - cbind(1, x) %*% coef1)
       1          
 Min.   :-0.5100  
 1st Qu.:-0.1613  
 Median : 0.0210  
 Mean   : 0.0000  
 3rd Qu.: 0.1333  
 Max.   : 0.6139

对于所有三个度量,我们看到模型之间的差异,而只有变量的顺序发生了变化。谁能解释一下?

【问题讨论】:

【参考方案1】:

我相信这是因为 glmnet 使用坐标下降,其中迭代变量以最小化损失函数。在这种情况下,变量的顺序会改变迭代的顺序,从而改变最小化损失函数的路径。

【讨论】:

【参考方案2】:

Glmnet 通过坐标下降计算 LASSO 正则化路径(参见 Trevor Hastie 演讲的幻灯片 15:http://web.stanford.edu/~hastie/TALKS/glmnet.pdf)。由于算法对系数进行迭代,因此变量的顺序会影响所采用的路径。根据收敛阈值和最大迭代次数,这可能导致系数的最终值存在差异。在您的示例中,请尝试更改

fit <- cv.glmnet(x = x, y = y, family = "gaussian", alpha = alpha, 
                 lambda = lambda, 
                 foldid = foldid)

例如

fit <- cv.glmnet(x = x, y = y, family = "gaussian", alpha = alpha, 
                 lambda = lambda, 
                 foldid = foldid, standardize=TRUE, thresh=1e-20, maxit=10^6)

并为您的fit2 做同样的事情。这可能需要一分钟左右的时间来计算,但您会发现差异变得可以忽略不计:

> summary(coef2 - coef1)
       1             
 Min.   :-2.038e-08  
 1st Qu.: 0.000e+00  
 Median : 0.000e+00  
 Mean   : 1.050e-10  
 3rd Qu.: 0.000e+00  
 Max.   : 3.028e-08  
> 
> min(fit$cvm)
[1] 4598.242
> 
> min(fit2$cvm)
[1] 4598.242
> 
> summary(cbind(1,x) %*% coef2 - cbind(1, x) %*% coef1)
       1             
 Min.   :-5.175e-08  
 1st Qu.:-1.457e-08  
 Median :-2.959e-10  
 Mean   : 0.000e+00  
 3rd Qu.: 1.503e-08  
 Max.   : 5.555e-08  

【讨论】:

以上是关于变量的顺序改变了 glmnet 中的估计系数的主要内容,如果未能解决你的问题,请参考以下文章

$\lambda = 0$ 和 OLS 的 LASSO 在 R glmnet 中产生不同的结果

全局变量的顺序改变了 C++/OpenGL 中的性能

r:来自 glmnet 和 caret 的系数对于相同的 lambda 是不同的

R语言基于glmnet构建分类模型并可视化特征系数(coefficient)以及L1正则化系数(lambda)实战

用分类数据解释 GLM 输出

Multipolyfit(Python):系数的顺序是啥?