所有的模型都是错的,但是有用 🌟
本文介绍如何建立逻辑回归模型进行交通事故预测,并验证了模型的准确度。
1.1 问题描述
基于交通事故相关数据,建立逻辑回归模型,并尽可能使模型的预测准确度达到最高。
使用交通事故发生前的车辆速度变化值、道路流量的变化值和天气的类型(下雨/晴天),建立回归模型对是否发生交通事故(事故/非事故)进行预测。
1.2 数据导入与类型转换
1.2.1 数据读取
原始数据可通过百度网盘下载:数据下载
使用read.csv()
函数读取CSV格式数据
1 | # 读取数据 |
1.2.2 数据类型转化
原始数据类型如下表所示,需要将case
和weather
均转换为无序因子型的数据。
使用factor()
函数实现类型转换,代码实现如下。
1 | ## 将case、weather转换为因子型变量,表示类型 |
2.1 统计冗余数据
首先检查是否含有冗余数据,使用duplicated()
函数对原始数据进行判断,检查发现无重复数据。
1 | ##冗余数据处理 |
2.2 缺失值分析及处理
2.2.1 缺失值分析
在得到数据集后,我们需要观察数据的分布情况,因为很多的模型对缺失值敏感,因此观察是否有缺失值是其中很重要的一个步骤。在正式分析前,我们先通过图形进行对观测字段的缺失情况有一个直观的感受。
使用VIM包中的aggr()
函数对缺失值进行图形探究。
1 | library("VIM") |
aggr()
函数不仅绘制每个变量的缺失值数,还绘制每个变量组合的缺失值数。红色表示缺失,不含缺失值的实例有759个,有缺失值的实例36个;可以看出前4分钟的速度变化值缺失值最多有11个。
使用matrixplot()
函数可以生成每个实例数据的图形。
1 | matrixplot(SourceData) |
此处,数值型数据被重新转换到[0, 1]区间,并用灰度来表示大小:浅色表示值小,深色表示值大。默认缺失值为红色
2.2.2 缺失值插补
对于缺失值的处理方法非常多,例如基于聚类的方法,基于回归的方法,基于均值的方法,其中最简单的方法是直接移除,但是在本文中因为缺失值所占比例较高,直接移除会损失大量观测,因此并不是最合适的方法。在这里,我们使用KNN方法
对缺失值进行填补。
1 | ### 删除(异常值)case为空的记录 |
2.3 异常值分析及处理
使用箱型图对各个单因素变量进行异常值的分析,结果如下,发现并无明显的异常值。
3.1 单变量分析
主要分析各个变量的分布,使用ggplot2
包中的ggplot()
函数绘制各变量的分布统计图如下图。为了简洁,只展示两个变量。
1 | library(ggplot2) |
可以看出,各个变量的分布大致呈负指数分布。
3.2 多变量之间的相关性分析
建模之前首先得检验变量之间的相关性,如果变量之间相关性显著,会影响模型的预测效果。下面通过corrplot
函数,画出各变量之间,包括响应变量与自变量的相关性。由下图可以看出,各变量之间的相关性是非常小的。
1 | library(corrplot) |
4.1 数据集分割
将样本分为按照模型标定:模型校验=7:3的比例划分。nrow(x)
返回x对象的序号,Sample()
函数随机抽取70%的序号,由此完成数据分割。
1 | train <- sample(nrow(nonNA_Data), 0.7*nrow(nonNA_Data)) |
4.2 建立模型
首先将所有自变量都考虑放入模型中,进行Logistic回归建模,模型如下。
1 | fit.full <- glm(case~spd_dif_1min + spd_dif_2min + spd_dif_3min + spd_dif_4m |
从summary()
返回的结果看出,自变量spd_dif_1min
、spd_dif_4min
和vol_dif_1min
对方程的贡献度较为显著,而其他变量对方程的贡献度不显著,去除这些变量,检验新模型是否拟合得好:
1 | fit.reduced <- glm(case ~ spd_dif_1min + spd_dif_4min + vol_dif_1min, data = |
新模型的每个回归系数都非常显著(p<0.05)。由于两模型嵌套(fit.reduced
是fit.full
的一个子集),可以使用anova()
函数对它们进行比较,对于广义线性回归,可用卡方检验。
1 | anova(fit.reduced, fit.full, test = "Chisq") |
结果的卡方值不显著(p=0.1343),表明三个预测变量的新模型与九个完整预测变量的模型拟合程度一样好。添加其他6个变量不会显著提高方程的预测精度,因此可以依据更简单的模型进行解释。
解释模型参数:
1 | exp(coef(fit.reduced)) |
可以看到,1min内速度的变化量增加1个单位,事故发生的优势将乘以1.14708542,同理1min速度、2min流量的变化量增加一个单位,事故发生的优势将乘以1.13031911、1.03248943。
4.3 判定标定模型的拟合优度
通常一个二值分类器可以通过ROC(Receiver Operating Characteristic)曲线和AUC值来评价优劣。
很多二元分类器会产生一个概率预测值,而非仅仅是0-1预测值。我们可以使用某个阈值(例如0.5),以划分哪些预测为1,哪些预测为0。得到二元预测值后,可以构建一个混淆矩阵来评价二元分类器的预测效果。所有的训练数据都会落入这个矩阵中,而对角线上的数字代表了预测正确的数目,即true positive + true negative。同时可以相应算出TPR(真正率或称为敏感度)和TNR(真负率或称为特异度)。我们主观上希望这两个指标越大越好,但可惜二者是一个此消彼涨的关系。除了分类器的训练参数,阈值的选择,也会大大的影响TPR和TNR。有时可以根据具体问题和需要,来选择具体的阈值。
首先使用训练数据集生成概率预测值:
1 | library(pROC) |
需要特别注意的是:type
一定要加,否则计算的最优阈值为负数
下面使用pROC
包计算fit.reduced
模型的拟合优度:
1 | modelroc <- roc(df.train$case,pre) |
从图中可以看出阈值为0.142
时,对应的AUC(Area Under Curve)值为0.762
大于0.7,区分能力可以接受,还有提高的空间。阈值为0.142,对应的敏感度和特异度分别为:0.907
、0.533
。
基于测试集使用建立的模型计算预测值,与真值比较计算出预测的准确率:
1 | # 评估模型的预测效果 |
计算的准确率为 0.62343,准确率不是很高🙈,可以考虑重新设计模型的结构提高准确率。
使用测试数据集计算ROC拟合优度,对于测试数据集AUC为0.765,TPR为0.923,TNR为0.588。
1 | # 测试集的ROC拟合优度 |
参考文献
[1] Kabacoff R , 卡巴科弗, Kabacoff, et al. R 语言实战[M]. 人民邮电出版社, 2013.
[2] 如何在R语言中使用Logistic回归模型
[3] 信用卡评分
[4] logistic回归预测婚姻出轨|R语言