Kaggle案例-基于随机森林的心脏病人预测分类
今天给大家分享的一个kaggle案例:基于随机森林模型(RandomForest)的心脏病人预测分类。主要的知识点包含:
- 数据的类型转化
- 随机森林模型建立
- 部分依赖图PDP的绘制和解释
- 机器学习SHAP库的使用和解释
感兴趣的朋友可以参考原notebook地址学习:https://www.kaggle.com/tentotheminus9/what-causes-heart-disease-explaining-the-model
导入库
本案例中涉及到多个不同方向的库:
- 数据预处理
- 多种可视化绘图;尤其是shap的可视化,模型可解释性的模块的使用(后面会专门写这个库)
- 随机森林模型
- 模型评价等
1 | import numpy as np |
数据探索EDA
1、导入数据
2、缺失值情况
数据比较完美,没有任何缺失值!
字段含义
在这里重点介绍下各个字段的含义。Peter近期导出的数据集中字段和原notebook中的字段名字写法稍有差异,已经为大家做了一一对应的关系,下面是具体的中文含义:
- age 年龄
- sex 性别 1=male 0=female
- cp 胸痛类型;4种取值情况
- 1:典型心绞痛
- 2:非典型心绞痛
- 3:非心绞痛
- 4:无症状
- trestbps 静息血压
- chol 血清胆固醇
- fbs 空腹血糖 >120mg/dl :1=true; 0=false
- restecg 静息心电图(值0,1,2)
- thalach 达到的最大心率
- exang 运动诱发的心绞痛(1=yes;0=no)
- oldpeak 相对于休息的运动引起的ST值(ST值与心电图上的位置有关)
- slope 运动高峰ST段的坡度
- 1:upsloping向上倾斜
- 2: flat持平
- 3:downsloping向下倾斜
- ca The number of major vessels(血管) (0-3)
- thal A blood disorder called thalassemia ,一种叫做地中海贫血的血液疾病(3 = normal;6 = fixed defect;;7 = reversable defect)
- target 生病没有(0=no;1=yes)
原notebook中的英文含义;
下面是Peter整理的对应关系。本文中以当前的版本为标准:
字段转化
转化编码
对部分字段进行一一的转化。以sex字段为例:将数据中的0变成female,1变成male
1 | # 1、sex |
字段类型转化
1 | # 指定数据类型 |
生成哑变量
1 | # 生成哑变量 |
随机森林RandomForest
切分数据
1 | # 生成特征变量数据集和因变量数据集 |
建模
1 | rf = RandomForestClassifier(max_depth=5) |
3个重要属性
随机森林中3个重要的属性:
- 查看森林中树的状况:estimators_
- 袋外估计准确率得分:oob_score_,必须是
oob_score
参数选择True的时候才可用 - 变量的重要性:feature_importances_
决策树可视化
在这里我们选择的第二棵树的可视化过程:
1 | # 查看第二棵树的状况 |
1 | # 指定数据类型 |
绘图的具体代码为:
1 | # 绘图显示 |
决策树的可视化过程能够让我们看到具体的分类过程,但是并不能解决哪些特征或者属性比较重要。后面会对部分属性的特征重要性进行探索
模型得分验证
关于混淆矩阵和使用特异性(specificity)以及灵敏度(sensitivity)这两个指标来描述分类器的性能:
1 | # 模型预测 |
绘制ROC曲线
1 | fpr, tpr, thresholds = roc_curve(y_test, y_pred_quant) |
本案例中的ROC曲线值:
1 | auc(fpr, tpr) |
根据一般ROC曲线的评价标准,案例的表现结果还是不错的:
- 0.90 - 1.00 = excellent
- 0.80 - 0.90 = good
- 0.70 - 0.80 = fair
- 0.60 - 0.70 = poor
- 0.50 - 0.60 = fail
补充知识点:分类器的评价指标
考虑一个二分类的情况,类别为1和0,我们将1和0分别作为正类(positive)和负类(negative),根据实际的结果和预测的结果,则最终的结果有4种,表格如下:
常见的评价指标:
1、ACC:classification accuracy,描述分类器的分类准确率
计算公式为:ACC=(TP+TN)/(TP+FP+FN+TN)
2、BER:balanced error rate
计算公式为:BER=1/2*(FPR+FN/(FN+TP))
3、TPR:true positive rate,描述识别出的所有正例占所有正例的比例
计算公式为:TPR=TP/ (TP+ FN)
4、FPR:false positive rate,描述将负例识别为正例的情况占所有负例的比例
计算公式为:FPR= FP / (FP + TN)
5、TNR:true negative rate,描述识别出的负例占所有负例的比例
计算公式为:TNR= TN / (FP + TN)
6、PPV:Positive predictive value
计算公式为:PPV=TP / (TP + FP)
7、NPV:Negative predictive value
计算公式:NPV=TN / (FN + TN)
其中TPR即为敏感度(sensitivity),TNR即为特异度(specificity)。
来自维基百科的经典图形:
可解释性
排列重要性-Permutation Importance
下面的内容是关于机器学习模型的结果可解释性。首先考察的是每个变量对模型的重要性。重点考量的排列重要性Permutation Importance:
部分依赖图( Partial dependence plots ,PDP)
一维PDP
Partial Dependence就是用来解释某个特征和目标值y的关系的,一般是通过画出Partial Dependence Plot(PDP)来体现。 也就是说PDP在X1的值,就是把训练集中第一个变量换成X1之后,原模型预测出来的平均值。
重点:查看单个特征和目标值的关系
字段ca
1 | base_features = df.columns.values.tolist() |
字段age
1 | feat_name = 'age' |
字段oldpeak
1 | feat_name = 'oldpeak' |
2D-PDP图
1 | inter1 = pdp.pdp_interact( |
SHAP可视化
关于SHAP的介绍可以参考文章:https://zhuanlan.zhihu.com/p/83412330
SHAP是Python开发的一个"模型解释"包,可以解释任何机器学习模型的输出。下面SHAP使用的部分功能:
Explainer
在SHAP中进行模型解释之前需要先创建一个explainer,SHAP支持很多类型的explainer,例如deep, gradient, kernel, linear, tree, sampling)。在这个案例我们以tree为例:
1 | # 传入随机森林模型rf |
Feature Importance
取每个特征SHAP值的绝对值的平均值作为该特征的重要性,得到一个标准的条形图(multi-class则生成堆叠的条形图:
summary_plot
summary plot
为每个样本绘制其每个特征的SHAP值,这可以更好地理解整体模式,并允许发现预测异常值。
- 每一行代表一个特征,横坐标为SHAP值
- 一个点代表一个样本,颜色表示特征值的高低(红色高,蓝色低)
个体差异
查看单个病人的不同特征属性对其结果的影响,原文描述为:
Next, let’s pick out individual patients and see how the different variables are affecting their outcomes
1 | def heart_disease_risk_factors(model, patient): |
dependence_plot
为了理解单个feature如何影响模型的输出,我们可以将该feature的SHAP值与数据集中所有样本的feature值进行比较:
多个预测的解释
1 | shap_values = explainer.shap_values(X_train.iloc[:50]) |