最常见的机器学习算法登场,临床预测模型中的宠儿
Hi,大家好,我是晨曦
今天这期推文我们依旧聚焦在机器学习,而我们这期的主角就来谈谈大家平时最常见、也是最能用到的模型——线性回归模型
那么,我们就开始吧

晨曦碎碎念系列传送门
线性回归模型背景知识
首先,根据我们前面所掌握的知识,线性回归属于有监督学习中回归的范畴,主要用来解决的是因变量为连续型变量的情况,这个时候我们常常会存在一个疑问:自变量究竟是连续型变量、还是离散型变量、还是数值型变量、还是字符型变量?
这个是很多小伙伴一开始就会出现的疑问,因为很多网络上的教程也把上述的概念给弄混淆了,所以这里我们做一个简单的区分
我们的数据类型包括:字符型、数值型和逻辑型三种,而我们的模型,或者扩展到我们的机器学习算法中,本质上来说其实就是一个个数学公式,所以我们要求的数据类型一定是数值型变量,那么这时候问题来了:为什么有的时候我们把字符型变量作为我们的自变量也是可以进行机器学习的呢?
这是因为我们在输入字符型的时候,我们R语言中的函数对字符型变量进行了重编码,也就是会生成一个虚拟编码,通俗的来讲举个例子就是性别是字符型变量,分为男和女,那么重编码后就变成了1和2
所以,我们这里解决了第一个问题即机器学习中的大多数模型都是通过重编码把字符型变量转化为数值型变量然后进行模型的构建
那么,还有一个问题:线性回归模型中的自变量要求是连续型还是离散型?
这个答案则是都可以,自变量即可以是离散型变量也可以是连续型变量,对于自变量来说,线性回归并没有太多的要求,而主要的要求是在于因变量上
所以我们可以做出总结:
1.针对线性回归(简单线性回归)来说,自变量为数值型变量(离散型&连续型),而因变量则是要求为连续型变量且建议正态分布
这里针对教科书上来说确实是直接要求因变量是符合正态分布的,但是我们往往对我们的因变量直接进行正态性检验发现严重偏离,这个时候其实我们是对于正态性的理解不够,这里晨曦直接说结论,针对因变量直接进行正态性检验是没有意义的,我们应该针对残差来进行正态性检,也就是说你没有必要提前对y做正态检验。而是先回归,然后针对残差做残差诊断,其中就是有一条要去判断残差是否满足正态性,如果残差不满足正态性,则可以说明模型不是最优(所以可以得出结论,针对线性回归来说,大样本(大于30)的前提下因变量、自变量和残差都不是必须符合正态性)
参考教程:数据分析中的第一误区 - 张霜的博文
2.通过构建虚拟变量,机器学习模型可以纳入字符型变量,但是我们要知道,最本质的数学公式接纳的是数值型变量而不是字符型变量,也就是说表面上来看是字符型变量,实际上其内在已经转换成了数值型变量
了解完上述的背景知识,我们就可以进入下面的代码实战部分
代码实战
#准备输入数据#数据中共有六个维度:age(年龄),sex(性别),bmi(肥胖指数),children(孩子数量),smoker(是否吸烟),region(居住地),charges则是当前数据人上年度在医院的花销library(data.table)df <- fread("insurance.txt")
这回可以很清楚的看到,我们的结局变量为连续型变量,这是一个美国病人的医疗费用的数据(医保)
  • age: 这是一个整数,表示主要受益者的年龄(离散型数值型变量)
  • sex: 这是保单持有人的性别,要么是male,要么是female(经过重编码后表面上看是字符型变量,实际上已经变成了数值型变量)
  • bmi: 这是身体质量指数(Body Mass Index,BMI),它提供了一个判断人的体重相对于身高是过重还是偏轻的方法,BMI指数等于体重(公斤)除以身高(米)的平方。一个理想的BMI指数在18.5~24.9的范围内(连续型数值型变量)
  • children: 这是一个整数,表示保险计划中所包括的孩子/受抚养者的数量(离散型数值型变量)
  • smoker: 根据被保险人是否吸烟判断yes或者no(经过重编码后表面上看是字符型变量,实际上已经变成了数值型变量)
  • region: 根据受益人在美国的居住地,分为4个地理区域:northeast、southeast、southwest和northwest
最后的结局变量则是花费,是一个连续型数值型变量
#探索数据str(df)#Classes ‘data.table’ and 'data.frame': 1338 obs. of 7 variables:# $ age : int 19 18 28 33 32 31 46 37 37 60 ...# $ sex : chr "female" "male" "male" "male" ...# $ bmi : num 27.9 33.8 33 22.7 28.9 ...# $ children: int 0 1 3 0 0 0 1 3 2 0 ...# $ smoker : chr "yes" "no" "no" "no" ...# $ region : chr "southwest" "southeast" "southeast" "northwest" ...# $ charges : num 16885 1726 4449 21984 3867 ...# - attr(*, ".internal.selfref")=<externalptr> #观察结局变量的分布
hist(df$charges)#可以很清楚的看到我们的因变量并不符合正态分布,但是我们仍然可以进行线性回归(大样本)
在我们的数据中,绝大多数的个人每年的费用都在0~15000美元,尽管分布的尾部经过直方图的峰部后延伸得很远。即将面临的另一个问题就是回归模型需要每一个特征都是数值型的,而在我们的数据框中,我们有3个字符型的特征。很快,我们会看到R中的线性回归函数如何处理我们的变量。
#建立模型ins_model <- lm(charges~age+children+bmi+sex+smoker+region,data=df)#观察模型ins_model#Call:#lm(formula = charges ~ age + children + bmi + sex + smoker + #    region, data = df)#Coefficients:# (Intercept) age children bmi sexmale # -11938.5 256.9 475.5 339.2 -131.3 # smokeryes regionnorthwest regionsoutheast regionsouthwest # 23848.5 -353.0 -1035.0 -960.1
晨曦解读:
Coefficients:回归系数
Intercept代表着一个截距数值,具体就是当所有自变量为0的时候,因变量是多少,这是一个常数项,这里我们解释一下截距项,其实这个数值没有太多的意义
这个数值往往我们是不看的,因为很难解释,比如说,你无法说年龄为0,这明显是不符合我们客观认知的~
至于其它的变量的回归系数,则表明,当其它变量不变的情况下,这个变量的增加会给因变量带来多大的改变
但是其实如果你试图解析这个数值背后的实际含义会发现比较困难,如果我们的因变量是连续型变量,比如说是房地产价格或者股票价格,那么我们这个回归系数可以解释为当其它自变量不变的情况下,因变量变化的大小,但是这里我们的因变量是一个离散型变量,这个就无法简单的用数值的增加或者降低来解释了,所以我们大体只可以得到一个趋势,但是如果必须要讨论实际的意义可能并不是一个简单的事情
这里我们又要纠正一个问题:单纯的线性回归适用于因变量为连续型变量的情况下,而如果我们的因变量是离散型变量,这个时候我们需要使用的广义线性模型中的Logistic回归模型
但是,如果因变量是连续型正整数,而且发生的频率不是很高,这个时候我们可以使用广义线性模型中的泊松回归(适用条件为因变量是连续型正整数且发生的频率不是很高)
同时,各位小伙伴可能注意到,在我们的模型公式中,我们仅指定了6个变量,但是输出时,除了截距项外,却输出了8个系数
之所以发生这种情况,是因为lm()函数自动将一种称为虚拟编码(dummy coding)的技术应用于模型所包含的每一个因子类型的变量中。当添加一个虚拟编码的变量到回归模型中时,一个类别总是被排除在外作为参照类别
然后,估计的系数就是相对于参照类别解释的。在我们的模型中,R自动保留sex female、smoker no和region northeast变量,使东北地区的女性非吸烟者作为参照组。因此,相对于女性来说,男性每年的医疗费用要少$131.30;吸烟者平均多花费$23848.50,远超过非吸烟者。此外,模型中另外3个地区的系数是负的,这意味着东北地区倾向于具有最高的平均医疗费用。
#评估模型性能#通过在R命令行输入ins_model,可以获得参数的估计值,它们告诉我们关于自变量是如何与因变量相关联的。但是它们根本没有告诉我们用该模型来拟合数据有多好。为了评估模型的性能,可以使用summary()命令来分析所存储的回归模型:summary(ins_model)#Call:#lm(formula = charges ~ age + children + bmi + sex + smoker + #    region, data = df)#Residuals:# Min 1Q Median 3Q Max #-11304.9  -2848.1   -982.1   1393.9  29992.8 #Coefficients:# Estimate Std. Error t value Pr(>|t|) #(Intercept) -11938.5 987.8 -12.086 < 2e-16 ***#age 256.9 11.9 21.587 < 2e-16 ***#children 475.5 137.8 3.451 0.000577 ***#bmi 339.2 28.6 11.860 < 2e-16 ***#sexmale -131.3 332.9 -0.394 0.693348 #smokeryes 23848.5 413.1 57.723 < 2e-16 ***#regionnorthwest -353.0 476.3 -0.741 0.458769 #regionsoutheast -1035.0 478.7 -2.162 0.030782 * #regionsouthwest -960.0 477.9 -2.009 0.044765 * #---#Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1#Residual standard error: 6062 on 1329 degrees of freedom#Multiple R-squared: 0.7509, Adjusted R-squared: 0.7494 #F-statistic: 500.8 on 8 and 1329 DF, p-value: < 2.2e-16
我们来解析一下这个模型的参数含义:
标志①:残差部分:提供了我们预测中的错误的汇总统计数据,其中一些显然是相当可观的。由于残差等于真值减去预测值,最大误差29992.8表明,该模型至少有一次观测的预测费用低了近30,000美元。另一方面,50%的误差在1Q和3Q值(第一和第三个四分之一)内,因此大部分预测在真实价值的2850美元和真实价值的1400美元之间。
标志②:星形(例如“***”)表示模型中每个特征的预测能力。显著性水平(如符号所列出的)提供了一个关于给定估计值的真实系数为零的可能性的度量。三颗星的存在表明其显著性水平为0, 这意味着该特征极不太可能与因变量无关。一种常见的做法是使用0.05的显著性水平来表示一个具有统计学意义的变量
标志③:多重R平方值(也称为决定系数)提供了一个度量,以衡量我们的模型作为一个整体如何解释因变量的值。与相关系数相似,值越接近1.0,模型越好地解释数据。由于调整后r平方值为0.7494,我们知道因变量的近75%的变化可以用我们的模型来解释
鉴于前三个性能指标,我们的模型表现得相当好。真实世界数据的回归模型具有相当低的r平方值并不罕见;0.75的值实际上是相当好的
接下来,我们来改进我们的模型
回归建模和其他机器学习方法之间的一个关键区别是,回归通常会将特征选择和模型的权利留给个人。因此,如果我们有关于一个特性如何与结果相关的主题知识,我们就可以使用这些信息来告知模型应该纳入何种变量,并潜在地提高模型的性能
1
第一种方法:Model specification – adding non-linear relationships
首先,我们先来解释一下这个概念
在线性回归中,假设自变量与因变量之间的关系是线性的,但这可能并不一定是正确的。例如,年龄对医疗支出的影响可能并非在所有年龄值中都保持不变;对于最年长的人群来说,治疗可能会变得不成比例地昂贵
如果你还记得,一个典型的回归方程遵循类似的形式:
为了解释一个非线性关系,我们可以在回归模型中添加一个高阶项,将该模型视为一个多项式。实际上,我们将建模一个这样的关系
这两种模型之间的区别在于,将估计一个单独的beta,其目的是捕获x平方项的影响。这使得年龄的影响可以作为年龄平方的函数来衡量
要将非线性年龄添加到模型中,我们只需要创建一个新的变量
df$age2 <- df$age^2
然后,当我们生成改进的模型时,我们将把年龄和年龄的平方添加到lm()公式中,例如:charges ~ age + age2
2
第二种方法:编码我们的自变量
我们在研究中发现,只有BMI大于30才会对患者造成伤害,或者说只有达到某一个阈值才会对我们的因变量造成影响
然后我们可以使用下面的代码对我们的自变量进行编码,我们编码的目的在于明确了BMI阈值上下对结局变量的影响
df$bmi30 <- ifelse(df$bmi >= 30, 1, 0)
然后,我们可以将bmi30变量纳入我们改进的模型中,要么替换原始的bmi变量,要么再添加,这取决于我们是否认为肥胖的影响是除了单独的BMI效应之外发生的。如果没有充分的理由不这样做,我们将在最终的模型中包括这两者。
如果您在决定是否包含一个变量时遇到困难,一种常见的做法是包含该变量并检查其显著性水平。然后,如果这个变量没有统计学意义,你就有证据支持在未来排除它
接下来,我们探讨如何给模型添加交互项
到目前为止,我们只考虑了每个特性对结果的贡献。如果某些特征对因变量有综合影响呢?例如,吸烟和肥胖可能分别产生有害影响,但我们有理由假设,它们的综合影响可能比两者单独的总和更糟糕
当两个特性具有组合效果时,这就被称为交互作用。如果我们怀疑两个变量有交互作用,我们可以通过在模型中添加它们的交互作用来验证这个假设。交互效果可以使用R公式语法来指定:charges ~ bmi30*smoker
上面的代码展开就是:charges ~ bmi30 + smokeryes + bmi30:smokeryes
然后让我们整体回顾一下,我们得到线性模型后,我们可以做哪些改动
1.添加非线性变量
2.编码自变量
3.添加交互项
然后我们就可以开始重新训练我们的模型
ins_model2 <- lm(charges ~ age + age2 + children + bmi + sex +bmi30*smoker + region, data = df)summary(ins_model2)#如果我们确定一个变量是有意义的,那么纳入的变量越多,模型一定是越准确的
相对于我们的第一个模型,r-平方值已经从0.75提高到约0.87。我们的模型现在解释了87%的医疗费用的变化
此外,我们关于模型函数形式的理论似乎得到了验证。高阶年龄项具有统计学意义,肥胖指标bmi30如此
肥胖和吸烟之间的相互作用表明了巨大的影响;除了单独吸烟的费用增加超过13,404美元之外,肥胖吸烟者每年花费19,810美元。这可能表明,吸烟会加剧与肥胖相关的疾病
到这里难道就结束了?不,显然我们依旧还有一些没有弄明白的问题,我们接下来继续进行探索
我们仔细看下面这三个模型,这里我们常会有一个疑问:有了年龄的平方后我们是否还需要纳入单纯的年龄变量以及我们已经重编码了BMI,我们是否还需要纳入没有重编码的BMI变量
#模型一ins_model2 <- lm(charges ~ age + age2 + children + bmi + sex +bmi30*smoker + region, data = df)#Multiple R-squared:  0.8664#模型二ins_model2 <- lm(charges ~ age2 + children + bmi + sex + bmi30*smoker + region, data = df)#Multiple R-squared:  0.8664#模型三ins_model2 <- lm(charges ~ age+age2 + children + sex + bmi30*smoker + region, data = df)#Multiple R-squared: 0.8652
这里我们依旧是通过实践来解答上述的问题,我们可以很清楚的看到去掉单纯的age变量和加入age变量,并没有对模型的决定系数产生影响,但是,我们根据最原始的数学公式,则是要求我们加入age平方前的变量,所以这里我们给的建议则是,添加上平方前的变量,即age和age的平方都纳入我们的自变量,而针对BMI重编码我们也可以得出结论,即添加上BMI会对模型的决定系数起到的一定性的提高
至此,我们线性回归模型相关的内容就给大家介绍到了这里,相信大家通过本期推文的学习,应该可以掌握线性回归模型,至于后续的一些细节,大家可以持续关注挑圈联靠公众号后续内容,会给大家带来更多机器学习相关的内容
那么,这期推文就到这里啦
参考书籍:Machine Learning with R
我是晨曦,我们下期再见~
晨曦单细胞笔记系列传送门
晨曦从零开始学画图系列传送门
晨曦单细胞数据库系列传送门

END

撰文丨晨   曦
排版丨四金兄
主编丨小雪球
欢迎大家关注解螺旋生信频道-挑圈联靠公号~
继续阅读
阅读原文