在R中使用LASSO和分类变量

问题描述 投票:5回答:2

我有一个包含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来做到这一点,所以如果可能的话,我会很感激任何想法或反馈。

谢谢,

r regression glmnet lasso lars
2个回答
1
投票

您可以使用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)

代码可以简化。但这个想法就在这里。


1
投票

这里的其他答案指出了将您的分类因素重新编码为假人的方法。根据您的应用,它可能不是一个很好的解决方案。如果您关心的只是预测,那么这可能很好,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的值(一个调整参数),或者只是将选项留空,该函数将为你选择一个范围。

© www.soinside.com 2019 - 2024. All rights reserved.