在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 563406 点 威望 12 点 阅读权限 255 积分 174245 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
# S' R- T! S" C& Q. ?9 i 详细讲解分类模型评估 分类模型评估
, Y' e3 k% F: e) m) M. I
) [9 Y5 B* d( p. I1 j; D 1、分类模型. [! h* l, Q% g9 ^
主题:如何对分类模型进行评估% u4 I( E3 }' {
目标:
@6 z$ B! u4 f5 @) o( H& K 2、混淆矩阵
' m0 [. E0 A) U; w, _3 N5 g 3、评估指标2 S' [' W8 G8 o$ t: y, |
3.1 正确率( T+ _" \! \6 I
3.2 精准率
Q# L: ?' E* S1 } 3.3 召回率# G1 k6 q. s' v' t9 J" s
3.4 调和平均值F1
7 [+ G% l9 H$ _/ e# K 4、ROC和AUC) z( \9 L& M; V
4.1 ROC曲线
6 ^; F9 |, L3 W: D* Z 如何画ROC曲线:9 ]* q: u% [8 v5 o
4.2 AUC+ L2 r E8 w* n2 V) q
4.3 ROC曲线程序示例
1 D! H$ T6 ?5 `2 Y 4.3.1 roc_curve函数的参数
- S! M+ { h$ j4 s$ g: H% x4 f9 y 4.3.2 roc_curve函数的返回值
# e9 s6 v2 g4 R/ Y* s5 m 4.3.3 绘制ROC曲线
9 S8 M$ W' H$ {/ \$ F) D6 J6 a; { 5、总结
C% B7 x7 H( ~ 1、分类模型; C: c+ Z8 o/ h; j9 m4 d+ e7 `% f' H
: A1 D: }5 F. k7 _0 Y. t; E. Y
分类问题在我们日常生活中处处可见,比如我们对帅哥的分类,可能对帅哥分为非常帅和一般帅。比如我们平时刷淘宝,淘宝根据我们平时的喜好给我们推送产品,那我们就会把产品分为感兴趣和不感兴趣两类。* v7 v7 W: S; m% J
上述所说的问题就是典型的分类问题,确切的说其实就是二分类问题。- N2 O8 `- D7 ?& Y
能够解决这些二分类问题的数学模型就被称为二分类模型。! u9 }" D+ M3 I1 v
用数学的方式表达就是,给定自变量X,代入到我们的分类模型F,会输出因变量y,y的取值为0或1,其中0代表负样本(一般帅的帅哥、不感兴趣的推送),1代表正样本(非常帅气的帅哥、感兴趣的推送)。
5 c8 }# v/ r B5 K( T 5 [5 g) W" m% ?* @
主题:如何对分类模型进行评估: X. O/ \8 I# [. e6 ~
8 B) d. ]* D: o: M B
目标:/ g; N- i6 w& U) X3 V4 C3 V, s: ^6 J
; p6 [2 k+ |, R8 H: D- m# | 能够熟知混淆矩阵的含义。
5 H/ v! J5 y2 u$ P 能够使用各种指标对分类模型进行评估。' J6 {$ F( h& G' Y; O
能够独立绘制ROC曲线,并熟悉该曲线细节。( y1 `: F7 t9 o2 s- j0 h; F$ Y% t) c
能够对样本不均衡进行处理(扩展内容)。
9 p' U5 e! _! F! Y+ Z( _# Q, e 2、混淆矩阵
6 P3 e& v9 j% f# E# ? * |6 G' N3 x6 `9 F
混淆矩阵,可以用来评估模型分类的正确性。
% U, G6 p9 u8 B6 F) r 该矩阵是一个方阵,矩阵的数值用来表示分类器预测的结果,包括真正例(True Positive),假正例(False Positive),真负例(True Negative),假负例(False Negative)。2 }( b7 S+ E: ?- M
: ^" o, H3 b6 j4 n. ]4 z
矩阵的形状是2 x 2,其中, - 矩阵的左上角表示,预测值为1,实际值为1(True Positive,简称TP); - 右上角表示预测值为1,实际值为0(False Positive,简称FP); - 左下角表示预测值为0,实际值为1(False Negative,简称FN); - 右下角表示预测值为0,实际值为0(True Negative,简称TN);9 K3 y1 J4 ?, T2 B) |$ I
+ H$ X8 _% t" Y) ~) I& m 真负例(TN)+ 假正例(FP)——每个类别真实存在的负例的数量
; q6 Y9 l8 X& C" B" Z 假负例(FN)+ 真正例(TP)——每个类别真实存在的正例的数量
/ @2 @1 ^ o# J0 w 真负例(TN)+ 假负例(FN)——每个类别预测的真负例数量+ v& z. ^; L/ ^
假正例(FP)+ 真正例(TP)——每个类别预测的真正例数量
' _# b. P; y6 g3 L* t 其中:
7 |- F/ m w& R9 N 9 O( {& {5 y; S% C D3 v
TP:真正例,实际为正预测为正;
7 V# J, R3 N* D1 {8 U& `" X/ t FP:假正例,实际为负但预测为正;
7 S' }) k. B/ T! x& F# ]3 P7 O, k FN:假反例,实际为正但预测为负;. C' V; n! h' g! N0 a% H9 v# x
TN:真反例,实际为负预测为负
, g! K& Y& ^ j) e* u7 y V& i/ m/ i0 } 接下来,我们通过数据来看下鸢尾花的混淆矩阵:
+ e( D& J3 x; }- C import numpy as np
4 Z- h- B; i: I8 X from sklearn.datasets import load_iris
" K+ \8 R2 Z+ J' { from sklearn.linear_model import LogisticRegression6 ^- E* C1 k6 ?6 b
from sklearn.model_selection import train_test_split H# B1 Z \- V: c
# 混淆矩阵
4 V# Y! B, a7 P$ Y from sklearn.metrics import confusion_matrix) v7 A$ S5 L1 s1 p1 f. H
import matplotlib.pyplot as plt8 N7 j/ c$ D/ K' R: [
import warnings
7 c" c$ i9 X8 h# o( |2 S/ }$ _ ) d) T6 s7 ?% R) S+ w; Z: W- }
plt.rcParams["font.family"] = "SimHei" m1 U( f- @4 B w) T g# a
plt.rcParams["axes.unicode_minus"] = False
2 y! a$ ^; Z, P8 F) w: w8 R plt.rcParams["font.size"] = 12; q0 f- ]4 t, ]* Q4 T0 F# h7 w7 v
warnings.filterwarnings("ignore")
* Z/ C- n' V# h
; M! `* P9 b6 k, x$ R5 ^4 ] iris = load_iris() #导入鸢尾花数据集$ W. e6 C2 x1 N0 A/ i& F
X, y = iris.data, iris.target
S% Y6 n0 R$ p9 P2 v( n X = X[y != 0, 2:]) n! ?9 E) e" f& m6 d5 h) |/ D
y = y[y != 0]
" ^% I) f/ K) A) Q' c y[y == 1] = 09 ]1 v. W8 x2 H5 R7 Z9 h$ S
y[y == 2] = 1
! J# J) A- Z6 p3 A/ j X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=2)
+ X6 p2 x, f1 q lr = LogisticRegression() #使用逻辑回归( q Q: d0 J2 g2 P2 a
lr.fit(X_train, y_train)
8 o# [0 T0 z( b9 b; z y_hat = lr.predict(X_test)
- G& {4 I) z5 `/ f; d # 根据传入的真实值与预测值,创建混淆矩阵。5 T, ^& Y/ j' X% r/ v& h: N
matrix = confusion_matrix(y_true=y_test, y_pred=y_hat); H8 K' x' W8 T2 C n* _. k0 u
print(matrix)( ?$ [8 y4 {9 b' S* T4 p
[0 ?! `! i, ^ f# U) V
o: f j8 b) l1 ~3 q7 E& X9 @
输出结果:- I7 N$ |- l* v1 [1 w! Y( T
5 Y: h* x8 ^" A4 [7 j ]2 i 我们还可以对其进行可视化操作:5 w$ r8 I4 m& y
mat = plt.matshow(matrix, cmap=plt.cm.Blues, alpha=0.5) #cmap 指定颜色图色系,alpha透明度
0 R2 J$ v1 F! u$ S* e$ D% Q y( [9 G label = ["负例", "正例"]9 V% I- h) N8 T- w- H
ax = plt.gca()
4 u* H) U! L6 L7 k: t# k" k+ D0 f ax.set(xticks=np.arange(matrix.shape[1]), yticks=np.arange(matrix.shape[0]),
4 T0 r% i6 j4 g xticklabels=label, yticklabels=label, title="混淆矩阵可视化\n",: L) q% {: m& E* s' A1 ?# |
ylabel="真实值", xlabel="预测值")/ Y2 ]; G, W3 Q3 \( t) @
for i in range(matrix.shape[0]):
+ x d; ]5 W7 R- P for j in range(matrix.shape[1]):
& h' w4 k" z" O: I) z plt.text(x=j, y=i, s=matrix[i, j], va="center", ha="center")( y! _: `+ F3 P! [! y7 [
a, b = ax.get_ylim()1 |& Z1 G# v; N) i
ax.set_ylim(a + 0.5, b - 0.5)' J! Y5 |3 F+ B7 I! [ w& J4 a2 s5 n
plt.show()
, f/ \2 Z9 s& l ; _8 }$ Z; D0 i* s- s
, W, O: F5 L) ?7 i7 T 代码解析:4 R7 q4 }/ ~3 ^$ A. X
matshow( ) 绘制矩阵,alpha 透明度" b, w# [* ]9 f3 |: |+ k- t3 B+ O
结果:
- g7 L' @6 d+ B$ Z9 U c
. O* M8 Z3 \) ~7 M! a7 H% ]
练习:
. q# Q( w1 v" q2 F6 `
, U, E! ], j" p$ | 关于混淆矩阵,说法正确的是( ABCD)。【不定项】2 }+ O% {# [+ o7 |! N6 }# }
A 混淆矩阵可以用来评估分类模型。
6 G3 j" d" b5 c$ N2 ]( M: v6 @8 H B 混淆矩阵中,TP与TN的数值越大,则分类的效果越好。
9 {. W7 Q3 {% a V7 g C 混淆矩阵一行元素的和代表某个类别的实际数量。0 W& d/ S$ R2 w/ N& k- E* x
D 混淆矩阵一列元素的和代表某个类别的预测数量。) ~8 ^/ @ ]! ]3 ? r
3、评估指标/ Y3 t. F. C2 O0 x
8 m6 C" K8 c. e0 |3 z 对于分类模型,我们可以提取如下的评估指标:" J5 _+ l2 d0 _/ {8 x) n
& t8 n7 O1 S- P5 z2 G 正确率(accuracy)' R+ \7 Q( ^$ m3 l
精准率(precision)3 i( q$ {5 S2 g6 G* N! X
召回率(recall)% Z6 ^+ }4 m8 f7 X
F1(调和平均值)
3 u& ~( r9 q5 m* i9 e0 h 3.1 正确率. D9 }: Y. N% v, A
' W, p5 @/ `" o Z3 {) f
正确率(准确率)定义如下:9 F' L. {% F/ T( |9 C U
衡量所有样本被分类准确的比例。7 M+ B9 D) z6 P
Accuracy = (TP+TN) / (TP+FP+TN+FN)$ A: K( A" x( I7 v: `" o
( L. \* C/ _' G/ v 预测正确的数量除以总数量。 k. L" i9 y1 j. I- Y
+ y; Q3 W* q/ b) o+ @6 q 3.2 精准率
. V7 H* a C& d8 m' F
, W$ Y) S) O: g a+ |* ^5 n 查准率(精准率)定义如下:2 k+ K; S" x! b! s! |- v
衡量正样本的分类准确率,就是说被预测为正样本的样本有多少是真的正样本。& {$ o% y: c; i& u |& A7 r/ J8 L& i
Precision = TP / (TP+FP)0 {8 o; w6 M" G" F, q1 R( Q
6 _, P, P6 k. Y1 d$ x2 ]1 U 精准率只考虑正例。+ I' A, z4 P3 d" }8 a% A B
6 a. \$ r- D+ G, Y9 K8 o
3.3 召回率+ H- `+ X' R( [. k) L/ l4 S
# {1 M! M# {% r D8 B9 x" S 查全率(召回率)定义如下:; x$ d y( F! H+ N# ^6 i k
表示分类正确的正样本占总的正样本的比例。1 B. m$ `% |8 k* r* X
Recall = TP / (TP+FN)# `" V& `" i9 t+ A4 Q
4 E- Q1 s, y8 p. s
9 W1 H0 r6 B) x `$ H7 J6 C" L 3.4 调和平均值F1( w+ n" y. n+ x. \4 S) t2 _
7 f0 [: m6 G$ U2 A- p- O- G
F值(F1-scores)调和平均值F1定义如下:. N: t/ h0 e1 @" W) p6 o3 ^
精确率和召回率的调和平均。" G) B9 [1 @3 `+ }+ K
精准率Precision和召回率Recall加权调和平均数,并假设两者一样重要。3 `, m3 \& R5 g5 v
( G4 `4 x7 M6 h8 f( s6 i, n( Y F1-score = (2Recall*Precision) / (Recall + Precision)0 P/ t& s/ z" i% a" E% [& v6 N
; a' t+ Z2 B/ `; ] 精准率和召回率是一对矛盾的度量。一般来说,精准率高时,召回率往往偏低;而召回率高时,精准率往往偏低。通常只有在一些简单任务中,才可能使二者都很高。7 @# G3 ]- |" s2 N* j/ E
最好的分类器当然是准确率、精确率,召回率都为1,但实际场景中几乎是不可能的,而且精确率和召回率往往会相互影响,一个高了另一个会有所下降,因此在实际应用中要根据具体需求做适当平衡。. L, Q) i: H$ K8 ?% r8 l
让我们做个练习加深下印象吧!6 ]/ g3 S7 b5 Y; ?
9 S/ x$ h1 L( { 以下说法正确的是( C )。
+ }: C! p9 _; ?/ p" G6 r4 p A 使用正确率去评估一个分类模型,效果会比精准率更好。1 w6 q6 ^" e1 ~& r8 u* J. {
B 使用精准率去评估一个分类模型,效果会比召回率更好。
" m5 S5 j, {% _3 Z2 j& ?' Q5 o; i C 精准率与召回率通常要联合使用。) |1 _ z. i" ]
D 精准率与召回率如果有一个值较低,F1值也可能会较高。
, j" c1 t% V. T' h8 J# l 如果精准率和召回率我们只能选择重视一个,我们会更看重( C )。
& P9 D8 y0 m2 T* `4 C* A A 精准率。+ T4 v5 a' O6 W, K& G
B 召回率。! j2 ?+ T! x7 _( P+ j; B
C 具体场景不同,重视谁也会不同。7 h( d, Q9 N. @" s6 w( p
接下来我们通过程序来说明下:
1 I: ~) A3 h F/ G' {0 C9 z7 |/ k from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score" `' ]8 {8 n" R; | a" y4 ~+ [
7 S9 y( g3 Y s" }$ h2 Q* D
print("正确率:", accuracy_score(y_test, y_hat))
3 H- m; {" Q/ _ L/ z" s7 Q, d8 g # 默认将1类别视为正例,可以通过pos_label参数指定。
. U2 ^( K/ B5 b- v print("精准率:", precision_score(y_test, y_hat))
" V/ |5 `! E0 Y# k& t5 b* ?& L+ l print("召回率:", recall_score(y_test, y_hat))7 Q) `' Y9 C1 p7 q1 g: Q& |
print("F1调和平均值:", f1_score(y_test, y_hat))7 X4 [( j$ _4 w/ D
# 我们也可以调用逻辑回归模型对象的score方法,也能获取正确率。
1 C: Q( ]" z. m4 F$ H # 但是需要注意,score方法与f1_score函数的参数是不同的。8 j6 g( L8 }& \% S/ n2 o
print("score方法计算正确率:", lr.score(X_test, y_test))
1 k! X3 }4 ^: p* x" X( u
2 G1 b3 Z$ D/ F2 I, O6 o4 h& N S ~) F 8 A, J5 p9 z1 }( X
结果:
% c) X& k" }+ E# V3 w# q0 v
8 d; {8 |( V1 [ 除此之外,我们也可以使用classification_report函数来查看模型的分类统计信息,该方法会返回字符串类型,给出相关的分类指标评估值。- P3 z2 o$ L5 k5 Z, u: d+ L' ]
from sklearn.metrics import classification_report, s$ I$ ^+ d6 c6 O! s
3 M" ~" [/ Q, v2 r5 {2 M* T
print(classification_report(y_true=y_test, y_pred=y_hat))( q9 l2 I5 K! c: J3 n& A
" i+ \2 S4 H( e0 K6 C7 s9 h5 p
+ P( q3 B% U5 l/ F
结果:
. W& s# P: J# S" I0 H, I
/ d# n, s/ `. G8 K/ W# y( V
6 K5 e5 s. K- E1 }5 ?; {
练习:0 g3 V; C. e: E9 I7 f
' s3 x& k( w. I ?- Z* W3 L+ @
如果使用精准率与召回率评估二分类模型时,我们应该将哪个类别设置为正例? (B)
/ |* C q9 e H/ Y A 随意* C" y% }, A. L
B 关注的类别# K* c3 w" N! T
C 不关注的类别( b& n6 z q# g
4、ROC和AUC
: q* J' r( @+ o' ?/ F% C" \ * Q) [6 a, h5 t# c W5 w
ROC(Receiver Operating Characteristic)曲线和AUC常被用来评价一个二值分类器(binary classifier)的优劣。6 A5 W3 H( X1 N, C' ^) z
8 M! s) K! v" G6 G+ U/ G: j
4.1 ROC曲线' d8 G: t7 t* `# Q9 n$ W; b; K
7 G0 v6 u4 P# q1 q | C ROC曲线(Receiver Operating Characteristic——受试者工作特征曲线),使用图形来描述二分类系统的性能表现。图形的纵轴为真正例率(TPR——True Positive Rate),横轴为假正例率(FPR——False Positive Rate)。其中,真正例率与假正例率定义为:% G5 S; R( \ ~7 B
6 o# x( u: F) e% y
ROC曲线通过真正例率(TPR)与假正例率(FPR)两项指标,可以用来评估分类模型的性能。真正例率与假正例率可以通过移动分类模型的阈值而进行计算。随着阈值的改变,真正例率与假负例率也会随之发生改变,进而就可以在ROC曲线坐标上,形成多个点。
# C0 d) @% s2 s- u
b5 T% ~0 u4 E ?2 I ROC曲线反映了FPR与TPR之间权衡的情况,通俗来说,即在TPR随着FPR递增的情况下,谁增长得更快,快多少的问题。TPR增长得越快,曲线越往上凸,模型的分类性能就越好。
9 [( }$ _& U' p e1 @
' V- L+ x* [) ?% _! o$ Q. Q; v9 ? ROC曲线如果为对角线,则可以理解为随机猜测。如果在对角线以下,则其性能比随机猜测还要差。如果ROC曲线真正例率为1,假正例率为0,即曲线为与构成的折线,则此时的分类器是最完美的。
- ?& i" G* e& N, p2 N9 v ' [1 s; d+ ?, Q0 Q: a
下图就是ROC曲线的一个示意图:$ p4 s" z5 ~0 H! l' J
5 c" M: ]- e2 T& z$ p7 u
ROC曲线横坐标是FPR(False Positive Rate),纵坐标是TPR(True Positive Rate)
0 N, j; S& D) ]: x a 接下来我们考虑ROC曲线图中的四个点和一条线。
V# e8 v H4 R
& {! s3 s D) c$ K' C8 g$ F 第一个点,(0,1),即FPR=0, TPR=1,这意味着FN(false negative)=0,并且FP(false% w3 ]: m& M) j8 m: X: T- j
positive)=0。这是一个完美的分类器,它将所有的样本都正确分类。
% U$ g- r# _8 a: ~! i) ?6 G 第二个点,(1,0),即FPR=1,TPR=0,类似地分析可以发现这是一个最糟糕的分类器,因为它成功避开了所有的正确答案。
2 S" b- L" z: h- |5 m; Q4 c; j" w# o8 ~ 第三个点,(0,0),即FPR=TPR=0,即FP(false positive)=TP(true
" t! J9 ^, c' }% c( I positive)=0,可以发现该分类器预测所有的样本都为负样本(negative)。
" ~; c% [! b0 u5 B; t2 Z 第四个点(1,1),分类器实际上预测所有的样本都为正样本。经过以上的分析,我们可以断言,ROC曲线越接近左上角,该分类器的性能越好。. B2 o# H1 ]$ b
如何画ROC曲线:0 q0 @# h* K/ { Z
$ d3 `. S, u4 q$ T. G- `+ Y; u1 c4 V 对于一个特定的分类器和测试数据集,显然只能得到一组FPR和TPR结果,而要得到一个曲线,我们实际上需要一系列FPR和TPR的值,这又是如何得到的呢?我们先来看一下wikipedia上对ROC曲线的定义:
& J ?, Q7 @( Q" K# p" L; Y C' e: z) X* i/ C
A receiver operating characteristic curve, i.e. ROC curve, is a
0 E$ i+ f/ }$ L, x; Q3 [ graphical plot that illustrates the diagnostic ability of a binary
, n. E0 A8 L5 X classifier system as its discrimination threshold is varied.; i3 n/ A7 q0 a9 ~
译:ROC曲线是由一系列因区分阈值变化产生的点,用于描述二分类模型的判断能力
5 z. y9 L& l! n4 H9 E& ` ?: q( C 这里的关键在于 “its discrimination threshold is varied” ,因为对于一个二分类模型,它的输出结果其实是判断这个样本属于正样本的概率值,假如我们已经得到了所有样本的概率输出(属于正样本的概率),现在的问题是如何改变“discrimination threashold”?我们根据每个测试样本属于正样本的概率值从大到小排序。下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率
6 d7 a+ H P9 R: ^) U( d
. [# Y, U; z; V- W4 s3 f 然后我们按照样本的score值,从大到小依次作为阈值,当样本score值大于等于阈值时则判定为正样本,否则为负样本。
/ D% D* W" `0 d" ]5 e; `2 I9 G 例如第一个阈值取0.9,这时只有id=1的样本被预测为正样本,其余都是负样本,此时TPR=1/1+9=0.1, FPR=0/0+10=0。还例如:对于图中的第4个样本,其“Score”值为0.6,那么样本1,2,3,4都被认为是正样本,因为它们的“Score”值都大于等于0.6,而其他样本则都认为是负样本。
6 t1 w3 Z4 s6 n9 F f# U6 Y6 w. u S
详细如下:+ _; \/ f# r/ d$ ^
5 I9 [5 Y2 `" j1 F 由此我们便得到了一组(FPR,TPR)的值,可以绘制出ROC曲线:
6 t4 I$ m1 b; P% F" Y
8 J7 _/ @( J5 D" h' Z9 k1 Y
当我们将threshold设置为1和0时,分别可以得到ROC曲线上的(0,0)和(1,1)两个点。将这些(FPR,TPR)对连接起来,就得到了ROC曲线。当threshold取值越多,ROC曲线越平滑。3 g }( v. F7 i9 [0 @' O
6 j; c5 ?! K& b# M' _/ s' b: i
4.2 AUC2 w& H2 X1 P+ J) O- w
5 Z- S+ \7 z4 ~% w
AUC(Area Under the Curve)是指ROC曲线下的面积,使用AUC值作为评价标准是因为有时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而AUC作为数值可以直观的评价分类器的好坏,值越大越好。
" C7 e; z) P4 \9 c t; s- x# s8 j
& G+ t' x5 W5 v9 Q AUC是ROC曲线下的面积。6 u \' B4 D& X* u [9 F
AUC的取值为[0.5-1],0.5对应于对角线的“随机猜测模型”。7 p0 s- u+ L; _6 Z% w) { V6 @
AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前面,从而能够更好地分类。
: k0 ^# m8 O7 s+ W
: k t2 x C3 R; g. t& f# V7 d 从AUC判断分类器(预测模型)优劣的标准:. C. E" m0 C' H+ t/ I6 t' [
& U* z# Z' V0 J% _9 R4 O3 @
8 @0 K0 J. Y* } 例如一个模型的AUC是0.7,其含义可以理解为:给定一个正样本和一个负样本,在70%的情况下,模型对正样本的打分(概率)高于对负样本的打分。# n* M5 b9 g9 Y
& V7 n- @. N& |2 @: `2 R
三种AUC值示例:: ^; {4 ~6 x% x. L3 @
) m* R' @9 t% @' ~, `3 \" | 简单说:AUC值越大的分类器,正确率越高。( D s) w+ C0 V* e& w
, g, z! ~6 X2 } X, U
那么为什么要用AUC作为二分类模型的评价指标呢?为什么不直接通过计算准确率来对模型进行评价呢?
$ S( n8 p9 N( z# B 因为机器学习中的很多模型对于分类问题的预测结果大多是概率,即属于某个类别的概率,如果计算准确率的话,就要把概率转化为类别,这就需要设定一个阈值,概率大于某个阈值的属于一类,概率小于某个阈值的属于另一类,而阈值的设定直接影响了准确率的计算。也就是说AUC越高说明阈值分割所能达到的准确率越高。
5 c0 y- v0 j5 h b8 @8 ?$ _7 p 7 R/ k1 B0 v, w9 x* k) }
小练习:
/ N% l ]* v3 G( u% B8 L 1 v; o# i8 m+ L
以下说法正确的是( ABD)。【不定项】9 l7 X- ^. r( T N+ C$ f
A 随着阈值的降低,TPR与FPR都会增大。& R4 j5 S Q# r! W4 X% u8 _' c
B TPR与召回率的值是相同的。
! S) E$ U2 N( q, `3 { C 如果AUC的值非常低,例如,0.1,则该模型效果很差,也很难调优。6 Q) y/ C; V, b
D 无论是什么分类模型,ROC曲线一定会经过(0, 0)与(1,1)这两个点。$ I+ p$ x3 W9 D" C- K) ~5 ?
4.3 ROC曲线程序示例
3 C3 H# h4 y$ G. H6 e. N ) ?" x" ]" q% T9 c/ ^ K* ?
我们首先来看一个简单的程序示例,借此来说明sklearn库中,ROC曲线的实现细节。
/ Y. J4 B! f S7 B
8 x* }3 B) d* ^ 4.3.1 roc_curve函数的参数" \" x4 }4 w! U* Y; `
import numpy as np
$ k& X( f1 i, n, z& W from sklearn.metrics import roc_curve, auc, roc_auc_score
' [" V2 U2 d7 i5 W; F: d2 G) v y = np.array([0, 0, 1, 1])7 X1 ? ^6 M1 D' F
scores = np.array([0.2, 0.4, 0.35, 0.8])
3 M7 B" T7 z! g # 返回ROC曲线相关值。返回FPR,TPR与阈值。当分值达到阈值时,将样本判定为正类,# u6 v y7 r" ^2 i& p
# 否则判定为负类。5 y3 x- F @4 A! R( z6 f. G
# y_true:二分类的标签值(真实值)。
; j/ y, c5 D4 y' Z% u # y_score:每个标签(数据)的分值或概率值。当该值达到阈值时,判定为正例,否则判定为负例。
Y! h! z( Q' } # 在实际模型评估时,该值往往通过决策函数(decision_function)或者概率函数(predict_proba)获得。
% C+ F: H) ] o% O/ I& y" ]- k # pos_label:指定正例的标签值。
+ ^) u) }9 c$ |# o; b fpr, tpr, thresholds = roc_curve(y, scores, pos_label=1)
% a+ D# g' I7 e4 p3 u, E print(f"fpr:{fpr}")
+ W- v6 F. U3 D- J print(f"tpr:{tpr}")( J- B& `7 s$ A
print(f"thresholds:{thresholds}")- n; ?. T; B' m& R( H/ e" M* S
# auc与roc_auc_score函数都可以返回AUC面积值,但是注意,两个函数的参数是不同的。9 d* H- [" w( b4 P7 s- i4 J
print("AUC面积值:", auc(fpr, tpr))" z* ]* X8 N1 X
print("AUC面积得分:", roc_auc_score(y_true=y, y_score=scores))
6 u" X! p& [1 z- T2 Z #### 3.3.2 roc_curve函数的返回值
* Q6 f/ w6 X: h0 z7 X( J; Y9 R6 K# k # b( K( d8 H3 }$ t j6 o, a) V# r
结果:, o2 i/ ~, N* g0 K, e( v% _/ Z
1.8 是怎么来的?, Q0 d1 c- x @3 J7 s
1.8是阈值中最大值+1(0.8+1)得来的。为什么这么算?因为要使得最开始得到的所有阈值都不会超过这个值,才能过(0,0)和(1,1)这两个点。
" S; m5 I0 n, Z# t& h
3 l# T& J6 h8 N' ?+ u 4.3.2 roc_curve函数的返回值
3 i) V0 u3 ]- X) [1 C
' Y3 Z9 }, @- W' s3 U5 V; B" P roc_curve函数具有3个返回值:
o+ n5 b6 m# Z( ?% L; Y$ {; D & M9 b' [( r1 P7 \
fpr 对应每个阈值(thresholds)下的fpr值。
5 [; X _7 F) S) m* j n tpr 对应每个阈值(thresholds)下的tpr值。: q' t6 `$ e: a: M( d! p
thresholds 阈值。& Y1 e7 w! w( t3 A
roc_curve函数会从y_score参数中,选择部分元素作为阈值(选择哪些元素属于实现细节,会根据sklearn版本的不同,也可能会有所差异。),然后进行降序排列,作为roc_curve函数的第3个返回值(thresholds)。同时,根据thresholds中的每个元素(阈值),分别计算fpr与tpr。
, C, c5 \/ I+ o: J iris = load_iris()9 w% L1 u/ |, o- i" h
X, y = iris.data, iris.target
* K% J- s% Z( q' @& I) ~5 P$ I X = X[y != 0, 2:]3 M3 x l% i8 f( ~6 `5 Q, ]
y = y[y != 0]
# P' R5 ~# S. x: T. i; ? y[y == 1] = 0
) B, K. [" }% n+ S. [9 | y[y == 2] = 1; F0 ~7 ]6 N) g- i( h# r+ b
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25,; _" {% ?& y: Q, ?5 ]/ I
random_state=2)' g. Y2 A" w( L% S( I5 ?
# lr = LogisticRegression(multi_class="multinomial", solver="lbfgs")
8 x* p& X9 E, S lr = LogisticRegression(multi_class="ovr", solver="liblinear")8 B2 Q. l% i1 i9 b$ Z" i* u& m2 a7 M
lr.fit(X_train, y_train)
# g: D) @7 U; O4 H! K1 k6 s # 使用概率来作为每个样本数据的分值。 E+ R. M! E% v" O# }
probo = lr.predict_proba(X_test)3 W2 }: d* @ C J- D* b
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=probo[:, 1],9 g8 C& Q1 N) W( n! e( G
pos_label=1)
' D3 c* u4 L5 d! x! R; h N display(probo[:, 1])
3 B) o% n1 R! [$ ^9 x+ S # 从概率中,选择若干元素作为阈值,每个阈值下,都可以确定一个tpr与fpr,2 M( i( ^, ?1 E7 |, u
# 每个tpr与fpr对应ROC曲线上的一个点,将这些点进行连接,就可以绘制ROC曲线。
- T9 o" H3 x4 K- q, X/ j display(thresholds). Q1 V! [! {1 h: Z9 O6 Y% {
* K6 v6 F# z; p( [& M0 ^ W
结果:
3 r. Z! V) O' A
, I1 d$ E0 [$ z7 X
. O$ L3 d' F' ~% C" o2 z9 ~* C7 _
. d# V& ~# T* Z* ` # 随着阈值的不断降低,fpr与tpr都在不断的增大。
% Q7 T8 r1 O/ g k i* u% H fpr, tpr) x& X$ P! {' B5 ?
: k5 o- Z: S% o' P8 s) c- K 结果:
. U( ?, V q% F! h
7 n. V; Z7 N/ a% d$ _
" `1 t7 {2 D" o# n% W6 _/ t5 _7 b 4.3.3 绘制ROC曲线
0 a! k! K' e0 _ 有了fpr与tpr的值,绘制ROC曲线是非常容易的,只不过是最简单的一个plot而已。: c, v% n( \7 b- {6 R1 A8 o
plt.figure(figsize=(10, 6))
' J9 K* ^- W2 x& E6 x plt.plot(fpr, tpr, marker="o", label="ROC曲线")4 s' h) b, X* O; u
plt.plot([0,1], [0,1], lw=2, ls="--", label="随机猜测")/ w& o; ] F/ x4 R Q( ]
plt.plot([0, 0, 1], [0, 1, 1], lw=2, ls="-.", label="完美预测")" H1 c8 Z; L( q& ^8 l) [
plt.xlim(-0.01, 1.02)
& j+ s* y' E2 C( t$ _9 Z# z plt.ylim(-0.01, 1.02)
% W7 ^0 k1 \0 _3 g9 b2 S plt.xticks(np.arange(0, 1.1, 0.1))3 V1 r. O7 ^2 Q
plt.yticks(np.arange(0, 1.1, 0.1)): b" M6 x9 h+ z8 `: q3 C2 N( y
plt.xlabel("False Positive Rate(FPR)")3 V `0 o/ c6 U% l/ o9 L: t& g$ g* |
plt.ylabel("True Positive Rate(TPR)")5 B1 f3 D1 n6 @* q! J6 P
plt.grid()4 s' W$ p4 N8 X0 p: j6 Z' Z
plt.title(f"ROC曲线-AUC值为{auc(fpr, tpr):.2f}")- C* p/ G6 `% u, H! V& b% N9 {0 E
plt.legend()( ?( w: e1 o+ ?7 K
plt.show()4 {9 M, r* B' }
% L* P9 y h1 N; b ' ], o' X& F2 m0 S' ^4 G3 V
5、总结
x% c3 y2 V9 u, m, F: q: l( l# g
/ r# h6 k2 s# {+ D; j9 ? 混淆矩阵的含义。; f/ t+ w/ l: a
正确率,精准率,召回率与调和平均值F1的含义。
, ^( b0 |( ]7 J+ J ROC与AUC。 J ?# q8 g# M' o+ P
/ q. |. M% z& n* X+ O
参考资料:
$ j, D$ |: w' _* R: y- u8 p 1、https://blog.csdn.net/zuolixiangfisher/article/details/813282977 \( {" r' l+ r" d8 x
2、https://www.jianshu.com/p/2feb00839154, d* ]" _; M% y2 C$ h. T' k; l
3、https://www.cnblogs.com/kamekin/p/9788730.html
5 f' s0 u; Z0 D+ C7 V% {5 Q* x 4、https://www.jianshu.com/p/c61ae11cc5f6
" _' X+ d( B0 X, ^ ————————————————
* Y2 O, Q9 J6 l# D 版权声明:本文为CSDN博主「糖潮丽子~辣丽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
7 }* R+ ?2 V! S' ^. H: E6 T$ F& F 原文链接:https://blog.csdn.net/qq_39783601/article/details/105600700
) }+ |. Q" i, R0 d% i* n& O. d/ m ? . _9 g* |4 E9 p
1 Q! x4 Y2 w1 o6 m A
zan