Как указать лог ссылку в glmnet?
Я использую эластичную сеть на обобщенной линейной модели с пакетами glmnet и caret в R.
Моя переменная ответа - это стоимость (где стоимость> $0), и поэтому я бы хотел указать семейство Гауссов со ссылкой на журнал для моего GLM. Однако glmnet не позволяет мне указывать (link="log")
следующее:
> lasso_fit <- glmnet(x, y, alpha=1, family="gaussian"(link="log"), lambda.min.ratio=.001)
Я пробовал разные варианты, с цитатами и без, но не повезло. В документации glmnet не обсуждается, как включить ссылку на журнал.
Я что-то пропустил? Есть ли family="gaussian"
уже неявно предполагаем ссылку на логи?
1 ответ
Это немного сбивает с толку, но family
аргумент в glmnet
а также glm
совсем разные. В glm
Вы можете указать character
лайк "gaussian"
или вы можете указать функцию с некоторыми аргументами, такими как gaussian(link="log")
, В glmnet
можно указать только семью с character
, лайк "gaussian"
и нет способа автоматически установить ссылку через этот аргумент.
Ссылка по умолчанию для gaussian
это identity
функция, то есть никакого преобразования вообще. Но помните, что функция ссылки - это просто преобразование вашей y
переменная; Вы можете просто указать это самостоятельно:
glmnet(x, log(y), family="gaussian")
Также обратите внимание, что ссылка по умолчанию для poisson
семья log
, но функция цели изменится. Смотрите детали под ?glmnet
в первой паре абзацев.
Ваши комментарии привели меня к переосмыслению моего ответа; У меня есть доказательства того, что это не правильно.
Как вы указали, существует разница между E[log(Y)] и log(E[Y]). Я думаю, что приведенный выше код соответствует E[log(Y)], а это не то, что вам нужно. Вот некоторый код для генерации данных и подтверждения того, что вы отметили в комментариях:
# Generate data
set.seed(1)
x <- replicate(3,runif(1000))
y <- exp(2*x[,1] + 3*x[,2] + x[,3] + runif(1000))
df <- data.frame(y,x)
# Run the model you *want*
glm(y~., family=gaussian(link="log"), data=df)$coef
# (Intercept) X1 X2 X3
# 0.4977746 2.0449443 3.0812333 0.9451073
# Run the model you *don't want* (in two ways)
glm(log(y)~., family=gaussian(link='identity'), data=df)$coef
# (Intercept) X1 X2 X3
# 0.4726745 2.0395798 3.0167274 0.9957110
lm(log(y)~.,data=df)$coef
# (Intercept) X1 X2 X3
# 0.4726745 2.0395798 3.0167274 0.9957110
# Run the glmnet code that I suggested - getting what you *don't want*.
library(glmnet)
glmnet.model <- glmnet(x,log(y),family="gaussian", thresh=1e-8, lambda=0)
c(glmnet.model$a0, glmnet.model$beta[,1])
# s0 V1 V2 V3
# 0.4726745 2.0395798 3.0167274 0.9957110
Я знаю, что это старый вопрос, но в текущей версии glmnet (4.0-2), что это можно использовать GLM семейных функций в качестве аргументов для "семьи" вместо строки символов, так что вы можете использовать:
glmnet(x, y, family=gaussian(link="log"))
Обратите внимание, что при использовании строковых аргументов пакет работает быстрее.
Ссылка: https://glmnet.stanford.edu/articles/glmnetFamily.html