在R的glmnet中,使用$\lambda=0$的LASSO和OLS会产生不同的结果。

14

我预期LASSO在没有惩罚因子($\lambda=0$)的情况下会产生与OLS拟合相同(或非常相似)的系数估计值。然而,当我将相同的数据(x,y)放入以下两个模型中:

  • glmnet(x, y , alpha=1, lambda=0) 用于LASSO拟合且不使用惩罚因子
  • lm(y ~ x) 用于OLS拟合。

为什么会出现不同的系数估计结果呢?


3
不要专注于R中的特定函数,最好解释为什么您认为这两个拟合应该非常相似。例如,如果您的意思是没有惩罚的LASSO应该只给出OLS拟合,则可以这样说。您还可以使用公式详细说明为什么您这样认为。 - Richard Hardy
1
我认为不带罚项的LASSO和OLS显然应该给出相同的结果。我想知道为什么这两种算法给出了不同的估计值。 - Helpa
对你来说很明显的事情可能并不明显,因此最好尽可能明确和精确。 - Richard Hardy
当然!我希望问题现在已经清楚了。 - Helpa
我确信这是一个软件问题,如果你手动通过SVD解决问题,你会得到相同的结果。我尝试过同样的事情。 - hxd1011
4个回答

4

我曾经遇到同样的问题,询问了周围的人但没有得到答案,后来我给包维护者(Trevor Hastie)发邮件询问,他给出了解决方案。当系列高度相关时会出现该问题。解决方案是通过减少在glmnet()函数调用中的阈值(而不是通过glmnet.control())来解决。下面的代码使用内置数据集EuStockMarkets并应用lambda=0的VAR。对于XSMI,OLS系数低于1,glmnet默认系数高于1,差约为0.03,并且带有thresh=1e-14glmnet系数非常接近OLS系数(差异为1.8e-7)。

# Use built-in panel data with integrated series
data("EuStockMarkets")
selected_market <- 2

# Take logs for good measure
EuStockMarkets <- log(EuStockMarkets)

# Get dimensions
num_entities <- dim(EuStockMarkets)[2]
num_observations <- dim(EuStockMarkets)[1]

# Build the response with the most recent observations at the top
Y <- as.matrix(EuStockMarkets[num_observations:2, selected_market])
X <- as.matrix(EuStockMarkets[(num_observations - 1):1, ])

# Run OLS, which adds an intercept by default
ols <- lm(Y ~ X)
ols_coef <- coef(ols)

# run glmnet with lambda = 0
fit <- glmnet(y = Y, x = X, lambda = 0)
lasso_coef <- coef(fit)

# run again, but with a stricter threshold
fit_threshold <- glmnet(y = Y, x = X, lambda = 0, thresh = 1e-14)
lasso_threshold_coef <- coef(fit_threshold)

# build a dataframe to compare the two approaches
comparison <- data.frame(ols = ols_coef,
                         lasso = lasso_coef[1:length(lasso_coef)],
                         lasso_threshold = lasso_threshold_coef[1:length(lasso_threshold_coef)]
)
comparison$difference <- comparison$ols - comparison$lasso
comparison$difference_threshold <- comparison$ols - comparison$lasso_threshold

# Show the two values for the autoregressive parameter and their difference
comparison[1 + selected_market, ]

R 返回:

           ols    lasso lasso_threshold  difference difference_threshold
XSMI 0.9951249 1.022945       0.9951248 -0.02782045         1.796699e-07

2
我也遇到了同样的问题,降低阈值并没有解决它。 - bob
@bob 你用了什么阈值?我现在很少做 LASSO,所以建议你再给包维护者发电子邮件,因为他非常负责。 - miguelmorin

4

您在使用该函数时有误。应将x作为模型矩阵,而非原始预测值。这样做可以得到完全相同的结果:

x <- rnorm(500)
y <- rnorm(500)
mod1 <- lm(y ~ x) 

xmm <- model.matrix(mod1)
mod2 <- glmnet(xmm, y, alpha=1, lambda=0)

coef(mod1)
coef(mod2)

但是glmnet默认情况下intercept=TRUE,因此它已经添加了一个截距项,对吧?所以我不清楚为什么这是必要的,因为你的xmm只是cbind(1,x).... - Tom Wenseleers
你在特殊情况下X变量没有相关性,所以你很幸运...在一般情况下,系数将不会相同... - Matifou

1

我已经运行了Hastie的书中关于“前列腺”示例数据集的下一个代码:

out.lin1 = lm( lpsa ~ . , data=yy ) 
out.lin1$coeff             
out.lin2 = glmnet( as.matrix(yy[ , -9]), yy$lpsa, family="gaussian", lambda=0, standardize=T  ) 
coefficients(out.lin2)

系数的结果非常相似。当我们使用标准化选项时,由glmnet()返回的系数以输入变量的原始单位表示。请确认您正在使用“高斯”系列。


添加 family = "gaussian" 没有改变结果。 - Helpa

0
从glmnet帮助文档中可以看到:请注意,对于“高斯”分布,glmnet在计算其lambda序列之前会将y标准化为单位方差(然后取消标准化得到结果系数);如果您希望重现/比较其他软件的结果,则最好提供标准化的y。

当系数的绝对值变小时,lm和glmnet系数之间的差异变小。当我取消标准化系数时,仍然得到相同的差异。 - Helpa
1
帮助文件中还有另一个警告,具体是关于 lambda 参数的描述,它指出如果仅提供标量而不是向量,则算法可能会出现问题。我不确定这是否只会导致速度问题,还是会使估计结果产生偏差。 - tomka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接