Пример: регрессия LASSO с использованием glmnet для двоичного результата


78

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

age     <- c(4, 8, 7, 12, 6, 9, 10, 14, 7) 
gender  <- c(1, 0, 1, 1, 1, 0, 1, 0, 0)
bmi_p   <- c(0.86, 0.45, 0.99, 0.84, 0.85, 0.67, 0.91, 0.29, 0.88)
m_edu   <- c(0, 1, 1, 2, 2, 3, 2, 0, 1)
p_edu   <- c(0, 2, 2, 2, 2, 3, 2, 0, 0)
f_color <- c("blue", "blue", "yellow", "red", "red", "yellow", "yellow", 
             "red", "yellow")
asthma  <- c(1, 1, 0, 1, 0, 0, 0, 1, 1)
# df is a data frame for further use!
df <- data.frame(age, gender, bmi_p, m_edu, p_edu, f_color, asthma)

Столбцы (переменные) в приведенном выше наборе данных являются следующими:

  • age (возраст ребенка в годах) - непрерывный
  • gender - двоичный (1 = мужской; 0 = женский)
  • bmi_p (Процентиль ИМТ) - непрерывный
  • m_edu (самый высокий уровень образования матери) - порядковый номер (0 = меньше, чем в старшей школе; 1 = диплом средней школы; 2 = степень бакалавра; 3 = степень бакалавра)
  • p_edu (отец высший уровень образования) - порядковый номер (так же, как m_edu)
  • f_color (любимый основной цвет) - номинальный («синий», «красный» или «желтый»)
  • asthma (статус астмы у ребенка) - бинарный (1 = астма; 0 = нет астмы)

Цель этого примера использовать лассо , чтобы создать модель прогнозирования состояния ребенка астмы из списка 6 потенциальных предикторов ( age, gender, bmi_p, m_edu, p_edu, и f_color). Очевидно, что размер выборки является проблемой здесь, но я надеюсь получить более полное представление о том, как обрабатывать различные типы переменных (то есть, непрерывные, порядковые, номинальные и двоичные) в glmnetрамках, когда результат является двоичным (1 = астма ; 0 = нет астмы).

Таким образом, желает ли кто-нибудь предоставить пример Rсценария вместе с пояснениями к этому фиктивному примеру, используя LASSO с вышеуказанными данными для прогнозирования статуса астмы? Я знаю, что, хотя и очень простой, я, и, вероятно, многие другие, работающие в CV, были бы очень благодарны!


2
Вы можете получить больше удачи, если разместите данные в dputвиде реального объекта R; не заставляйте читателей ставить глазурь сверху, а также печь пирог! Скажем foo, если вы сгенерируете соответствующий фрейм данных в R , то отредактируйте вопрос dput(foo).
Гэвин Симпсон

Спасибо @GavinSimpson! Я обновил пост с фреймом данных, так что, надеюсь, я смогу съесть торт без глазури! :)
Мэтт Райхенбах

2
Используя процентиль ИМТ, вы в некотором смысле бросаете вызов законам физики. Ожирение влияет на людей в соответствии с физическими измерениями (длина, объемы, вес), а не в зависимости от того, сколько людей похожи на текущий предмет, что делает процентилирование.
Фрэнк Харрелл

3
Я согласен, процентиль ИМТ - это не показатель, который я предпочитаю использовать; однако в рекомендациях CDC рекомендуется использовать процентиль ИМТ по сравнению с ИМТ (также весьма сомнительный показатель!) для детей и подростков младше 20 лет, так как он учитывает возраст и пол в дополнение к росту и весу. Все эти переменные и значения данных были придуманы полностью для этого примера. Этот пример не отражает ни одну из моих текущих работ, так как я работаю с большими данными. Я просто хотел увидеть пример glmnetв действии с двоичным результатом.
Мэтт Райхенбах

Подключите здесь пакет Патрика Брити под названием ncvreg, который подходит для моделей линейной и логистической регрессии, штрафуемых MCP, SCAD или LASSO. ( cran.r-project.org/web/packages/ncvreg/index.html )
bdeonovic,

Ответы:


101
library(glmnet)

age     <- c(4, 8, 7, 12, 6, 9, 10, 14, 7) 
gender  <- as.factor(c(1, 0, 1, 1, 1, 0, 1, 0, 0))
bmi_p   <- c(0.86, 0.45, 0.99, 0.84, 0.85, 0.67, 0.91, 0.29, 0.88) 
m_edu   <- as.factor(c(0, 1, 1, 2, 2, 3, 2, 0, 1))
p_edu   <- as.factor(c(0, 2, 2, 2, 2, 3, 2, 0, 0))
f_color <- as.factor(c("blue", "blue", "yellow", "red", "red", "yellow", 
                       "yellow", "red", "yellow"))
asthma <- c(1, 1, 0, 1, 0, 0, 0, 1, 1)

xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[, -1]
x        <- as.matrix(data.frame(age, bmi_p, xfactors))

# Note alpha=1 for lasso only and can blend with ridge penalty down to
# alpha=0 ridge only.
glmmod <- glmnet(x, y=as.factor(asthma), alpha=1, family="binomial")

# Plot variable coefficients vs. shrinkage parameter lambda.
plot(glmmod, xvar="lambda")

введите описание изображения здесь

Категориальные переменные обычно сначала преобразуются в факторы, затем создается фиктивная матрица предикторов и вместе с непрерывными предикторами передается в модель. Имейте в виду, что glmnet использует штрафы как для риджа, так и для лассо, но может быть установлен либо в одиночку.

Некоторые результаты:

# Model shown for lambda up to first 3 selected variables.
# Lambda can have manual tuning grid for wider range.

glmmod
# Call:  glmnet(x = x, y = as.factor(asthma), family = "binomial", alpha = 1) 
# 
#        Df    %Dev   Lambda
#   [1,]  0 0.00000 0.273300
#   [2,]  1 0.01955 0.260900
#   [3,]  1 0.03737 0.249000
#   [4,]  1 0.05362 0.237700
#   [5,]  1 0.06847 0.226900
#   [6,]  1 0.08204 0.216600
#   [7,]  1 0.09445 0.206700
#   [8,]  1 0.10580 0.197300
#   [9,]  1 0.11620 0.188400
#  [10,]  3 0.13120 0.179800
#  [11,]  3 0.15390 0.171600
# ...

Коэффициенты могут быть извлечены из glmmod. Здесь показано с 3 выбранными переменными.

coef(glmmod)[, 10]
#   (Intercept)           age         bmi_p       gender1        m_edu1 
#    0.59445647    0.00000000    0.00000000   -0.01893607    0.00000000 
#        m_edu2        m_edu3        p_edu2        p_edu3    f_colorred 
#    0.00000000    0.00000000   -0.01882883    0.00000000    0.00000000 
# f_coloryellow 
#   -0.77207831 

Наконец, перекрестная проверка также может быть использована для выбора лямбда-выражения.

cv.glmmod <- cv.glmnet(x, y=asthma, alpha=1)
plot(cv.glmmod)

введите описание изображения здесь

(best.lambda <- cv.glmmod$lambda.min)
# [1] 0.2732972

4
это именно то, что я искал +1, единственные вопросы, которые у меня есть: 1) что вы можете сделать с перекрестной проверкой лямбда 0,2732972? и 2) Являются ли выбранные переменные любимым цветом (желтый), пол и образование отца (степень бакалавра) из glmmod? Спасибо!
Мэтт Райхенбах

4
1) Перекрестная проверка используется для выбора лямбда-коэффициентов (при минимальной ошибке). В этом макете нет локального минимума (было также предупреждение, связанное с слишком малым количеством obs); Я бы интерпретировал, что все коэффициенты были сведены к нулю с учетом штрафов за усадку (лучшая модель имеет только перехват), и повторил бы с большим количеством (реальных) наблюдений и, возможно, увеличил бы диапазон лямбда-коэффициентов. 2) Да, в примере, где я выбрал coef (glmmod) [, 10] ... вы выбираете лямбду для модели через CV или интерпретацию результатов. Не могли бы вы пометить как решенные, если вы почувствовали, что я решил ваш вопрос? Благодарю.
погладить

2
Могу ли я спросить, как это обрабатывает f_colorпеременную? Считается ли фактор 1–4 большим шагом, чем 1–2, или все они одинаково взвешены, ненаправлены и категоричны? (Я хочу применить его к анализу со всеми неупорядоченными предикторами.)
beroe

3
Строка xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[,-1]кодирует категориальную переменную f_color (как было объявлено as.factorв предыдущих строках). Следует использовать кодировку фиктивной переменной по умолчанию R, если contrasts.argне указан аргумент. Это означает, что все уровни f_color являются одинаково взвешенными и ненаправленными, за исключением первого, который используется в качестве эталонного класса и включается в точку пересечения.
Алекс

1
@ Алекс не model.matrix(asthma ~ gender + m_edu + p_edu + f_color + age + bmi_p)[, -1]даст тот же результат, что и две строки выше? Зачем использовать дополнительный шаг для объединения непрерывных переменных с data.frame?
Jiggunjer

6

Я буду использовать пакет enet, так как это мой предпочтительный метод. Это немного более гибкий.

install.packages('elasticnet')
library(elasticnet)

age <- c(4,8,7,12,6,9,10,14,7) 
gender <- c(1,0,1,1,1,0,1,0,0)
bmi_p <- c(0.86,0.45,0.99,0.84,0.85,0.67,0.91,0.29,0.88)
m_edu <- c(0,1,1,2,2,3,2,0,1)
p_edu <- c(0,2,2,2,2,3,2,0,0)
#f_color <- c("blue", "blue", "yellow", "red", "red", "yellow", "yellow", "red", "yellow")
f_color <- c(0, 0, 1, 2, 2, 1, 1, 2, 1)
asthma <- c(1,1,0,1,0,0,0,1,1)
pred <- cbind(age, gender, bmi_p, m_edu, p_edu, f_color)



enet(x=pred, y=asthma, lambda=0)

4
спасибо, что поделились elasticnet; однако я не знаю, что делать с выводом из приведенного выше Rсценария. Можете ли вы уточнить? Заранее спасибо!
Мэтт Райхенбах

4

Просто, чтобы расширить на превосходный пример, представленный пат. Первоначальная задача представляла порядковые переменные (m_edu, p_edu) с внутренним порядком между уровнями (0 <1 <2 <3). В первоначальном ответе Пэта я думаю, что они рассматривались как номинальные категориальные переменные без порядка между ними. Я могу ошибаться, но я считаю, что эти переменные должны быть закодированы так, чтобы модель учитывала их внутренний порядок. Если они закодированы как упорядоченные факторы (а не как неупорядоченные факторы, как в ответе Пата), то glmnet дает несколько иные результаты ... Я думаю, что приведенный ниже код правильно включает порядковые переменные в качестве упорядоченных факторов, и это дает немного другие результаты:

library(glmnet)

age     <- c(4, 8, 7, 12, 6, 9, 10, 14, 7) 
gender  <- as.factor(c(1, 0, 1, 1, 1, 0, 1, 0, 0))
bmi_p   <- c(0.86, 0.45, 0.99, 0.84, 0.85, 0.67, 0.91, 0.29, 0.88) 
m_edu   <- factor(c(0, 1, 1, 2, 2, 3, 2, 0, 1), 
                  ordered = TRUE)
p_edu   <- factor(c(0, 2, 2, 2, 2, 3, 2, 0, 0), 
                  levels = c(0, 1, 2, 3), 
                  ordered = TRUE)
f_color <- as.factor(c("blue", "blue", "yellow", "red", "red", 
                       "yellow", "yellow", "red", "yellow"))
asthma <- c(1, 1, 0, 1, 0, 0, 0, 1, 1)

xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[, -1]
x        <- as.matrix(data.frame(age, bmi_p, xfactors))

# Note alpha=1 for lasso only and can blend with ridge penalty down to
# alpha=0 ridge only.
glmmod <- glmnet(x, y=as.factor(asthma), alpha=1, family="binomial")

# Plot variable coefficients vs. shrinkage parameter lambda.
plot(glmmod, xvar="lambda")

введите описание изображения здесь


1
иногда, хороший улов - это был бы более подходящий способ для моделирования переменных уровня образования. Спасибо за ваш вклад.
Мэтт Райхенбах

Как добавить легенду для переменных? Например, что такое красная линия в этом примере?
Jiggunjer
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.