LASSO с $ \ lambda = 0 $ и OLS дают разные результаты в R glmnet

Я ожидаю, что LASSO без штрафов ($ \ lambda = 0 $) даст такие же (или очень похожие) оценки коэффициентов, что и подгонка OLS. Однако я получаю разные оценки коэффициентов в R, помещая одни и те же данные (x, y) в

  • glmnet(x, y , alpha=1, lambda=0) для LASSO подходит без штрафов и
  • lm(y ~ x) для OLS подходит.

Это почему?


person Community    schedule 14.07.2016    source источник
comment
Вместо того, чтобы сосредотачиваться на конкретной функции в R, вам лучше объяснить, почему вы думаете, что эти два соответствия должны быть очень похожими. Например. скажите, что LASSO без штрафов не должно давать ничего, кроме OLS, если вы это имеете в виду. Вы также можете уточнить, почему вы так думаете, используя формулы.   -  person Richard Hardy    schedule 14.07.2016
comment
Я думал, что это вполне очевидный LASSO без штрафов, и OLS должен дать такие же результаты. Мне было интересно, почему два алгоритма дают мне разные оценки.   -  person    schedule 14.07.2016
comment
То, что очевидно для вас, может быть неочевидным для всех остальных, поэтому на всякий случай лучше быть максимально точным и точным.   -  person Richard Hardy    schedule 14.07.2016
comment
Конечно! Надеюсь, проблема теперь ясна.   -  person    schedule 14.07.2016
comment
Я уверен, что это программная проблема. Если вы решите проблему с помощью СВД вручную, вы получите идентичный результат. Я пробовал то же самое.   -  person hxd1011    schedule 14.07.2016


Ответы (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)
person Community    schedule 14.07.2016
comment
Но в glmnet по умолчанию параметр intercept = TRUE, так что он уже добавляет термин перехват, верно? Мне непонятно, зачем это нужно, ведь xmm - это просто cbind (1, x) .... - person Tom Wenseleers; 13.08.2019

У меня была та же проблема, я безрезультатно расспрашивал меня, а затем я отправил электронное письмо сопровождающему пакета (Тревору Хасти), который дал ответ. Проблема возникает, когда ряды сильно коррелированы. Решение состоит в том, чтобы уменьшить порог в вызове функции glmnet() (а не через glmnet.control()). В приведенном ниже коде используется встроенный набор данных EuStockMarkets и применяется VAR с lambda=0. Для XSMI коэффициент OLS ниже 1, коэффициент glmnet по умолчанию больше 1 с разницей около 0,03, а коэффициент glmnet с thresh=1e-14 очень близок к коэффициенту 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
person miguelmorin    schedule 23.02.2018
comment
У меня была такая же проблема, и установка более низкого порога ее не решила. - person bob; 04.08.2020
comment
@bob Какое пороговое значение вы использовали? В наши дни я редко использую LASSO, поэтому предлагаю еще раз написать письмо сопровождающему пакета, так как он очень отзывчивый. - person miguelmorin; 05.08.2020

Я запустил с набором данных примера "простаты" из книги Хасти следующий код:

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 (), находятся в исходных единицах входных переменных. Пожалуйста, убедитесь, что вы используете семейство «гауссов»

person Community    schedule 14.07.2016
comment
Добавление family = gaussian не повлияло на результат - person ; 14.07.2016

Из справки glmnet: обратите внимание, что для «гауссовского», glmnet стандартизирует y, чтобы иметь единичную дисперсию перед вычислением его лямбда-последовательности (а затем нестандартизирует результирующие коэффициенты); если вы хотите воспроизвести / сравнить результаты с другим программным обеспечением, лучше всего предоставить стандартизированное y.

person tomka    schedule 14.07.2016
comment
Разница между коэффициентами lm и glmnet уменьшается по мере уменьшения абсолютного значения коэффициентов. Я все еще получаю те же различия, когда нестандартизирую коэффициенты. - person ; 14.07.2016
comment
В файле справки есть еще одно предупреждение, в частности, описание лямбда-параметра, в котором говорится, что алгоритм может иметь проблемы, если предоставляет только скаляр, а не вектор. Я не уверен, вызывает ли это только проблему скорости или действительно может искажать оценки. - person tomka; 14.07.2016