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