利用算法识别糖尿病患者(R语言实现)

浏览: 4148

本文章是基于R语言一个数据挖掘的案例实现(预测糖尿病),主要内容包括: 数据源介绍——缺失值分析及填补——数据集拆分——建立模型及优化——总结

希望内容对大家有所收获,如有疑问欢迎沟通

数据源介绍

本次数据挖掘的数据来自于印第安人糖尿病数据库,数据源名称PimaIndiansDiabetes2,

可以通过以下途径进行获取

 # 获取数据

library(mlbench)

data(PimaIndiansDiabetes2)

alldata<-PimaIndiansDiabetes2

数据源总共768条记录,9个字段,含有缺失值

Clipboard Image.png


缺失值分析

图是缺失值分布,可以看出缺失值得行数较多,将近50%记录数有缺失,所以不能采取将缺失值全部删除的做法。完整记录数392个,有缺失记录的个数376个,缺失值集中在insulin、triceps这两个字段,两者都缺失的记录数192个,insulin单独缺失的记录数140,glucose单独缺失的记录数只有1个

#缺失值数据探索

library(mice)

#缺失值表格展示

md.pattern(alldata)

 运行结果如下:

Clipboard Image.png

#缺失值可视化

library("VIM")

aggr(alldata,prop=FALSE,numbers = TRUE)

Clipboard Image.png


缺失值填充

KNN插补

首先解释一下为啥用k近邻算法进行插补,因为k近邻算法依据“近朱者赤近墨者黑”的原理,利用缺失值附近的k个已知值维度上的数值进行平均值插补或者距离加权再插补,所以插补的值只和周围特定的值相关,所以一般而言这种插补方法相比较而言比较好

# K近邻算法进行插补

library(DMwR)

#使用knn加权平均算法进行插补计算,其中k是选择紧邻缺失值的10个点进行插补,scale表示对数#据集进行归一化,meth设置计算方法

knndata<-knnImputation(alldata,k= 10,scale = T,meth= "weighAvg")

# 验证一下是否还存在缺失,False表示无缺失值

anyNA(knndata)

# 查看数据集信息

summary(knndata)

Clipboard Image.png


多重插补(mice)

 多重插补(MI)是基于重复模拟的处理缺失值的方法,在面对复杂的缺失问题时,MI是最常选用的方

法,它将从一个包含缺失值的数据集中生成一组完整的数据集(默认是5个)

#使用mice插补方法

library(mice)

# 基于随机森林算法的mice的缺失值插补方法(具体方法可以见R的函数帮助),模型会生出5组缺失值填补数据集

micedata<-mice(alldata,method = 'rf',m=5)

micedata1<-complete(micedata)# 生成完整数据集

# 进行判断是否还有缺失值,false表示无缺失值

anyNA(micedata1)

summary(micedata1)  ##查看数据详情

Clipboard Image.png



注明:这里我们选用第一种knn方法填补的缺失值数据集,下面的建立模型都是使用这个数据集knndata

生成训练集和测试集

我们将对数据集按照变量diabetes等比例抽样,建立训练集(80%)和测试集(20%),这里要使用caret包里面的createDataPartition函数来进行抽样

 #数据集等比例抽取

library(caret)

# 第一个参数是按照哪个变量进行等比例抽取,times表示抽样次数,p表示抽取索引占比,

#list是否生成列表

index1<-createDataPartition(knndata$diabetes,times= 1,p=0.8,list = FALSE)

# 生成训练集和测试数据集

traindata_glm<-knndata[index1,] # 训练集

testdata_glm<-knndata[-index1,] # 测试集

prop.table(table(traindata_glm$diabetes))  #检验抽取后比例

prop.table(table(knndata$diabetes))

执行结果如下

Clipboard Image.png


模型搭建及预测

这里将使用三种数据挖掘的方法来建模,它们分别是广义线性回归(GLM)、随机森林算法(randomForest)以及朴素贝叶斯分类,为什么选用这三种方法呢,首先广义线性回归算法易于理解和操作,方便后期解释,而随机森林算法在常见的决策树、knn、SVM中属于复合模型(决策树模型加强版),所以它模型结果的准确率一般来说都相对于其他几个表现得更好,而朴素贝叶斯分类在分类问题上使用的比较多。

一:变量间相关系数参看

#查看变量间相关性

cor(knndata[c(1:8)])

library(corrgram)

corrgram(knndata,order= TRUE,lower.panel = panel.cor,upper.panel = panel.pie,

         text.panel = panel.txt,main ='knndata数据集变量间的相关性')

执行结果如下,可以看出glucose和insulin,triceps和mass,pregnant和age这三组变量之间相关

系数在0.5-0.7之间,整体而言应该是不存在共线性的干扰,

Clipboard Image.png

Clipboard Image.png


二:使用GLM广义线性回归建模(knndata数据集)

#建立glm回归模型----1

knn_logit<-glm(diabetes~.,data =traindata_glm,family = binomial())

summary(knn_logit)

# 检查变量之间的多重共线性

#这里我们使用统计量VIF(方差膨胀因子)进行检查,一般原则下,

#vif的平方根大于2表明存在多重共线性问题

library(car)

vif(knn_logit)

sqrt(vif(knn_logit))

# type=response 预测结果是概率值

prop<-predict(knn_logit,testdata_glm[c(-9)],type ='response')

par(mfrow=c(2,2))

plot(knn_logit)

logit.pred<-ifelse(prop>0.5,'pos','neg')

# 生成预测结果的混淆矩阵

 table(testdata_glm$diabetes,logit.pred,dnn =c('Real','Predicted'))

运行结果如下图所示:预测的结果准确率79.7%(122/153)presssure、triceps、age这三个变量的F值没有达到显著性相关(p>0.05),说明这些变量对因变量走向影响较小,但是不确定哪些变量一定有用,所以接下来我们使用逐步回归step()函数 

Clipboard Image.png


Clipboard Image.png

#逐步回归方法

knn_step<-step(knn_logit)

knn_logit2<-glm(diabetes~pregnant+mass+pedigree+glucose,data= traindata_glm,family = binomial())

summary(knn_logit2)

prop1<-predict(knn_logit2,testdata_glm[c(-9)],type= 'response')

logit.pred1<-ifelse(prop1>0.5,'pos','neg')

table(testdata_glm$diabetes,logit.pred1,dnn= c('Real','Predicted'))

#对前后两个模型做卡方检验,p>0.05说明新模型更好

anova(knn_logit,knn_logit2,test= 'Chisq')

采用step()函数可以的得知

glm(diabetes~pregnant+mass+pedigree+glucose,data= traindata_glm,family = binomial())

时,AIC的值最小,该模型四个变量都显著相关(p<0.05),而且两个模型的卡方检验值大于0.05,

说明新模型更优利用逐步回归模型之后新模型进行预测,得到的预测结果的准确率78.4%(120/153),

运行结果如下:

Clipboard Image.png


三:利用随机森林算法建模

#基于随机森林算法

library(randomForest)

set.seed(1234)

knn_forest<-randomForest(diabetes~.,data=traindata_glm,na.action=na.roughfix,importance=TRUE)

knn_forest

# 各个变量的重要性

importance(knn_forest,type = 2)

forest.pred<-predict(knn_forest,testdata_glm[c(-9)])#对测试数据集预测

#生出预测结果的混淆矩阵

table(testdata_glm$diabetes,forest.pred,dnn =c('Real','Predicted'))

执行结果如下:

从下面执行的结果可以看出,随机森林每次选择两个变量,建立500个决策树进行建模分析,从变量的重要性来看,glucose、insulin、mass、age四个变量重要性依次从高到低(MeanDecreaseGini系数越高表示越重要)),模型预测结果准确率79%(121/153)


四:利用朴素贝叶斯算法进行预测

##朴素贝叶斯方法实现,通过e1071包里面的navieBayes函数实现

library(e1071)

# 第一步模型搭建

model_naive<-naiveBayes(diabetes~.,data =traindata_glm)

# 利用建立好的模型对结果进行预测

pred_naive<-predict(model_naive,testdata_glm[c(-9)])

# 生成预测结果混淆矩阵,进行输出

result<-table(testdata_glm$diabetes,pred_naive)

(a<-paste0(round(sum(diag(result)*100)/sum(result),1),'% 的预测准确率'))

运行结果如下:

Clipboard Image.png


总结

使用以上三种方法进行建模,然后对预测结果进行比较,其中随机森林算法的预测效果稍微优于其他两者,,所以我会选择随机森林算法来进行建模,尽管三者的准确率都低于80%(而且这是医院数据,用于诊断),考虑到缺失数据将近一半,这样的预测效果目前勉强接受,后期会考虑其他方法来提升预测效果。

广义线性回归预测准确率precision_glm=78.4%

随机森林算法预测准确率precision_RF= 79.1%

朴素贝叶斯算法预测准确率precision_Navie=78.4%


谢谢大家的浏览,如有疑问或者文章有错误的地方,欢迎指正。如果你有更棒的想法欢迎加微信(qq号:546432637)沟通。希望明天都可以进步一点点!!!

推荐 4
本文由 Smurf.... 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

2 个评论

赞,多重插补和相关性分析探索用的不错
谢谢老师哈哈

要回复文章请先登录注册