在R中使用LASSO和分类变量

时间:2017-10-21 17:09:32

标签: r regression glmnet lasso lars

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

谢谢,

2 个答案:

答案 0 :(得分: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 :(得分: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值(调整参数),也可以将选项保留为空白,该函数将为您选择一个范围。