分类模型的效果度量---R语言实现
之前我们介绍了连续型响应变量模型的评估方法(有包括RMSE,R^2之类的评估指标),这次我们介绍一下分类型响应变量模型的评估方法。
目 录
一、分类模型介绍
二、混淆矩阵
三.接受者操作特征(ROC)曲线
四、提升图
五、R语言实现
一、分类模型介绍
分类模型一般产生两种类型的预测。和回归模型类似,分类模型产生一个连续数值预测,该预测通常是概率的形式(即任意样本从属于不同类别的概率预测值均在0到1之间,合计为1)。
二、混淆矩阵
评估分类模型性能一个常用的方法是混淆矩阵(一张简单的观测类和预测类的交叉表)。如表1.1所示:
表1.1 二分类问题的混淆矩阵
Table 1.1 The confusion matrix of binaryclassification problem
预测 |
观测 |
|
发生 |
不发生 |
|
发生 |
TP |
FP |
不发生 |
FN |
TN |
注:表格单元分别代表真阳性(TP),假阳性(FP),假阴性(FN),真阴性(TN)的数量。
模型的准确度稳定在一个水平,通常会在灵敏度和特异度之间做一个权衡。一般而言,增加灵敏度会使特异度下降。能同时反应假阳性率和假阴性率的指标有Youden指数J,Youden指标同时衡量了准确判定观测发生和不发生的样本比率:
接受者操作特征(ROC)曲线是评估二者权衡的一种方法,我将在后面介绍。
灵敏度和特异度均是条件度量,非条件评估阳性预测值PPV回答了”这个样本发生的概率是多少”的问题公式如下(流行度指事件发生的概率):
三.接受者操作特征(ROC)曲线
ROC曲线是在一系列连续数据点情况下,确定一个有效的阈值。横轴是(1-特异度)的一系列连续值,纵轴是对应的灵敏度的值。ROC曲线还可以用于模型的定量评估,一个完美的曲线能完全区分两个类,灵敏度和特异度均为100%,从图上来看,ROC曲线为在(0,0)和(0,1)间的线段,在(0,1)和(1,1)间是常值线段。一个完全无效的模型的ROC曲线会与45°对角线趋近,ROC曲线下面积近视为0.5。为了直观的比较两个或更多不同预测变量集的模型的效果(或相同的模型,不同的调优参数),对比ROC曲线会非常有用。
ROC曲线描述模型的一个优势是,由于它是特异度和灵敏度的一个函数,曲线对类失衡不敏感。使用曲线下的面积(AUC)评估一个模型的不足之处在于它掩盖了一些信息。比如,当比较模型时,没有某条ROC曲线是一致的好于另外一条(曲线存在交叉时)的情况非常常见。用一个量总结曲线将带来信息损失,特别是我们对某特定的区域感兴趣时。此时,我们可以采用ROC曲线下的局部面积来度量模型。
ROC曲线虽然是针对二分类问题定义的,但已将将其扩展用于于3个或更多的类的情况。
四、提升图
提升图是一个评估模型对二分类数据集判定能力的可视化工具。假定有一组使用事件类概率对M个时间进行评分的样本,当样本按照目标类概率进行排序,我们希望目标类样本的排序高于非目标类样本的排序。提升图的作用就是对样本按照评分排序,随着更多样本被评估计算累计目标类样本率。最优的情况是排名最高的M个样本将包含M个事件。当模型无信息时,数据排名最高的X%的样本平均会包含X%目标类样本。提升图展示了通过模型筛选出的目标类的样本数目比随机筛选得到的高多少。构建提升图的步骤:
预测一个模型构建过程中未使用但结果已知的样本集合(即测试集);
确定基准概率,即整个数据集中目标类样本的比例;
对样本按照目标类概率排序;
对每个类概率值高于该概率值的所有样本中目标类样本占总样本的百分比;
将(4)中的百分比除以基准发生比。
五、R语言实现
5.1 建立随机二分类预测模型—随机森林和二次判别模型
install.packages("AppliedPredictiveModeling")
library(AppliedPredictiveModeling)
set.seed(975)
# quadBoundaryFunc函数生成预测变量和输出结果创建模拟数据集
simulatedTrain<-quadBoundaryFunc(500)
simulatedTest<-quadBoundaryFunc(1000)
head(simulatedTest)
#使用随机森林和二次判别模型来拟合数据
install.packages("randomForest")
#拟合随机森林模型
library("randomForest")
rfModel<-randomForest(class~X1+X2,data=simulatedTrain,ntree=2000)
install.packages("MASS")
#拟合二次判别模型
library(MASS)
qdaModel<-qda(class~X1+X2,data=simulatedTrain)
qdaTrainPred<-predict(qdaModel,simulatedTrain)
qdatestPred<-predict(qdaModel,simulatedTest)
names(qdaTrainPred)
head(qdaTrainPred)
simulatedTrain$QDAprob<-qdaTrainPred$posterior[,"Class1"]
simulatedTest$QDAprob<-qdatestPred$posterior[,"Class1"]
#随机森林模型需要两次调用predict函数来获取预测的类别概率和类别
rfTestPred<-predict(rfModel,simulatedTest,type="prob")
simulatedTest$RFprob<-rfTestPred[,"Class1"]
simulatedTest$RFclass<-predict(rfModel,simulatedTest)
5.2 灵敏度和特异度
#将类别1作为感兴趣的类
> library(caret)
> library(ggplot2)
> library(lattice)
>sensitivity(data=simulatedTest$RFclass,
reference=simulatedTest$class,
positive="Class1")
[1] 0.8278867
>specificity(data=simulatedTest$RFclass,
reference=simulatedTest$class,
negative="Class2")
[1] 0.8946396
#假设数据集中类的目标流行度为46%,预测值计算
>posPredValue(data=simulatedTest$RFclass,
reference=simulatedTest$class,
positive="Class1")
[1] 0.8695652
>negPredValue(data=simulatedTest$RFclass,
reference=simulatedTest$class,
positive="Class1")
[1] 0.8596803
#手动设定流行度
>posPredValue(data=simulatedTest$RFclass,
reference=simulatedTest$class,
positive="Class1",
prevalence=0.9)
[1] 0.986056
5.3 混淆矩阵
> library(e1071)
> confusionMatrix(data=simulatedTest$RFclass,
+ reference =simulatedTest$class,
+ positive = "Class1")
ConfusionMatrix and Statistics
Reference
PredictionClass1 Class2
Class1 380 57
Class2 79 484
Accuracy : 0.864
95% CI : (0.8412, 0.8846)
No Information Rate : 0.541
P-Value [Acc > NIR] : < 2e-16
Kappa : 0.7252
Mcnemar's Test P-Value : 0.07174
Sensitivity : 0.8279
Specificity : 0.8946
Pos Pred Value : 0.8696
Neg Pred Value : 0.8597
Prevalence : 0.4590
Detection Rate : 0.3800
Detection Prevalence : 0.4370
BalancedAccuracy : 0.8613
'Positive' Class : Class1
#如果类的数目大于2,则函数会计算其中每一个类对应剩余所有类的灵敏度、特异度和类似的统计量。
5.4 ROC曲线
>library(pROC)
>rocCureve<-roc(response=simulatedTest$class,
+ predictor =simulatedTest$RFprob,
+ #该函数假设类2为感兴趣的事件,因此我们需要互换标签
+ levels =rev(levels(simulatedTest$class)))
>auc(rocCureve)
Area under thecurve: 0.9328
>ci(rocCureve)
95% CI:0.9176-0.948 (DeLong)
>plot(rocCureve,legacy.axes=TRUE)
5.5 提升图
>labs<-c(RFprob=" Random Forest",QDAprob="QuadraticDiscriminant Analysis")
>liftCurve<-lift(class~RFprob+QDAprob,
data=simulatedTest,
labels = labs)
>liftCurve
Call:
lift.formula(x= class ~ RFprob + QDAprob, data = simulatedTest, labels = labs)
Models: Random Forest, Quadratic DiscriminantAnalysis
Event:Class1 (45.9%)
>xyplot(liftCurve,auto.key=list(colSums=2,lines=TRUE,points=FALSE))