Использование LASSO из пакета lars (или glmnet) в R для выбора переменных

39

Извините, если этот вопрос встречается немного базовым.

Я хочу использовать выбор переменных LASSO для модели множественной линейной регрессии в R. У меня есть 15 предикторов, один из которых является категориальным (вызовет ли это проблему?). После установки моих и я использую следующие команды:ИксY

model = lars(x, y)
coef(model)

Моя проблема, когда я использую coef(model). Это возвращает матрицу с 15 строками, каждый раз добавляется один дополнительный предиктор. Однако нет никаких предложений относительно того, какую модель выбрать. Я что-то пропустил? Есть ли способ получить пакет lars для возврата только одной « лучшей » модели?

Есть другие посты, предлагающие использовать glmnetвместо этого, но это кажется более сложным. Попытка заключается в следующем, используя те же и . Я что-то здесь пропустил? ИксY

cv = cv.glmnet(x, y)
model = glmnet(x, y, type.gaussian="covariance", lambda=cv$lambda.min)
predict(model, type="coefficients")

Последняя команда возвращает список моих переменных, большинство с коэффициентом, хотя некоторые из них = 0. Это правильный выбор « лучшей » модели, выбранной LASSO? Если я затем подгоняю линейную модель ко всем моим переменным с коэффициентами, not=0я получаю очень похожие, но немного отличающиеся оценки коэффициентов. Есть ли причина для такой разницы? Было бы приемлемо перефразировать линейную модель с этими переменными, выбранными LASSO, и принять это как мою окончательную модель? В противном случае я не вижу никаких значений p для значимости. Я что-то пропустил?

Имеет ли

type.gaussian="covariance" 

убедиться, что glmnetиспользуется множественная линейная регрессия?

Влияет ли автоматическая нормализация переменных на коэффициенты вообще? Есть ли способ включить условия взаимодействия в процедуру LASSO?

Я собираюсь использовать эту процедуру в большей степени как демонстрацию того, как LASSO может использоваться, чем для любой модели, которая будет фактически использоваться для любого важного вывода / прогноза, если это что-то изменит.

Спасибо, что нашли время, чтобы прочитать это. Любые общие комментарии по LASSO / lars / glmnet также будут высоко оценены.

Джеймс
источник
4
В качестве дополнительного комментария, если вы хотите интерпретировать результат, убедитесь, что набор переменных, выбранных Лассо, стабилен. Это можно сделать с помощью симуляции Монте-Карло или загрузив свой собственный набор данных.
Фрэнк Харрелл

Ответы:

28

Пользоваться им glmnetдействительно легко, как только вы его освоите, благодаря превосходной виньетке на http://web.stanford.edu/~hastie/glmnet/glmnet_alpha.html (вы также можете проверить страницу пакета CRAN). Что касается лучшей лямбды glmnet, эмпирическое правило заключается в использовании

cvfit <- glmnet::cv.glmnet(x, y)
coef(cvfit, s = "lambda.1se")

вместо lambda.min.

Чтобы сделать то же самое, larsвы должны сделать это вручную. Вот мое решение

cv <- lars::cv.lars(x, y, plot.it = FALSE, mode = "step")
idx <- which.max(cv$cv - cv$cv.error <= min(cv$cv))
coef(lars::lars(x, y))[idx,]

Имейте в виду, что это не совсем то же самое, потому что это останавливается на узле лассо (когда входит переменная), а не в любой точке.

Обратите внимание, что glmnetсейчас это предпочтительный пакет, он активно поддерживается, более того lars, и что ранее были вопросы по glmnetсравнению с larsответами (используемые алгоритмы отличаются).

Что касается вашего вопроса об использовании лассо для выбора переменных, а затем для подбора OLS, это постоянные дебаты. Google для OLS опубликовать сообщение Лассо, и есть несколько статей, обсуждающих эту тему. Даже авторы «Элемента статистического обучения» признают, что это возможно.

Изменить : вот код для более точного воспроизведения, что glmnetделает вlars

  cv <- lars::cv.lars(x, y, plot.it = FALSE)
  ideal_l1_ratio <- cv$index[which.max(cv$cv - cv$cv.error <= min(cv$cv))]
  obj <- lars::lars(x, y)
  scaled_coefs <- scale(obj$beta, FALSE, 1 / obj$normx)
  l1 <- apply(X = scaled_coefs, MARGIN = 1, FUN = function(x) sum(abs(x)))
  coef(obj)[which.max(l1 / tail(l1, 1) > ideal_l1_ratio),]
Juancentro
источник
+1 Отличный ответ! Не могли бы вы или кто-либо еще уточнить, почему lambda.1se является эмпирическим правилом, а не lambda.min?
Еросеннин
После 4 лет написания этого (и без использования лассо некоторое время) моя память просто исчезла. Сожалею!
Juancentro
9

Я возвращаюсь к этому вопросу некоторое время назад, так как думаю, что решил правильное решение.

Вот реплика, использующая набор данных mtcars:

library(glmnet)
`%ni%`<-Negate(`%in%')
data(mtcars)

x<-model.matrix(mpg~.,data=mtcars)
x=x[,-1]

glmnet1<-cv.glmnet(x=x,y=mtcars$mpg,type.measure='mse',nfolds=5,alpha=.5)

c<-coef(glmnet1,s='lambda.min',exact=TRUE)
inds<-which(c!=0)
variables<-row.names(c)[inds]
variables<-variables[variables %ni% '(Intercept)']

«Переменные» дает вам список переменных, которые решают лучшее решение.

Джейсон
источник
1
Я искал код и обнаружил, что «тестирование» еще не определено, и поэтому код: «final.list <-testing [-removed] #removing variable» выдает ошибку: объект не найден Предположим, что вместо «тестирования» следует использовать «cp.list», чтобы код был: final.list <-cp.list [-removed] # удаление переменных final.list <-c (final.list, дубликаты) # добавление в те переменные, которые были удалены, а затем добавлены позже. Дайте мне знать, если это правильно. С уважением
3
`% Ni%` <-Negate ( `% Ni%`); ## выглядит неправильно. Хотя `% ni%` <-Negate (`% in%`); ## выглядит правильно. Я думаю, что форматировщик stackexchange испортил это ...
Крис
Можете ли вы уточнить, как вы выбрали nfolds=5и alpha=0.5параметры?
Колин
7

Возможно, поможет сравнение с поэтапной регрессией прямого выбора (см. Следующую ссылку на сайт одного из авторов http://www-stat.stanford.edu/~tibs/lasso/simple.html). Этот подход используется в главе 3.4.4 «Элементы статистического обучения» (доступен онлайн бесплатно). Я думал, что глава 3.6 в этой книге помогла понять связь между наименьшими квадратами, лучшим подмножеством и лассо (плюс несколько других процедур). Я также считаю полезным взять транспонирование коэффициента t (coef (модель)) и write.csv, чтобы я мог открыть его в Excel вместе с копией графика (модели) на стороне. Возможно, вы захотите отсортировать по последнему столбцу, который содержит оценку наименьших квадратов. Затем вы можете ясно видеть, как каждая переменная добавляется на каждом кусочном шаге и как коэффициенты изменяются в результате. Конечно, это не вся история, но, надеюсь, это будет начало.

Джоэл Кадвелл
источник
3

larsи glmnetоперировать необработанными матрицами. Чтобы включить условия взаимодействия, вы должны будете сами построить матрицы. Это означает, что один столбец на взаимодействие (то есть на уровень на фактор, если у вас есть факторы). Посмотрите, lm()чтобы увидеть, как он это делает (предупреждение: там будут драконы).

Чтобы сделать это прямо сейчас, сделайте что-то вроде: Чтобы создать термин взаимодействия вручную, вы можете (но, возможно, не должны , потому что он медленный) сделать:

int = D["x1"]*D["x2"]
names(int) = c("x1*x2")
D = cbind(D, int)

Затем, чтобы использовать это в lars (при условии, что вы yразбираетесь):

lars(as.matrix(D), as.matrix(y))

Я хотел бы помочь вам больше с другими вопросами. Я нашел это, потому что Ларс приносит мне горе, и документация в нем и в Интернете очень тонкая.

kousu
источник
2
«Предупреждение: там будут драконы» Это довольно легко model.matrix().
Грегор
2

LARS решает ВСЁ путь решения. Путь решения является кусочно-линейным - существует конечное число «надрезов» точек (т. Е. Значений параметра регуляризации), в которых изменяется решение.

Таким образом, матрица решений, которые вы получаете, - это все возможные решения. В списке, который он возвращает, он также должен дать вам значения параметра регуляризации.

Адам
источник
Спасибо за ваш ответ. Есть ли способ отобразить значения параметра регуляризации? Кроме того, есть ли способ выбора между решениями на основе этого параметра? (Также это параметр лямбда?)
Джеймс
Обратите внимание, что кусочно-линейность не означает, что линии горизонтальны, и, следовательно, решение постоянно меняется с лямбда-выражением. Например, для целей прогнозирования можно использовать сетку лямбда-значений не только в узлах, но и между ними . Вполне возможно, что некоторая точка между узлами дает лучшую прогностическую эффективность.
Ричард Харди