我有一个包含1000个观测值和76个变量的数据集,其中大约20个是绝对的。我想在整个数据集上使用LASSO。我知道有因子变量在LASSO中通过lars或glmnet确实不起作用,但是变量太多而且有太多不同的,无序的值它们可以用来合理地重新编码它们。
可以在这种情况下使用LASSO吗?我该怎么做呢?创建预测变量矩阵会产生以下响应:
hdy<-as.numeric(housingData2[,75])
hdx<-as.matrix(housingData2[,-75])
model.lasso <- lars(hdx, hdy)
Error in one %*% x : requires numeric/complex matrix/vector arguments
我意识到其他方法可能更容易或更合适,但挑战实际上是使用lars或glmnet来做到这一点,所以如果可能的话,我会很感激任何想法或反馈。
谢谢,
您可以使用model.matrix
从您的因子中创建虚拟变量。
我创建了一个data.frame。 y是目标变量。
create_factor <- function(nb_lvl, n= 100 ){
factor(sample(letters[1:nb_lvl],n, replace = TRUE))}
df <- data.frame(var1 = create_factor(5),
var2 = create_factor(5),
var3 = create_factor(5),
var4 = create_factor(5),
var5 = rnorm(100),
y = create_factor(2))
# var1 var2 var3 var4 var5 y
# 1 a c c b -0.58655607 b
# 2 d a e a 0.52151994 a
# 3 a b d a -0.04792142 b
# 4 d a a d -0.41754957 b
# 5 a d e e -0.29887004 a
选择所有因子变量。我使用dplyr::select_if
然后解析变量名称来获得像y ~ var1 + var2 +var3 +var4
这样的表达式
library(dplyr)
library(stringr)
library(glmnet)
vars_name <- df %>%
select(-y) %>%
select_if(is.factor) %>%
colnames() %>%
str_c(collapse = "+")
model_string <- paste("y ~",vars_name )
使用model.matrix
创建虚拟变量。不要忘记as.formula
强迫性格配方。
x_train <- model.matrix(as.formula(model_string), df)
适合你的模特。
lasso_model <- cv.glmnet(x=x_train,y = df$y, family = "binomial", alpha=1, nfolds=10)
代码可以简化。但这个想法就在这里。
这里的其他答案指出了将您的分类因素重新编码为假人的方法。根据您的应用,它可能不是一个很好的解决方案。如果您关心的只是预测,那么这可能很好,Flo.P提供的方法应该没问题。 LASSO会为您找到一组有用的变量,您可能不会过度适应。
但是,如果您有兴趣解释您的模型或讨论事后重要的因素,那么您就处于一个奇怪的地方。 model.matrix的默认编码在自己采用时具有非常具体的解释。 model.matrix使用所谓的“虚拟编码”。 (我记得把它作为“参考编码”学习;请参阅here的摘要。)这意味着如果包含其中一个假人,你的模型现在有一个参数,其解释是“这个因素的一个级别与任意之间的差异”选择该因素的其他水平“。并且可能没有选择该因素的其他假人。您可能还会发现,如果您的因子水平的顺序发生变化,您最终会得到一个不同的模型。
有办法解决这个问题,但是我不会把这些东西拼凑在一起,而是尝试组合套索。基于上面的Flo.P代码构建:
install.packages("gglasso")
library(gglasso)
create_factor <- function(nb_lvl, n= 100 ){
factor(sample(letters[1:nb_lvl],n, replace = TRUE))}
df <- data.frame(var1 = create_factor(5),
var2 = create_factor(5),
var3 = create_factor(5),
var4 = create_factor(5),
var5 = rnorm(100),
y = rnorm(100))
y <- df$y
x <- model.matrix( ~ ., dplyr::select(df, -y))[, -1]
groups <- c(rep(1:4, each = 4), 5)
fit <- gglasso(x = x, y = y, group = groups, lambda = 1)
fit$beta
因为我们没有指定我们的因子(var1,var2等)和y之间的关系,所以LASSO做得很好并且将所有系数设置为0,除非应用最小正则化量。你可以使用lambda的值(一个调整参数),或者只是将选项留空,该函数将为你选择一个范围。