Использование LASSO в R с категориальными переменными
У меня есть набор данных с 1000 наблюдениями и 76 переменными, около двадцати из которых являются категориальными. Я хочу использовать 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 ответа
Другие ответы здесь указывают на способы перекодирования ваших категориальных факторов в качестве фиктивных. В зависимости от вашего приложения, это может быть не лучшим решением. Если все, что вас волнует, это предсказание, то это, вероятно, хорошо, и подход, предоставленный Flo.P, должен быть в порядке. LASSO найдет вам полезный набор переменных, и вы, вероятно, не будете перегружены.
Однако, если вам интересно интерпретировать свою модель или обсудить, какие факторы важны после факта, вы оказались в странном положении. Код по умолчанию для этого model.matrix имеет очень специфические интерпретации, когда они взяты сами по себе. model.matrix использует то, что называется "фиктивным кодированием". (Я помню, как изучал его как "эталонное кодирование"; см. Здесь краткое изложение.) Это означает, что если включен один из этих макетов, ваша модель теперь имеет параметр, интерпретация которого равна "разнице между одним уровнем этого фактора и произвольно выбрал другой уровень этого фактора ". И, возможно, ни один из других манекенов для этого фактора не был выбран. Вы также можете обнаружить, что если порядок ваших уровней факторов изменится, вы получите другую модель.
Есть способы справиться с этим, но вместо того, чтобы что-то связывать вместе, я бы попробовал групповое лассо. Опираясь на код 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, за исключением случаев, когда применяется минимальная величина регуляризации. Вы можете поиграть со значениями лямбды (параметр настройки) или просто оставить опцию пустой, и функция выберет для вас диапазон.
Вы можете сделать фиктивные переменные из вашего фактора, используя model.matrix
,
Я создаю data.frame. у является целевой переменной.
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)
Код может быть упрощен. Но идея здесь.