R教程中的Logistic回归
发现所有关于逻辑回归:它与线性回归有什么不同,如何用glm()函数和其他函数来拟合和评估这些模型。
逻辑回归是机器学习从统计领域借鉴的又一技术。这是一种用一个或多个解释变量建模二项结果的强大统计方法。它通过使用逻辑函数估计概率来测量分类因变量和一个或多个自变量之间的关系,逻辑函数是累积逻辑分布。
这个R教程将指导您完成逻辑回归的简单执行:
-
您将首先探讨逻辑回归背后的理论:您将进一步了解线性回归和逻辑回归模型的差异。你还会发现多项式和有序逻辑回归。
-
接下来,您将解决R中的逻辑回归:您不仅会探索数据集,还会使用 R中强大的
glm()
函数拟合逻辑回归模型,评估结果并解决过拟合问题。
提示:如果您有兴趣将线性回归技能提升到新的水平,请考虑DataCamp的多元回归和逻辑回归课程!
回归分析:简介
正如名称所表明的那样,逻辑回归是一种回归分析技术。回归分析是一组统计过程,可以用来估计变量之间的关系。更具体地说,您使用这套技术来模拟和分析因变量与一个或多个独立变量之间的关系。回归分析可帮助您了解当自变量之一被调整并且其他变量保持固定时,因变量的典型值如何变化。
正如你已经读过的,有各种回归技术。您可以通过查看三个方面来区分它们:自变量的数量,因变量的类型和回归线的形状。
线性回归
线性回归是最广为人知的建模技术之一。简而言之,它使您可以使用线性关系来预测给定值为$ X $的直线的$ Y $的(平均)数值。这条线被称为“回归线”。ÿX
因此,线性回归模型是$ y = ax + b $。该模型假定响应变量$ y $是定量的。但是,在许多情况下,响应变量是定性的,换句话说,是分类的。例如,性别是定性的,具有男性或女性的价值。ÿ= a x + bÿ
预测观测的定性响应可以称为对观测进行分类,因为它涉及将观测分配给类别或类别。另一方面,通常用于分类的方法首先预测定性变量的每个类别的概率,作为进行分类的基础。
线性回归不能预测概率。例如,如果您使用线性回归来模拟二元响应变量,则所得到的模型可能不会将预测的Y值限制在0和1之内。这里是逻辑回归发挥作用的地方,其中您得到的概率分数反映了事件发生。
Logistic回归
逻辑回归是分类技术的一个实例,您可以使用它来预测定性响应。更具体地说,逻辑回归模型是$ gender $属于特定类别的概率。GÈ Ñ dË [R
这意味着,如果您尝试进行性别分类,那么响应$ gender $属于两个类别之一,或者,您将使用逻辑回归模型来估计$ gender $属于特定类别的概率。GÈ Ñ dË [Rmale
female
GÈ Ñ dË [R
例如,给定$ longhair $的$ gender $的概率可写为:GÈ Ñ dË [R升Ò Ñ 克h a i r
Pr (gÈ Ñ de r = fË 中号一升ë | 升Ò Ñ 克h a i r )
$ Pr(gender = female | longhair)$(缩写为$ p(longhair)$)的值将介于0和1之间。然后,对于任何给定的$ long hair $值,可以预测$ gender $。Pr (gÈ Ñ de r = fË 中号一升ë | 升Ò Ñ 克h a i r )p (l o n gh a i r )升Ò Ñ 克h a i rGÈ Ñ dË [R。
给定$ X $作为解释变量,$ Y $作为响应变量,你应该如何建模$ p(X)= Pr(Y = 1 | X)$和$ X $?之间的关系。线性回归模型将这些概率表示为:Xÿp (X)= Pr (Y= 1 | X)X
p(X)= β 0 + β 1 X
这种方法的问题是,任何时候一条直线适合编码为$ 0 $或$ 1 $的二元响应,原则上我们可以总是预测$ p(X)<0 $对于$ X $的某些值和其他$ p(X)> 1 $。01p (X)< 0Xp (X)> 1
为了避免这个问题,您可以使用logistic函数来模拟$ p(X)$,该函数为$ X $的所有值提供$ 0 $和$ 1 $之间的输出:p (X)01X
p (X)= eβ0+ β1X1 + eβ0+ β1X
逻辑函数将总是产生一个S形曲线,所以不管$ X $的值如何,我们都会得到一个合理的预测。 X
上面的等式也可以被重新定义为:
p (X)1 – p (X)= eβ0+ β1X
数量$$ \ frac {p(X)} {1 – p(X)} $$被称为优势比,可以取$ 0 $到$ \ infty $之间的任何值。比值比接近$ 0 $和$ \ infty $的值分别表示$ p(X)$的概率非常低和非常高。
p (X)1 – p (X)
0∞0∞p (X)
通过从上面的公式得到双方的对数,您会得到:
l o g(p (X)1 – p (X))= β0+ β1X
左侧称为logit。在逻辑回归模型,增加X由一个单元改变由分对数β 0。该量p(X)的变化,由于在一个单位改变X将取决于当前值X。但不管值的X,如果β 1为正,则提高X将随相关联的p(X),并且如果β 1为负,那么增加X将随着相关联p(X)。
系数β 0和β 1是未知的,必须基于现有的训练数据来估计。对于逻辑回归,您可以使用最大可能性,一种强大的统计技术。我们再回顾一下您的性别分类示例。
您寻求估计β 0和β 1,从而堵塞这些估计到模型p(X)产生的数接近1谁是女性的所有个人,以及一些接近0谁是不是所有的人。
这种直觉可以用一个称为似然函数的数学方程来形式化:
升(β 0, β 1)= p(X)(1 - p(X))
估计β 0和β 1被选择以最大化该似然函数。一旦估计了系数,就可以简单地计算在发生$ long头发$的情况下为$ female $的概率。总体而言,最大可能性是拟合非线性模型的一种非常好的方法。FË 中号一升ë升Ò Ñ 克h a i r
多项Logistic回归
到目前为止,本教程仅着重于二项Logistic回归,因为您将实例分类为男性或女性。多项Logistic回归模型是二项逻辑回归模型的简单扩展,当探索变量具有两个以上名义(无序)类别时,您使用该模型。
在多项式逻辑回归中,探索性变量被虚拟编码成多个1/0变量。除了一个类别之外,所有类别都有一个变量,因此如果有M个类别,则会有$ M-1 $个虚拟变量。每个类别的虚拟变量的类别值为1,其他值为0。一个类别,即参考类别,不需要自己的虚拟变量,因为它由所有其他变量唯一标识为0。中号– 1
然后多元逻辑回归估计每个这些虚拟变量的单独二元逻辑回归模型。结果是$ M-1 $二元逻辑回归模型。与参考类别相比,每个模型都传达了预测因子对该类别成功概率的影响。中号– 1
序数Logistic回归
除了多项逻辑回归之外,您还有序逻辑回归,这是二项物流回归的另一个扩展。序数回归用于预测具有“有序”多个类别和自变量的因变量。你已经看到了这种逻辑回归的名称,因为“序数”是指“类别的顺序”。
换句话说,它用于促进因变量(具有多个有序水平)与一个或多个独立变量的相互作用。
例如,您正在进行客户访谈,以评估他们对我们新发布产品的满意度。您有责任向被访者提问,他们的答案在$满意$或$不满意$之间。为了很好地概括答案,您在回答中添加了级别,例如$ Very Unsisfactory $,$ Unsatisfactory $,$ Neutral $,$ Satisfactory $,$ Very Satisfactory $。这有助于您观察类别中的自然顺序。小号a t i s fa c t o r yüÑ 小号一吨我小号˚Fa c t o r yVe r yüÑ 小号一吨我小号˚Fa c t o r yüÑ 小号一吨我小号˚Fa c t o r yñè ù 吨ř 一个升小号a t i s fa c t o r yVe r y小号a t i s fa c t o r y
R中的Logistic回归 glm
在本节中,您将学习一个二元逻辑回归的例子,您将使用ISLR
包来处理这个包,它将为您提供数据集,而glm()
通常用于拟合广义线性模型的函数将会用于拟合逻辑回归模型。
加载数据中
首先要做的是安装并加载ISLR
包中包含您要使用的所有数据集的包。
require(ISLR)## Loading required package: ISLR## Warning: package 'ISLR' was built under R version 3.3.2
在本教程中,您将使用 RStudio中的Smarket数据集。数据集显示2001年至2005年标准普尔500指数的每日回报率。
探索数据
我们来探讨一下。names()
对于查看数据框上的内容很有用,可以看到head()
前几行,并且summary()
也很有用。
names(Smarket)## [1] "Year" "Lag1" "Lag2" "Lag3" "Lag4" "Lag5" ## [7] "Volume" "Today" "Direction"head(Smarket)## Year Lag1 Lag2 Lag3 Lag4 Lag5 Volume Today Direction## 1 2001 0.381 -0.192 -2.624 -1.055 5.010 1.1913 0.959 Up## 2 2001 0.959 0.381 -0.192 -2.624 -1.055 1.2965 1.032 Up## 3 2001 1.032 0.959 0.381 -0.192 -2.624 1.4112 -0.623 Down## 4 2001 -0.623 1.032 0.959 0.381 -0.192 1.2760 0.614 Up## 5 2001 0.614 -0.623 1.032 0.959 0.381 1.2057 0.213 Up## 6 2001 0.213 0.614 -0.623 1.032 0.959 1.3491 1.392 Upsummary(Smarket)## Year Lag1 Lag2 ## Min. :2001 Min. :-4.922000 Min. :-4.922000 ## 1st Qu.:2002 1st Qu.:-0.639500 1st Qu.:-0.639500 ## Median :2003 Median : 0.039000 Median : 0.039000 ## Mean :2003 Mean : 0.003834 Mean : 0.003919 ## 3rd Qu.:2004 3rd Qu.: 0.596750 3rd Qu.: 0.596750 ## Max. :2005 Max. : 5.733000 Max. : 5.733000 ## Lag3 Lag4 Lag5 ## Min. :-4.922000 Min. :-4.922000 Min. :-4.92200 ## 1st Qu.:-0.640000 1st Qu.:-0.640000 1st Qu.:-0.64000 ## Median : 0.038500 Median : 0.038500 Median : 0.03850 ## Mean : 0.001716 Mean : 0.001636 Mean : 0.00561 ## 3rd Qu.: 0.596750 3rd Qu.: 0.596750 3rd Qu.: 0.59700 ## Max. : 5.733000 Max. : 5.733000 Max. : 5.73300 ## Volume Today Direction ## Min. :0.3561 Min. :-4.922000 Down:602 ## 1st Qu.:1.2574 1st Qu.:-0.639500 Up :648 ## Median :1.4229 Median : 0.038500 ## Mean :1.4783 Mean : 0.003138 ## 3rd Qu.:1.6417 3rd Qu.: 0.596750 ## Max. :3.1525 Max. : 5.733000
该summary()
功能为您提供Smarket数据框中每个变量的简单摘要。你可以看到有一些滞后,成交量,今天的价格和方向。您可以Direction
用作可回应的回应,因为这表明市场自前一天起上涨或下跌。
可视化数据
数据可视化可能是对数据进行总结和了解更多信息的最快和最有用的方式。您将首先单独探索数字变量。
直方图提供了一个数字变量拆分为分箱的条形图,高度显示了落入每个分箱的实例数量。它们对于获取属性分布的指示很有用。
par(mfrow=c(1,8))for(i in 1:8) { hist(Smarket[,i], main=names(Smarket)[i])}
这是非常难以看到的,但大多数变量显示高斯或双重高斯分布。
您可以使用盒子和胡须图以不同的方式查看数据的分布。盒子可以捕获中间50%的数据,线条显示中位数,图中的胡须显示合理的数据范围。晶须外的任何点都是离群值的好候选者。
par(mfrow=c(1,8))for(i in 1:8) { boxplot(Smarket[,i], main=names(Smarket)[i])}
你可以看到Lag
s和Today
所有的都有相似的范围。否则,没有任何异常值的迹象。
缺失数据对建模有很大影响。因此,您可以使用缺少的图来快速了解数据集中缺失数据的数量。x轴显示属性,y轴显示实例。水平线表示实例丢失的数据,垂直块表示属性丢失的数据。
library(Amelia)library(mlbench)missmap(Smarket, col=c("blue", "red"), legend=FALSE)
好吧,对我来说很幸运!这个数据集中没有丢失的数据!
我们开始计算每对数字变量之间的相关性。这些成对相关性可以绘制在相关矩阵图中以给出关于哪些变量一起改变的想法。
library(corrplot)correlations <- cor(Smarket[,1:8])corrplot(correlations, method="circle")
在蓝色表示正相关和红色负的情况下使用点表示。点越大,相关性越大。你可以看到矩阵是对称的,对角线是完全正相关的,因为它显示了每个变量与自身的相关性。不幸的是,这些变量中没有一个与另一个相关。
我们来做一个数据图。有一个pairs()
函数将变量绘制Smarket
成散点图矩阵。在这种情况下,Direction
你的二元响应是颜色指示器:
pairs(Smarket, col=Smarket$Direction)
看起来这里没有太多相关性。类变量从变量派生Today
,所以Up
并Down
似乎使一个部门。除此之外,没有太多的事情发生。
我们来看看按Direction
值分解的每个变量的密度分布。像上面的散点图矩阵,通过方向上的密度图可以帮助看到的分离Up
和Down
。它也可以帮助理解Direction
变量值的重叠。
library(caret)x <- Smarket[,1:8]y <- Smarket[,9]scales <- list(x=list(relation="free"), y=list(relation="free"))featurePlot(x=x, y=y, plot="density", scales=scales)
您可以看到Direction
所有这些变量的值都重叠,这意味着很难预测Up
或Down
仅基于一个或两个变量。
建立Logistic回归模型
现在你调用glm.fit()
函数。你传递给这个函数的第一个参数是一个R公式。在这种情况下,该公式表明 Direction
是响应,而Lag
和Volume
变量是预测因子。正如您在介绍中看到的,glm
通常用于拟合广义线性模型。
但是,在这种情况下,您需要明确说明您想要适合逻辑回归模型。你可以通过设置family
参数来解决这个问题binomial
。这样,你告诉glm()
把合适的逻辑回归模型,而不是其他许多其他模型之一,可以适应glm
。
# Logistics Regressionglm.fit <- glm(Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + Volume, data = Smarket, family = binomial)
接下来,你可以做一个summary()
,它告诉你有关适合的一些事情:
summary(glm.fit)## ## Call:## glm(formula = Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + ## Volume, family = binomial, data = Smarket)## ## Deviance Residuals: ## Min 1Q Median 3Q Max ## -1.446 -1.203 1.065 1.145 1.326 ## ## Coefficients:## Estimate Std. Error z value Pr(>|z|)## (Intercept) -0.126000 0.240736 -0.523 0.601## Lag1 -0.073074 0.050167 -1.457 0.145## Lag2 -0.042301 0.050086 -0.845 0.398## Lag3 0.011085 0.049939 0.222 0.824## Lag4 0.009359 0.049974 0.187 0.851## Lag5 0.010313 0.049511 0.208 0.835## Volume 0.135441 0.158360 0.855 0.392## ## (Dispersion parameter for binomial family taken to be 1)## ## Null deviance: 1731.2 on 1249 degrees of freedom## Residual deviance: 1727.6 on 1243 degrees of freedom## AIC: 1741.6## ## Number of Fisher Scoring iterations: 3
如您所见,summary()
返回每个系数的估计值,标准误差,z分数和p值。看起来这些系数都不重要。它也为您提供无效偏差(偏差仅用于平均值)和剩余偏差(模型与所有预测变量的偏差)。2和6个自由度之间的差别非常小。
您分配的结果predict()
的glm.fit()
到glm.probs
,用类型等于响应。这将对您用来拟合模型的训练数据进行预测,并给出拟合概率的向量。
你看前5个概率,他们非常接近50%:
glm.probs <- predict(glm.fit,type = "response")glm.probs[1:5]## 1 2 3 4 5 ## 0.5070841 0.4814679 0.4811388 0.5152224 0.5107812
现在我要基于滞后和其他预测因素来预测市场是否会涨跌。特别是,我将通过将阈值设置为0.5来将概率转换为分类。为了这样做,我使用了一个ifelse()
命令。
glm.pred <- ifelse(glm.probs > 0.5, "Up", "Down")
glm.pred
是trues和falses的向量。如果glm.probs
大于0.5,则glm.pred
调用"Up"
; 否则,它会调用"False"
。
在这里,你附上数据框Smarket
并制作一个表格glm.pred
,这是上一个方向的起伏。你也取这些的意思。
attach(Smarket)table(glm.pred,Direction)## Direction## glm.pred Down Up## Down 145 141## Up 457 507mean(glm.pred == Direction)## [1] 0.5216
从表格中,对角线上的实例是您得到正确分类的位置,而对角线则是您犯错的地方。看起来你犯了很多错误。平均值为0.52。
创建培训和测试样本
你怎么能做得更好?将数据分成训练集和测试集是一个很好的策略。
# Make training and test settrain = Year<2005glm.fit <- glm(Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + Volume, data = Smarket, family = binomial, subset = train)glm.probs <- predict(glm.fit, newdata = Smarket[!train,], type = "response")glm.pred <- ifelse(glm.probs > 0.5, "Up", "Down")
我们来仔细看看这个代码块:
-
train
等于2005年以下。在2005年以下的全年,你会得到一个true
; 否则,我会得到一个false
。 -
然后你重新调整模型
glm.fit()
,除了子集等于'训练',这意味着它适合仅仅是2005年的数据。 -
然后,您使用的
predict()
再次功能glm.probs
,以在一年大于或等于剩余数据预测到2005年。对于新的数据,你给它Smarket,通过索引!train
(!train
是true
如果年份大于或等于2005)。您可以设置type
到"response"
预测的概率。 -
最后,
ifelse()
再次使用该函数来glm.pred
进行制作Up
和Down
变化。
您现在创建一个新变量来存储测试数据的新子集并调用它Direction.2005
。响应变量仍然是Direction
。你制作一张表并计算这个新测试集的平均值:
Direction.2005 = Smarket$Direction[!train]table(glm.pred, Direction.2005)## Direction.2005## glm.pred Down Up## Down 77 97## Up 34 44mean(glm.pred == Direction.2005)## [1] 0.4801587
哈,你做得比前一种情况更糟。这怎么会发生?
解决过度配合
那么,你可能已经装备了数据。为了解决这个问题,你要适应较小的型号和使用Lag1
,Lag2
,Lag3
作为预测,从而留下了所有其他变量。其余的代码是一样的。
# Fit a smaller modelglm.fit = glm(Direction ~ Lag1 + Lag2 + Lag3, data = Smarket, family = binomial, subset = train)glm.probs = predict(glm.fit, newdata = Smarket[!train,], type = "response")glm.pred = ifelse(glm.probs > 0.5, "Up", "Down")table(glm.pred, Direction.2005)## Direction.2005## glm.pred Down Up## Down 39 31## Up 72 110mean(glm.pred == Direction.2005)## [1] 0.5912698
那么,你的分类率是59%,不算太差。使用较小的模型似乎表现更好。
最后,你会做summary()
的glm.fit
,看看是否有任何变化signficant。
summary(glm.fit)## ## Call:## glm(formula = Direction ~ Lag1 + Lag2 + Lag3, family = binomial, ## data = Smarket, subset = train)## ## Deviance Residuals: ## Min 1Q Median 3Q Max ## -1.338 -1.189 1.072 1.163 1.335 ## ## Coefficients:## Estimate Std. Error z value Pr(>|z|)## (Intercept) 0.032230 0.063377 0.509 0.611## Lag1 -0.055523 0.051709 -1.074 0.283## Lag2 -0.044300 0.051674 -0.857 0.391## Lag3 0.008815 0.051495 0.171 0.864## ## (Dispersion parameter for binomial family taken to be 1)## ## Null deviance: 1383.3 on 997 degrees of freedom## Residual deviance: 1381.4 on 994 degrees of freedom## AIC: 1389.4## ## Number of Fisher Scoring iterations: 3
没有什么变得显着,至少P值更好,表明对性能预测的增加。
结论
所以这是R教程的结尾,它使用glm()
函数和将系列设置为二项式来构建逻辑回归模型。glm()
不假设依赖变量和自变量之间的线性关系。然而,它假定链接函数和logit模型中的自变量之间存在线性关系,我希望你已经学到了一些有价值的东西!