1.评估分类方法的性能

  • 拥有能够度量实用性而不是原始准确度的模型性能评价方法是至关重要的。
  • 3种数据类型评价分类器:真实的分类值;预测的分类值;预测的估计概率。之前的分类算法案例只用了前2种。
  • 对于单一预测类别,可将predict函数设定为class类型,如果要得到预测的概率,可设为为prob、posterior、raw或probability等类型。predict大部分情况下返回对结果不同水平的预测概率。
#朴素贝斯分类的预测概率
predicted_prob=predict(model,test_data,type="raw")
#决策树C5.0分类器
predicted_proc=predict(model,test_data,type="prob")
  • 一般而言,预测值和真实值都是同一类时的预测概率会比较极端(接近0或1),但总有一些相反的,概率值介于中间,这时判断模型是否可用,可通过对测试数据应用各种误差度量的方法。
# obtain the predicted probabilities
sms_test_prob <- predict(sms_classifier, sms_test, type = "raw")
head(sms_test_prob)

1.1 混淆矩阵

混淆矩阵是一张二维表(第一维是所有可能的预测类别,第二维是真实的类别),按照预测值是否匹配真实值来对预测值进行分类。二值分类是2X2混淆矩阵,三值分类模型是3X3混淆矩阵。

  • 阳性和阴性:相对的概念,无任何隐含的价值判断。一般将感兴趣的类别(或目标)设为阳性。

  • 度量性能:准确度(成功率)

  • 错误率



    gmodels::CrossTable代码示例:

数据下载链接: https://pan.baidu.com/s/1YiFdOHX8rWrVKB97FRY8Iw 提取码: eka6

## Confusion matrixes in R ----
sms_results <- read.csv("sms_results.csv") # the first several test cases
head(sms_results) # test cases where the model is less confident
head(subset(sms_results, prob_spam > 0.40 & prob_spam < 0.60)) # test cases where the model was wrong
head(subset(sms_results, actual_type != predict_type)) # specifying vectors
table(sms_results$actual_type, sms_results$predict_type) # alternative solution using the formula interface (not shown in book)
xtabs(~ actual_type + predict_type, sms_results) # using the CrossTable function
library(gmodels)
CrossTable(sms_results$actual_type, sms_results$predict_type) # accuracy and error rate calculation --
# accuracy
(152 + 1203) / (152 + 1203 + 4 + 31)
# error rate
(4 + 31) / (152 + 1203 + 4 + 31)
# error rate = 1 - accuracy
1 - 0.9748201

1.2 其他评价指标

分类和回归训练R包caret提供了更多的计算性能度量指标的函数。

## Beyond accuracy: other performance measures ----
library(caret)
confusionMatrix(sms_results$predict_type,
sms_results$actual_type,
positive = "spam") #检测垃圾信息是目标,将其设为阳性

1)Kappa统计量

  • Kappa对准确度进行调整,表示的是预测值和真实值之间的一致性

  • Kappa计算公式:



    Pr是预测值和真实值之间的真实一致性a和期望一致性e的比例。Kappa统计量使用期望的一致性Pr(e)对准确度进行调整,Pr(e)是完全的偶然性导致的预测值和实际值相同的概率。

计算示例:

pr(a)=0.865+0.111=0.976
pr(e)=0.868*0.886+0.132*0.114=0.784096
kappa=(pr(a)-pr(e))/(1-pr(e))=0.89
  • 其他计算Kappa的函数:
# calculate kappa via the vcd package
library(vcd)
Kappa(table(sms_results$actual_type, sms_results$predict_type))

  • vcd::Kappa函数计算出来的kappa有加权和没加权的,对于二分类,加不加权都一样,一般关注不加权的就好。加权主要用于存在不同尺度一致性的情况。
# calculate kappa via the irr package
library(irr)
kappa2(sms_results[1:2])

  • irr::kappa2函数可直接使用数据框中的预测值向量和实际分类向量来计算Kappa值。

注意不要用内置的kappa函数,它与Kappa统计量没关系。

2)灵敏度与特异性

  • 用来权衡做决策时保守or激进的度量。权衡时最典型的做法是:对模型进行调整或者使用不同的模型,直到能通过灵敏度和特异性的阈值为止。
  • 灵敏度(真阳性率):度量阳性样本被正确分类的比例。

  • 特异性(真阴性率):度量阴性样本被正确分类的比例。



如上面的混淆矩阵中,手动计算:

# Sensitivity and specificity
# example using SMS classifier
sens <- 152 / (152 + 31)
sens spec <- 1203 / (1203 + 4)
spec

caret包中的sensitivity和specificity函数可直接计算:

# example using the caret package
library(caret)
sensitivity(sms_results$predict_type,
sms_results$actual_type,
positive = "spam")
specificity(sms_results$predict_type,
sms_results$actual_type,
negative = "ham")

3)精确度与回溯精确度

  • 这两者也与分类时的折中方案有关。
  • 精确度(阳性预测值):真阳性在所有预测为阳性案例中的比例。

  • 回溯精确度:度量结果的完备性,真阳性与阳性总数的比例(计算与灵敏度一样,只是解释不同:捕捉大量阳性样本,具有很宽的范围)。



手动计算:

# Precision and recall
prec <- 152 / (152 + 4)
prec rec <- 152 / (152 + 31)
rec

caret包中的posPredValue函数计算:

# example using the caret package
library(caret)
posPredValue(sms_results$predict_type,
sms_results$actual_type,
positive = "spam")
sensitivity(sms_results$predict_type,
sms_results$actual_type,
positive = "spam")

4)F度量

  • F度量(F1记分/F记分):将精确度和回溯精确度合并成一个单一值(通过调和平均值来整合)的模型性能度量方式。



计算:

# F-measure
f <- (2 * prec * rec) / (prec + rec)
f f <- (2 * 152) / (2 * 152 + 4 + 31)
f
  • 整合成一个单一值比较方便,但需要假设精确度和回溯精确度具有同样的权重。

1.3 性能权衡可视化(ROC曲线)

  • 可视化可以考察度量如何在大范围的值之间变化,还可以在单个图形中同时比较多个分类器的方法。
  • ROC(受试者工作特征)曲线:常用来检查在找出真阳性和避免假阳性之间的权衡。
  • ROC曲线横轴表假阳性比例(1-特异性),纵轴表真阳性比例(灵敏度),所以也称为灵敏度/特异性图。

  • ROC曲线上的点表示不同假阳性阈值上的真阳性的比例。
  • AUC(Area Under the ROC):ROC曲线下面积来度量识别阳性值的能力。位于0.5(无预测值分类器)-1(完美分类器)之间,解释AUC得分可参考(比较主观):

  • ROC+AUC:两个ROC曲线可能形状不同,但具有相同的AUC,因此AUC可能具有误导性,最好是和ROC曲线定性分析结合使用。

    代码示例:
## Visualizing Performance Tradeoffs ----
library(ROCR)
pred <- prediction(predictions = sms_results$prob_spam,
labels = sms_results$actual_type) # ROC curves
perf <- performance(pred, measure = "tpr", x.measure = "fpr")
plot(perf, main = "ROC curve for SMS spam filter", col = "blue", lwd = 2) # add a reference line to the graph
abline(a = 0, b = 1, lwd = 2, lty = 2)



定性分析可看到上图ROC曲线占据了图形左上角的区域,接近完美分类器;定量分析则通过函数来计算AUC。

# calculate AUC
perf.auc <- performance(pred, measure = "auc")
#返回S4对象,存储信息的位置称为槽(slots),槽的前缀为@
str(perf.auc) #查看所有槽
unlist(perf.auc@y.values) #简化为数值向量

AUC值可达到0.98。但这个模型对其他数据集是否也表现好呢?需要测试外部数据来推断模型的预测性能。

2.评估未来的性能

  • 当训练数据进行了错误的预测时会产生再带入误差。与信赖再带入误差相比,更好的方式时评估模型对其从未见过数据的性能。一般就是将数据分为训练集和测试集,但当数据集很小时,这样的划分会减小样本量,是不合适的。

2.1 保持法

  • 保持法就是常见的数据划分训练集和测试集的过程:训练集用来生成模型,应用到测试集来生成预测结果进行评估。一般1/3的数据用于测试,2/3用于训练。
  • 保持法不允许测试集的结果影响模型,但如果基于重复测试的结果选择一个最好的模型,则会违反这个原则。因此可再分出第三个数据集,集验证集。(注:前面的章节中我们只划分了训练和测试集两类数据,实际上违反了这一原则,那些测试集更准确地应该称为验证集。如果我们使用测试集来做决策,从结果中挑选最好的模型,那么评估将不再是对未来性能的无偏估计)
  • 验证集用来对模型迭代和改善。测试集只使用一次,最后输出对未来预测的错误率估计。一般数据划分50%训练集,25%测试集,25%验证集。
  • 分层随机抽样:确保随机划分后每个类别的比例与总体数据中的比例近似相等。可用caret:::createDataPartition函数实现。

数据下载链接: https://pan.baidu.com/s/1O9JYXUZnQfVGIU-VWGTptA 提取码: 7q7q

# partitioning data
library(caret)
credit <- read.csv("credit.csv") # Holdout method
# using random IDs
random_ids <- order(runif(1000))
credit_train <- credit[random_ids[1:500],]
credit_validate <- credit[random_ids[501:750], ]
credit_test <- credit[random_ids[751:1000], ] # using caret function
#返回行号
in_train <- createDataPartition(credit$default,
p = 0.75, #该划分中样本的比例
list = FALSE) #防止结果存储成列表
credit_train <- credit[in_train, ]
credit_test <- credit[-in_train, ]
  • 一般的,模型在更大的数据集中训练可得到更好的性能,所以常见的做法是:在选择和评估了最终的模型之后,将模型在整个数据集(训练集+测试集+验证集)上重新训练,使模型最大化地利用所有数据。
  • 重复保持法:保持法的一种特殊形式,对多个随机保持样本的模型分别评估,然后用结果的均值来评价整个模型的性能。

2.2 交叉验证

  • 重复保持法使k折交叉验证(k折CV,将数据随机分成k个完全分隔的部分)的基础,k折交叉验证已称为业界评估模型性能的标准。
  • 最常用10折交叉验证(每一折包含总数据的10%),机器学习模型使用剩下的90%数据建模,包含10%数据的这一折用来评估,训练和评估模型进行不同的10次,将输出所有折的平均性能指标。
  • 留一交叉验证法:将每个样本作为1折,用最大数目的样本来建模,但计算量太大,很少用。
  • 使用caret::createFolds函数创建交叉验证数据集:
# 10-fold CV
folds <- createFolds(credit$default, k = 10)
str(folds)
credit01_test <- credit[folds$Fold01, ]
credit01_train <- credit[-folds$Fold01, ]

可以用不同数据集手动执行以上步骤10次,然后建模评估,最后将所有性能度量取均值作为总体的性能。但我们肯定可以通过编程来实现自动化,这里以10折CV建立C5.0决策树模型为例,然后估计Kappa统计量:

## Automating 10-fold CV for a C5.0 Decision Tree using lapply() ----
library(caret)
library(C50)
library(irr) credit <- read.csv("credit.csv") set.seed(123)
folds <- createFolds(credit$default, k = 10) cv_results <- lapply(folds, function(x) {
credit_train <- credit[-x, ]
credit_test <- credit[x, ]
credit_model <- C5.0(default ~ ., data = credit_train)
credit_pred <- predict(credit_model, credit_test)
credit_actual <- credit_test$default
kappa <- kappa2(data.frame(credit_actual, credit_pred))$value
return(kappa)
}) str(cv_results)
mean(unlist(cv_results))



kappa值很低,总体模型性能差,下一章会讲如何改进。

2.3 自助法抽样

  • 自助法抽样(bootstrap):主要指一些统计方法,通过对数据进行随机抽样的方式来估计大数据集的内容。各种随机产生的数据集的结果可以通过平均值计算得到一个最终的估计值,用来评估未来的性能。
  • 与k折CV的不同:交叉验证将数据分隔开来,每个样本只能出现一次,而自助法是有放回的抽样,每个样本可以被选择多次。因此自助法抽样对完整数据集的代表性更弱,但它对于小数据集的效果更好。除了度量性能之外,它还能提高模型性能。
  • 0.632自助法:每个样本包含在训练集中的概率是63.2%。通过训练数据集(过于乐观)和测试集(过于悲观)的函数来计算最终的性能度量:


机器学习与R语言系列推文汇总:

【机器学习与R语言】1-机器学习简介

【机器学习与R语言】2-K近邻(kNN)

【机器学习与R语言】3-朴素贝叶斯(NB)

【机器学习与R语言】4-决策树

【机器学习与R语言】5-规则学习

【机器学习与R语言】6-线性回归

【机器学习与R语言】7-回归树和模型树

【机器学习与R语言】8-神经网络

【机器学习与R语言】9-支持向量机

【机器学习与R语言】10-关联规则

【机器学习与R语言】11-Kmeans聚类

【机器学习与R语言】12-如何评估模型的性能?

【机器学习与R语言】13-如何提高模型的性能?

【机器学习与R语言】12- 如何评估模型的性能?的更多相关文章

  1. 【机器学习与R语言】13- 如何提高模型的性能?

    目录 1.调整模型参数来提高性能 1.1 创建简单的调整模型 2.2 定制调整参数 2.使用元学习来提高性能 2.1 集成学习(元学习)概述 2.2 bagging 2.3 boosting 2.4 ...

  2. 【机器学习与R语言】7-回归树和模型树

    目录 1.理解回归树和模型树 2.回归树和模型树应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估模型 5)提高模型性能 1.理解回归树和模型树 决策树用于数值预测: 回归树:基于到达 ...

  3. 【机器学习与R语言】11- Kmeans聚类

    目录 1.理解Kmeans聚类 1)基本概念 2)kmeans运作的基本原理 2.Kmeans聚类应用示例 1)收集数据 2)探索和准备数据 3)训练模型 4)评估性能 5)提高模型性能 1.理解Km ...

  4. 【机器学习与R语言】10- 关联规则

    目录 1.理解关联规则 1)基本认识 2)Apriori算法 2.关联规则应用示例 1)收集数据 2)探索和准备数据 3)训练模型 4)评估性能 5)提高模型性能 1.理解关联规则 1)基本认识 购物 ...

  5. 【机器学习与R语言】9- 支持向量机

    目录 1.理解支持向量机(SVM) 1)SVM特点 2)用超平面分类 3)对非线性空间使用核函数 2. 支持向量机应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估模型 5)提高性能 ...

  6. 【机器学习与R语言】8- 神经网络

    目录 1.理解神经网络 1)基本概念 2)激活函数 3)网络拓扑 4)训练算法 2.神经网络应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估模型 5)提高性能 1.理解神经网络 1) ...

  7. 【机器学习与R语言】6-线性回归

    目录 1.理解回归 1)简单线性回归 2)普通最小二乘估计 3)相关系数 4)多元线性回归 2.线性回归应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估模型 5)提高模型性能 1.理 ...

  8. 【机器学习与R语言】5-规则学习算法

    目录 1.分类规则原理 1.1 1R单规则算法 1.2 RIPPER算法 2. 规则学习应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估性能 5)提高性能 6)选择决策树中的分类规则 ...

  9. 【机器学习与R语言】4-决策树

    目录 1.决策树原理 2.决策树应用示例 2.1)收集数据 2.2)探索和准备数据 2.3)训练模型 2.4)评估模型性能 2.5)提高模型性能 通过自适应增强算法(boosting) 将惩罚因子分配 ...

随机推荐

  1. 240.搜索二维矩阵II

    从左下角位置开始搜索 时间复杂度:O(行数+列数). 想法有点像二分法,大了往一个方向找,小了往另一个方向找.由于矩阵横向和纵向都是递增,如果从(0,0)位置开始找,往右和往下都是增大,因此不知道实际 ...

  2. vue3.x全局$toast、$message、$loading等js插件

    有时候我们需要使用一些类似toast,messge.loading这些跟js交互很频繁的插件,vue3.x这类插件的定义跟vue2.x插件稍大,而且相对变得复杂了一点点. 第一种.需要时创建,用完移除 ...

  3. [对对子队]会议记录5.24(Scrum Meeting10)

    今天已完成的工作 梁河览 ​ 工作内容:修改第一关的新手引导 ​ 相关issue:优化初步导出版本 ​ 相关签入:fix:改进第一关的新手引导 何瑞 ​ 工作内容:为加速按钮添加锚点 ​ 相关issu ...

  4. Go并发编程--Mutex/RWMutex

    目录 一.前言 二. Mutex 2.1 案例 三. 实现原理 3.1 锁的实现模式 3.2 Go Mutex 实现原理 3.2.1 加锁 3.2.2 解锁 四. 源码分析 4.1 Mutex基本结构 ...

  5. python mysqlclient安装失败 Command "python setup.py egg_info" failed with error code 1

    python2 python3 中代码 pip install mysqlclient 都安装失败的话, 很有可能是你的操作系统中没有安装mysql 如果确定已经安装了,请忽略下面的内容. Ubunt ...

  6. 『学了就忘』Linux基础命令 — 18、Linux命令的基本格式

    目录 1.命令提示符说明 2.命令的基本格式 (1)举例ls命令 (2)说明ls -l命令的 输出内容 1.命令提示符说明 [root@localhost ~] # []:这是提示符的分隔符号,没有特 ...

  7. Python3使用Print输出彩色字体

    一.介绍 在一些开发程序中,有些输出消息需要突出显示,我们可以尝试着给他们换上更靓丽的颜色来突出显示. 二.实现过程 终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关. ...

  8. offsetX各种值总结

    pageX: 页面X坐标位置 pageY: 页面Y坐标位置 screenX: 屏幕X坐标位置 screenY: 屏幕Y坐标位置 clientX: 鼠标的坐标到页面左侧的距离 clientY: 鼠标的坐 ...

  9. Java8新特性之Optional,如何优雅地处理空指针

    是什么 ​ 从 Java 8 引入的一个很有趣的特性是 Optional 类.Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)-- 每个 Java ...

  10. 动态sql & 抽取可重用sql

    抽取可重用的sql片段 抽取:<sql id="xx"></sql> 使用:<include refid="xx">< ...