示例:使用glmnet获得二进制结果的LASSO回归


77

我开始与使用的涉猎glmnetLASSO回归那里我感兴趣的结果是二分。我在下面创建了一个小的模拟数据框:

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 (BMI百分位数)-连续
  • m_edu (母亲的最高学历)-顺序(0 =高中以下; 1 =高中文凭; 2 =学士学位; 3 =学士后学位)
  • p_edu (父亲的最高学历)-序数(与m_edu相同)
  • f_color (最喜欢的原色)-标称(“蓝色”,“红色”或“黄色”)
  • asthma (儿童哮喘状态)-二元(1 =哮喘; 0 =无哮喘)

此示例中的目标是利用套索创建一个从6个潜在的预测变量(列表中选择一个模型预测孩子的哮喘状况agegenderbmi_pm_edup_edu,和f_color)。显然样本量是一个问题,但我希望glmnet当结局为二元(1 =哮喘)时,如何在框架内处理不同类型的变量(即,连续,序数,名义和二元)获得更多见解。; 0 =无哮喘)。

因此,是否有人愿意提供样本R脚本以及使用LASSO和上述数据预测哮喘状态的模拟示例的解释?尽管非常基础,但我知道我以及可能还有很多其他简历工作人员,一定会非常感谢!


2
如果您发布的数据作为你可能会得到更多的运气dput了的实际 [R对象; 不要让读者把糖霜放在上面,也不要给你烤蛋糕!例如,如果您在R中生成适当的数据帧foo,则将问题的输出编辑到问题中dput(foo)
加文·辛普森

谢谢@GavinSimpson!我用数据框更新了帖子,所以希望我能吃点蛋糕而不会结霜!:)
马特·赖兴巴赫

2
通过使用BMI百分位数,您在某种意义上是在违背物理定律。肥胖症是根据体格测量(长度,体积,体重)影响个人的,而不是根据与当前受试者相似的个体的多少来衡量的,这就是百分比的作用。
弗兰克·哈雷尔

3
我同意,BMI百分位数不是我更喜欢使用的指标;但是,疾病预防控制中心指南建议,对于身高不到20岁的儿童和青少年,BMI百分比要高于BMI(这也是一个高度可质疑的指标!),因为它考虑了身高和体重以及年龄和性别。在本示例中,所有这些变量和数据值都经过了深思熟虑。该示例未反映我处理大数据时的任何当前工作。我只是想看看一个glmnet具有二进制结果的实际操作示例。
马特·赖兴巴赫

在此处插入Patrick Breheny称为ncvreg的软件包,该软件包适合受MCP,SCAD或LASSO惩罚的线性和逻辑回归模型。(cran.r-project.org/web/packages/ncvreg/index.html
bdeonovic

Answers:


100
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 

最后,交叉验证还可用于选择lambda。

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的交叉验证lambda做什么?和2)从glmmod中选择的变量是喜欢的颜色(黄色),性别和父亲的学历(学士学位)吗?非常感谢!
Matt Reichenbach

4
1)使用交叉验证来选择λ和系数(最小误差)。在此模型中,没有本地分钟(有一个警告也与obs太少有关);我会解释说,所有的系数都随着收缩率的减少而缩小为零(最好的模型只有截距),然后用更多(真实)的观测值重新运行,也许还会增加lambda范围。2)是的,在我选择coef(glmmod)[,10] ...的示例中,您通过CV或结果解释为模型选择了lambda。如果您认为我已经解决了您的问题,您能否标记为已解决?谢谢。
2013年

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前几行中所述)。除非contrasts.arg提供了参数,否则应使用默认的R虚拟变量编码。这意味着,除了第一个用作参考类别并被吸收到截距中的f_color之外,所有f_color的级别都具有相同的加权和方向性。
亚历克斯(Alex)

1
@Alex不会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脚本的输出。你能澄清一下吗?提前致谢!
Matt Reichenbach

4

只是为了扩展pat提供的出色示例。最初的问题是序数变量(m_edu,p_edu),其固有的顺序介于级别之间(0 <1 <2 <3)。在pat的原始答案中,我认为这些被视为名义分类变量,它们之间没有顺序。我可能是错的,但是我相信应该对这些变量进行编码,以使模型尊重其固有顺序。如果将这些编码为有序因子(而不是如pat的答案那样作为无序因子),则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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.