机器学习 模型评估指标 - ROC曲线和AUC值

article/2025/5/1 9:12:01
  1. 机器学习算法-随机森林初探(1)

  2. 随机森林拖了这么久,终于到实战了。先分享很多套用于机器学习的多种癌症表达数据集 https://file.biolab.si/biolab/supp/bi-cancer/projections/。

  3. 机器学习算法-随机森林之理论概述

分类问题评估指标有:准确率 (Accuracy)、精准率 (Precision)、灵敏度 (Sensitivity)、ROC曲线、AUC值。

回归问题评估指标有:MAEMSE

假设有下面一个分类效果评估矩阵Confusion matrix(也称混淆矩阵,总觉得这个名字奇怪),如下

行代表实际值,列代表预测值。如DLBCL组有56+2个样品,其中56个被预测为DLBCL2个被预测为FL

confusion <- data.frame(Predicted_as_DLBCL=c(56,8), Predicted_as_FL=c(2,11), class.error=c(0.03448, 0.4211),row.names = c("Originally_classified_as_DLBCL","Originally_classified_as_FL"))confusion##                                Predicted_as_DLBCL Predicted_as_FL class.error
## Originally_classified_as_DLBCL                 56               2     0.03448
## Originally_classified_as_FL                     8              11     0.42110

准确率 (Accuracy)表示预测正确的结果占总样本的比例

计算如下:

准确率可以判断总的正确率,但在各个分组样本数目差别较大时就不能作为一个很好的评价标准。比如上面confusion matrix中,所有样品全部预测为DLBCL,则准确率可达75.3%。这一不负责任的分法跟预测模型的准确率 (87.0%)相差不是太大。

精准率 (Precision)

  • 所有被预测为DLBCL的样品中有多少确实是DLBCL;

  • 所有被预测为FL的样品中有多少确实是FL;

灵敏度 (Sensitivity)

灵敏度 (Sensitivity)也称为真阳性率。

  • 实际为DLBCL的样品中有多少被预测为DLBCL

  • 实际为FL的样品中有多少被预测为FL:

不同的分组,灵敏度(Sensitivity)值差别很大,尤其是样本数目不均衡时。

假阳性率 (false-positive)

假阳性率 (false-positive)实际为1-灵敏度

  • DLBCL的预测假阳性率指所有实际为FL的样本被错误的预测为DLBCL的比例;

  • FL的预测假阳性率指所有实际为DLBCL的样本被错误的预测为FL的比例。

ROC曲线

ROC (Receiver Operating Characteristic)特征曲线就是横轴为假阳性率,纵轴为真阳性率的一条曲线。这条曲线越陡越好,说明在较低的假阳性率时可以获得较高的真阳性率。

根据阈值设定的变化,模型的假阳性率和真阳性率随之变化,形成了ROC曲线。

那么ROC曲线是怎么绘制的?假设有一个预测结果如下:

probability <- data.frame(Original_class= c("DLBCL", "DLBCL", "DLBCL", "DLBCL", "DLBCL", "FL", "DLBCL","FL", "FL"),Predicted_socre_for_sample_in_class_DLBCL=seq(0.9,0.1,-0.1))
probability##   Original_class Predicted_socre_for_sample_in_class_DLBCL
## 1          DLBCL                                       0.9
## 2          DLBCL                                       0.8
## 3          DLBCL                                       0.7
## 4          DLBCL                                       0.6
## 5          DLBCL                                       0.5
## 6             FL                                       0.4
## 7          DLBCL                                       0.3
## 8             FL                                       0.2
## 9             FL                                       0.1

如果设置Predicted_socre_for_sample_in_class_DLBCL:

  • >0.75为阈值标准,那么灵敏度=2/6=0.33,假阳性率为1-3/3=0;

  • >0.65为阈值标准,那么灵敏度=3/6=0.50,假阳性率为1-3/3=0;

  • >0.55为阈值标准,那么灵敏度=4/6=0.67,假阳性率为1-3/3=0;

  • >0.45为阈值标准,那么灵敏度=5/6=0.83,假阳性率为1-3/3=0;

  • >0.35为阈值标准,那么灵敏度=5/6=0.83,假阳性率为1-2/3=0.33;

  • >0.25为阈值标准,那么灵敏度=6/6=1.00,假阳性率为1-2/3=0.33;

  • >0.15为阈值标准,那么灵敏度=6/6=1.00,假阳性率为1-1/3=0.66;

  • >0.05为阈值标准,那么灵敏度=6/6=1.00,假阳性率为1-0/3=1.00;

还是写个程序来算吧。

thresholdL = seq(1,0,-0.05)
right_class = "DLBCL"
score_column = "Predicted_socre_for_sample_in_class_DLBCL"
original_right = sum(probability$Original_class == right_class)
original_wrong = sum(probability$Original_class != right_class)tpr_fpr <- function(probability, score_column, threshold, right_class, original_right, original_wrong){pass_threshold = as.vector(probability[probability[[score_column]]>threshold,1])# print(pass_threshold)pass_threshold_true = sum(pass_threshold == right_class)pass_threshold_false = sum(pass_threshold != right_class)tpr <- pass_threshold_true/original_rightfpr <- pass_threshold_false/original_wrongreturn(c(threshold=threshold, tpr=tpr, fpr=fpr, right_class=right_class))
}ROC_data = as.data.frame(do.call(rbind, lapply(thresholdL, tpr_fpr, probability=probability, score_column = score_column, right_class=right_class, original_right=original_right, original_wrong=original_wrong)))
ROC_data$tpr <- as.numeric(ROC_data$tpr)
ROC_data$fpr <- as.numeric(ROC_data$fpr)ROC_data

结果如下

##             threshold       tpr       fpr right_class
## 1                   1 0.0000000 0.0000000       DLBCL
## 2                0.95 0.0000000 0.0000000       DLBCL
## 3                 0.9 0.0000000 0.0000000       DLBCL
## 4                0.85 0.1666667 0.0000000       DLBCL
## 5                 0.8 0.1666667 0.0000000       DLBCL
## 6                0.75 0.3333333 0.0000000       DLBCL
## 7                 0.7 0.3333333 0.0000000       DLBCL
## 8                0.65 0.5000000 0.0000000       DLBCL
## 9                 0.6 0.5000000 0.0000000       DLBCL
## 10               0.55 0.6666667 0.0000000       DLBCL
## 11                0.5 0.6666667 0.0000000       DLBCL
## 12               0.45 0.8333333 0.0000000       DLBCL
## 13                0.4 0.8333333 0.3333333       DLBCL
## 14               0.35 0.8333333 0.3333333       DLBCL
## 15                0.3 0.8333333 0.3333333       DLBCL
## 16               0.25 1.0000000 0.3333333       DLBCL
## 17                0.2 1.0000000 0.3333333       DLBCL
## 18               0.15 1.0000000 0.6666667       DLBCL
## 19                0.1 1.0000000 1.0000000       DLBCL
## 20 0.0499999999999999 1.0000000 1.0000000       DLBCL
## 21                  0 1.0000000 1.0000000       DLBCL

简单地绘制下ROC曲线

library(ggplot2)ggplot(ROC_data, aes(x=fpr, y=tpr, group=right_class)) + geom_step(direction="vh", color='red') + geom_abline(intercept = 0, slope = 1)  + theme_classic() + scale_y_continuous(expand=c(0,0)) + xlab("False positive rate") + ylab("True positive rate") + coord_fixed(1)

如果right_classFL呢?(这里只是用同一套数据,方便说明问题,实际需要对score取反)

thresholdL = seq(1,0,-0.05)
right_class = "FL"
score_column = "Predicted_socre_for_sample_in_class_DLBCL"
original_right = sum(probability$Original_class == right_class)
original_wrong = sum(probability$Original_class != right_class)tpr_fpr <- function(probability, score_column, threshold, right_class, original_right, original_wrong){pass_threshold = as.vector(probability[probability[[score_column]]>threshold,1])# print(pass_threshold)pass_threshold_true = sum(pass_threshold == right_class)pass_threshold_false = sum(pass_threshold != right_class)tpr <- pass_threshold_true/original_rightfpr <- pass_threshold_false/original_wrongreturn(c(threshold=threshold, tpr=tpr, fpr=fpr, right_class=right_class))
}ROC_data2 = as.data.frame(do.call(rbind, lapply(thresholdL, tpr_fpr, probability=probability, score_column = score_column, right_class=right_class, original_right=original_right, original_wrong=original_wrong)))
ROC_data2$tpr <- as.numeric(ROC_data2$tpr)
ROC_data2$fpr <- as.numeric(ROC_data2$fpr)ggplot(ROC_data2, aes(x=fpr, y=tpr, group=right_class)) + geom_step(direction="vh", color='red') + geom_abline(intercept = 0, slope = 1)  + theme_classic() + scale_x_continuous(expand=c(0,0)) + xlab("False positive rate") + ylab("True positive rate") + coord_fixed(1)

从这张图可以看到,不管是根据FL计算,还是DLBCL计算,ROC曲线是一致的。

ROC_data3 = rbind(ROC_data, ROC_data2)ggplot(ROC_data3, aes(x=fpr, y=tpr, color=right_class)) + geom_step(direction="vh") + geom_abline(intercept = 0, slope = 1)  + theme_classic() + xlab("False positive rate") + ylab("True positive rate") + coord_fixed(1)

同时ROC曲线不不因样品不均衡而受影响。

阈值的改变只是会改变真阳性率(灵敏度)和假阳性率。但是ROC曲线却不会变化。这只是我们控制假阳性率和灵敏度在合理范围时设置的过滤标准。

AUC (Area under curve)

如何根据ROC曲线判断一个模型的好坏呢?ROC曲线越陡越好,说明在较低的假阳性率时可以获得较高的真阳性率。一般通过曲线下面积AUC评估一个ROC曲线的好坏。一般模型的AUC值在0.5-1之间,值越大越好。

下面是一个经验展示。AUC=1是最理想的情况。AUC=0.5就是随机模型。如果总是AUC<0.5模型就可以反过来用。

实际计算面积时并不是按几何图形进行计算的。通常根据AUC的物理意义进行计算。AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前面,从而能够更好地分类。

假设有一套数据包含n个样本,M个正样本,N个负样本。每个样本计算一个Score值,所有样本按Score值排序。Score值最大的样本的rankn(下面例子中是9),Score值次大的样品的rankn-1(下面例子中是8)。正样品中rank最大的样本有rank_positive_max - 1 - (M-1)个负样本比他的score小 (M-1代表多少个正样本比);正样品中rank第二大的样本有rank_positive_second - 1 - (M-2)个负样本比他的score小;

如下面样品arank最大的正样品其rank值为9,有3个负样品得分比其低。3怎么算的呢?3 = 9 - 1 - (6-1) = rank1 - M(9是样品arank-1是排除自身,6是正样本数,6-1是除了a之外的正样本数)

如下面样品brank次大的正样品其rank值为8,有3个负样品得分比其低。3怎么算的呢?3 = 8 - 1 - (6-2) = rank2 - M+1(8是样品brank-1是排除自身,6是正样本数,6-2是除了a,b之外的正样本数)

单独提取出后面的值就是M, M+1, M+2, M+3, ..., M + M-1,其加和就是

这样就可以总结出一个公式:

probability_rank <- data.frame(Sample = letters[1:9],Original_class= c("DLBCL", "DLBCL", "DLBCL", "DLBCL", "DLBCL", "FL", "DLBCL","FL", "FL"),Predicted_socre_for_sample_in_class_DLBCL=seq(0.9,0.1,-0.1),rank=seq(9,1,-1))
probability_rank##   Sample Original_class Predicted_socre_for_sample_in_class_DLBCL rank
## 1      a          DLBCL                                       0.9    9
## 2      b          DLBCL                                       0.8    8
## 3      c          DLBCL                                       0.7    7
## 4      d          DLBCL                                       0.6    6
## 5      e          DLBCL                                       0.5    5
## 6      f             FL                                       0.4    4
## 7      g          DLBCL                                       0.3    3
## 8      h             FL                                       0.2    2
## 9      i             FL                                       0.1    1

写个函数计算

# 测试用例
# probability <- data.frame(Original_class= c("DLBCL", "DLBCL", "DLBCL", "DLBCL", "DLBCL", "FL", "DLBCL","FL", "FL"),
#                          Predicted_socre_for_sample_in_class_DLBCL=sample(seq(0,1,0.1),9))
# probability
AUC <- function(probability, score_column, class_column, right_class){sample_count = nrow(probability)positive_count = nrow(probability[probability[[class_column]]==right_class,])negative_count = sample_count - positive_countprobability <- probability[rev(order(probability[[score_column]])),]probability$rank <- sample_count:1print(probability)rank_sum = sum(probability[probability[[class_column]]==right_class, "rank"])return((rank_sum - (positive_count+positive_count^2)/2)/(positive_count * negative_count))
}AUC(probability, "Predicted_socre_for_sample_in_class_DLBCL", "Original_class", "DLBCL")##   Original_class Predicted_socre_for_sample_in_class_DLBCL rank
## 1          DLBCL                                       0.9    9
## 2          DLBCL                                       0.8    8
## 3          DLBCL                                       0.7    7
## 4          DLBCL                                       0.6    6
## 5          DLBCL                                       0.5    5
## 6             FL                                       0.4    4
## 7          DLBCL                                       0.3    3
## 8             FL                                       0.2    2
## 9             FL                                       0.1    1## [1] 0.9444444

参考

  • https://www.spectrumnews.org/opinion/viewpoint/quest-autism-biomarkers-faces-steep-statistical-challenges/

  • https://www.cnblogs.com/gatherstars/p/6084696.html

  • https://blog.csdn.net/qq_24753293/article/details/80942650-

往期精品(点击图片直达文字对应教程)

后台回复“生信宝典福利第一波”或点击阅读原文获取教程合集

 

(请备注姓名-学校/企业-职务等)


http://chatgpt.dhexx.cn/article/ewEuDK3I.shtml

相关文章

[sklearn]性能度量之AUC值

[sklearn]性能度量之AUC值 &#xff08;from sklearn.metrics import roc_auc_curve&#xff09; 1.AUC AUC&#xff08;Area Under ROC Curve&#xff09;&#xff0c;即ROC曲线下面积。 2.AUC意义 若学习器A的ROC曲线被学习器B的ROC曲线包围&#xff0c;则学习器B的性能优…

如何理解ROC曲线和AUC值

1、ROC曲线下的面积就是AUC值。 2、如何绘制ROC曲线&#xff0c;通过改变不同的阈值&#xff0c;每个阈值都可以得到一个混淆矩阵&#xff0c;通过混淆矩阵&#xff0c;可以计算出假阳性率和真阳性率。即该坐标系下的一个点。将阈值从0&#xff0c;调整到1&#xff0c;即可绘制…

AUC值越大_AUC的一般计算和近似计算方式

AUC值是一个概率值&#xff0c;当你随机挑选一个正样本以及负样本&#xff0c;当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值&#xff0c;AUC值越大&#xff0c;当前分类算法越有可能将正样本排在负样本前面&#xff0c;从而能够更好地分类。…

AUC值越大_模型评价——准确率、精确率与召回率与F值、宏平均与微平均、ROC曲线与AUC值...

在上一篇文章中&#xff08;baiziyu&#xff1a;模型评价——训练误差与测试误差、过拟合与欠拟合、混淆矩阵&#xff09;主要介绍了模型评价涉及的基本概念&#xff0c;本节给出一些常用的评价指标。这些指标大致可以分为三类&#xff0c;第一大类是普通的准确率评价指标&…

AUC值越大_「机器学习速成」分类,评估指标(TP、FP、TN、FN),ROC曲线和AUC

大家好&#xff0c;今天我们学习【机器学习速成】之 分类&#xff0c;评估指标(TP、FP、TN、FN)&#xff0c;ROC曲线和AUC。 本节介绍了如何使用逻辑回归来执行分类任务&#xff0c; 并探讨了如何评估分类模型的有效性。 我们 马上学三点 &#xff0c; 逻辑回归用作分类&#x…

AUC值越大_一文看懂ROC、AUC

评测指标是衡量一个算法是否出色的一个重要部分,好的指标能让我们这些炼丹学徒知道,练出来的丹药是否有效果。那么在机器学习中有哪些值得一探究竟的指标呢?本文就PR图,ROC、AUC、mAP这4个方面进行详细探究。 总的来说评价指标的核心得从二分类问题说起:一个类,它实际值有…

入门选手都能理解的ROC曲线与AUC值

项目github地址&#xff1a;bitcarmanlee easy-algorithm-interview-and-practice 欢迎大家star&#xff0c;留言&#xff0c;一起学习进步 1.ROC曲线 在信号检测理论中&#xff0c;接收者操作特征曲线&#xff08;receiver operating characteristic curve&#xff0c;或者叫…

AUC值得含义和计算方法

转载自&#xff1a;http://baijiahao.baidu.com/s?id1597939133517926460&wfrspider&forpc 机器学习备忘录 | AUC值的含义与计算方法 浮生偷闲 18-04-17 05:32 内容导读 在机器学习领域&#xff0c; AUC 值经常用来评价一个二分类模型的训练效果&#xff0c;对于许多机…

python计算偏态、极差、方差、标准差、平均数、中位数、众数

import numpy as np lists[1,2,3,4,5,6,7,8,9]print("极差&#xff1a;",np.max(lists)-np.min(lists))#最大值减最小值 lists_varnp.var(lists, axisNone, dtypeNone, outNone, ddof0, keepdimsnp._NoValue) print("方差&#xff1a;",lists_var) lists_s…

数据分析应用统计学之分散性与变异性的测量【极差、四分位差、偏态系数、峰态系数、统计指标】

文章目录 1、极差与四分位差&#xff08;R&#xff09;2、方差与标准差&#xff08;西格玛、V&#xff09;3、偏态系数与峰态系数&#xff08;SK、β&#xff09;4、统计指标类型 1、极差与四分位差&#xff08;R&#xff09; 1&#xff09;极差&#xff1a;称为全距&#xff…

偏态数据的观察、量化评估与处理前后的对比

在机器学习中&#xff0c;模型更容易从具有正态分布特性的数据中学习到有用特征。但我们经常会发现有些特征存在长尾分布&#xff0c;对于这种偏态分布数据&#xff0c;需要进行特殊的处理&#xff0c;本文首先观察特征分布情况&#xff0c;然后以量化的方式评估数据偏态程度从…

统计学学习日记:L7-离散趋势分析之偏态和峰态

一、偏态&#xff08;SK&#xff09; 1.数据偏斜程度的测度 偏态系数0为对称分布 偏态系数>0为右偏分布 偏态系数<0为左偏分布 偏态系数>1或<-1&#xff0c;被称为高度偏态分布&#xff1b;偏态系数在0.5~1或-1~-0.5之间&#xff0c;被认为是中等偏态分布&#xf…

如何处理偏态数据?

这是笔试/面试题系列的第2篇文章 在了解何为偏态数据前&#xff0c;要先从正态数据说起。 正态分布 正态分布是自然界中广泛存在的&#xff0c;我们都知道它是两头低&#xff0c;中间高&#xff0c;整个形态呈现对称钟形的一个分布&#xff0c;之所以叫正态分布&#xff0c;是…

skewness and kurtosis偏态和峰度的解释和演示、数据的偏度和峰度——df.skew()、df.kurt()

skewness (偏态) 正偏态分布(positive skewness distribution)是指频数分布的高峰偏于左侧&#xff0c;偏态系数为正值的频数分布形态。偏态分布分为正偏态和负偏态。当均值大于众数时称为正偏态&#xff1b;当均值小于众数时称为负偏态。 定义上偏度是样本的三阶标准化矩&am…

Uniapp中onShow()的应用

遇到问题&#xff1a; 在使用一些变量进行判断时&#xff0c;用完一次开始下一次判断时&#xff0c;结果会跟前一次一样&#xff0c;比如门禁中第一个房子打开后&#xff0c;切换到另外的房子&#xff0c;结果返回结果跟第一个房子一样。 原因分析&#xff1a; 用于使用了相…

uni中onLoad与onShow周期的区别

一、说明 页面周期参考网址&#xff1a;https://uniapp.dcloud.io/tutorial/page.html#lifecycle 二、通俗概括 1. onLoad先执行&#xff0c;onShow后执行 onLoad() {console.log(111); }, onShow(){console.log(222); },2. onLoad只执行一次&#xff0c;onShow监听页面可执…

uni-app小程序onShow执行两次;微信小程序onShow重复执行原因;导航栏tabBar页的onLoad函数不执行;App.vue页的onShow执行原因;onShow莫名其妙执行

1.只有五种情况会触发导航栏tabBar页的onLoad函数&#xff0c;分别是&#xff1a; –1.1&#xff1a;首次进入到导航栏tabBar页面&#xff1b; –1.2&#xff1a;从微信分享进入的导航栏tabBar页面&#xff1b; –1.3&#xff1a;识别二维码跳转到小程序的导航栏tabBar页面&…

自定义组件中,使用onLoad,onShow生命周期失效问题

的解决方法 自定义组件中&#xff0c;使用onLoad,onShow生命周期失效问题 自定义组件中&#xff0c;使用onLoad,onShow生命周期失效问题 官方文档可查阅到&#xff1a; 页面生命周期仅在page中的vue页面有效&#xff0c;而单独封装的组件中【页面周期无效】&#xff0c;但是Vu…

微信小程序onTabItemTap和onShow的执行顺序

很显然 onShow的执行顺序要比 onTabItemTap早 onTabItemTap的特性是只在当前tabbar页面生效&#xff0c;比如onTabItemTap写在home页面&#xff0c;那么只有点击了tabbar上的home才会执行。 那是否有办法让onTabItemTap早于onShow先执行那&#xff1f;经过测试找到2种办法 方…