数学建模社区-数学中国

标题: 详细讲解分类模型评估 [打印本页]

作者: 杨利霞    时间: 2020-4-19 11:53
标题: 详细讲解分类模型评估

( E% t9 u9 }7 K7 S/ j& u详细讲解分类模型评估分类模型评估6 _( ]3 D3 T/ w  K# a' ]7 |) A

2 y& B: Z; H4 X1、分类模型
9 y* P4 e8 V* t% \% F' W# g# n主题:如何对分类模型进行评估4 V0 U. e' ~* U% w
目标:
: Q8 d4 [2 D* s* T2、混淆矩阵
: Y- {: o  O% @0 j3、评估指标( f1 I, a0 Q/ H$ b$ o
3.1 正确率
7 B, `; M1 C2 J1 f3 [, R2 ^- g3.2 精准率/ W, t, X, t5 i+ G
3.3 召回率7 X" v3 r' ~6 p5 K6 m" c. ~' F
3.4 调和平均值F1
4 R5 [4 ~+ I9 y: z7 e4、ROC和AUC$ L% E; R* K; ^
4.1 ROC曲线- M; \; x+ x; ^1 m
如何画ROC曲线:. C& M4 g1 p. v% R( B& N
4.2 AUC5 N) E7 s* Y- n0 f0 _
4.3 ROC曲线程序示例1 u0 P4 D9 e4 l, E
4.3.1 roc_curve函数的参数
( o/ N: A5 c9 ^! S2 s1 s+ ^' K- M4.3.2 roc_curve函数的返回值
! p3 V9 V* n* i/ i2 f1 |. m' W# L4.3.3 绘制ROC曲线0 h( a9 G6 }. v: E. W8 \% L/ r; X
5、总结2 V- R( |( a9 G) h; y
1、分类模型5 l$ e" l$ g' G+ c0 Q, j( X5 D4 E
, T2 A3 R3 s" ^3 n) j
分类问题在我们日常生活中处处可见,比如我们对帅哥的分类,可能对帅哥分为非常帅和一般帅。比如我们平时刷淘宝,淘宝根据我们平时的喜好给我们推送产品,那我们就会把产品分为感兴趣和不感兴趣两类。
- h8 d* O( F# I; Q2 s5 \1 {. |- Y上述所说的问题就是典型的分类问题,确切的说其实就是二分类问题。
/ k, E2 S- [/ J' m9 R能够解决这些二分类问题的数学模型就被称为二分类模型。
3 b9 S7 r8 x9 w& ~1 A- b& f' G, M用数学的方式表达就是,给定自变量X,代入到我们的分类模型F,会输出因变量y,y的取值为0或1,其中0代表负样本(一般帅的帅哥、不感兴趣的推送),1代表正样本(非常帅气的帅哥、感兴趣的推送)。2 B; J  M7 _1 ~! @0 T5 H4 h
3 _9 c' p$ y* Q
主题:如何对分类模型进行评估2 K/ ]: Y& F3 z5 g/ b- b4 l0 d
: r: _& {  [4 R
目标:
: Q  R" h4 C* ^& h5 N3 c
4 y  s! ]$ u# J1 e) A" _5 I能够熟知混淆矩阵的含义。
. \) E  u+ Q$ |' w4 F: V8 o能够使用各种指标对分类模型进行评估。9 M( ~1 B' l4 ^$ f( y0 w
能够独立绘制ROC曲线,并熟悉该曲线细节。$ ]8 T  ?& e: {: z; w
能够对样本不均衡进行处理(扩展内容)。2 e* _# C: c9 H1 |6 `  P$ a+ R
2、混淆矩阵
4 z$ C  R/ ?0 ^  d
* C; n( {7 I1 M) J* P混淆矩阵,可以用来评估模型分类的正确性。
& Z8 Z) ?5 s1 U1 \' @该矩阵是一个方阵,矩阵的数值用来表示分类器预测的结果,包括真正例(True Positive),假正例(False Positive),真负例(True Negative),假负例(False Negative)。
4 p# H( d: U) H  F 1.png
% n$ g1 b$ C3 q$ M矩阵的形状是2 x 2,其中, - 矩阵的左上角表示,预测值为1,实际值为1(True Positive,简称TP); - 右上角表示预测值为1,实际值为0(False Positive,简称FP); - 左下角表示预测值为0,实际值为1(False Negative,简称FN); - 右下角表示预测值为0,实际值为0(True Negative,简称TN);
' g2 k) `, i7 a2 y! r% z+ n% G7 O* H- k
真负例(TN)+ 假正例(FP)——每个类别真实存在的负例的数量3 q/ r4 U+ X& h9 N$ I! k1 @
假负例(FN)+ 真正例(TP)——每个类别真实存在的正例的数量7 Q2 E7 [% i+ p2 ]* l
真负例(TN)+ 假负例(FN)——每个类别预测的真负例数量
) [# G6 A* q2 f5 X: t假正例(FP)+ 真正例(TP)——每个类别预测的真正例数量  L1 j/ n9 U: r5 ]6 _1 U; b6 d1 X
其中:# U$ u2 W% T4 V

* O' }7 v( D4 z. m; UTP:真正例,实际为正预测为正;
8 f& C5 Y) a8 ~9 e: |2 E) `. ZFP:假正例,实际为负但预测为正;
1 y  f0 e& @7 \8 a3 Y! |- YFN:假反例,实际为正但预测为负;- p( q  o: P$ u$ Y$ t5 V3 W
TN:真反例,实际为负预测为负) _% C6 H4 h# b1 C* S1 u0 S& p6 d
接下来,我们通过数据来看下鸢尾花的混淆矩阵:: k+ \# w: G4 K' y
import numpy as np
) p. D, W. i6 l5 D: `& S+ f' s% a8 ffrom sklearn.datasets import load_iris: j) h* A! c& C9 y, Z) ?
from sklearn.linear_model import LogisticRegression" |- X. h1 s. \3 O& m
from sklearn.model_selection import train_test_split0 t2 j4 q' j) j
# 混淆矩阵
5 Q9 `$ F: W' [' K- b: Cfrom sklearn.metrics import confusion_matrix) m9 c5 G+ m( }5 M5 U2 D
import matplotlib.pyplot as plt
% I/ U( ~# X4 K& W/ F& simport warnings
) W( ~$ ^2 A% L2 q% ~& Z; V* M  n& Q$ @" k/ w7 e$ d2 D7 V  {* C
plt.rcParams["font.family"] = "SimHei"
8 e8 {# H# M$ g' k! Zplt.rcParams["axes.unicode_minus"] = False2 x6 [# C% {, |! q8 C( g& a% `
plt.rcParams["font.size"] = 125 Y6 r8 y/ u0 S" h4 f0 S
warnings.filterwarnings("ignore")
4 ~5 h4 j4 O! D- P( }
( S, `% K' {, T2 |6 riris = load_iris()  #导入鸢尾花数据集
2 _2 ]$ r  T* _/ j, b, u. ^X, y = iris.data, iris.target
% u" T* c+ r  u9 }: E  {& [X = X[y != 0, 2:]
+ x4 C/ d& W9 n* J0 F9 ^1 Py = y[y != 0]
/ G# u6 C( H8 n9 u; I  Ey[y == 1] = 0/ _7 d. F- ]- [( S; z4 g
y[y == 2] = 1
6 A6 T8 U& a  [+ k- G. |X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=2)
1 j! [5 _1 N% ^lr = LogisticRegression()  #使用逻辑回归1 W: A, F0 n4 S% T6 e: i  g
lr.fit(X_train, y_train)
. @: H) o# C& n8 I/ I  ry_hat = lr.predict(X_test)5 b$ h% I5 Y6 t
# 根据传入的真实值与预测值,创建混淆矩阵。% X0 O7 F6 |3 n8 V
matrix = confusion_matrix(y_true=y_test, y_pred=y_hat)) L5 h% x; |  Y" r( f: a1 Q- L. M, F
print(matrix)3 v+ g7 u6 k3 x1 \- {

9 ~% N2 M2 _' U6 M* }% f  m! Z! i: `* k* J+ q* Z/ \: {
输出结果:
% Z( l  C' R5 a/ f* ^' V 2.png
& n* ~7 [+ I' W我们还可以对其进行可视化操作:2 ~1 K, o( U4 z: k* t
mat = plt.matshow(matrix, cmap=plt.cm.Blues, alpha=0.5)    #cmap 指定颜色图色系,alpha透明度
8 p/ G: t# R  e6 I& o) v4 q% e8 y( qlabel = ["负例", "正例"]
$ V* H) {, G+ U. \* sax = plt.gca()
8 U  C4 `* N# A, d; p( [ax.set(xticks=np.arange(matrix.shape[1]), yticks=np.arange(matrix.shape[0]),; Y: E+ G+ |/ R% ^  X$ U1 h
        xticklabels=label, yticklabels=label, title="混淆矩阵可视化\n",$ t4 f( w4 t! R$ h. `! h
        ylabel="真实值", xlabel="预测值")$ P' p; `0 \: p3 e. Z2 Z# h
for i in range(matrix.shape[0]):
+ F0 C, y( I' m  I5 I    for j in range(matrix.shape[1]):6 M9 b% o6 N' V" E) N+ t8 u
        plt.text(x=j, y=i, s=matrix[i, j], va="center", ha="center")& m2 g9 a  E6 A5 @$ R2 u
a, b = ax.get_ylim()3 W; x" h( G, H0 J$ b" P
ax.set_ylim(a + 0.5, b - 0.5)3 f% R1 d0 p# h$ K& j
plt.show()" B6 v: J* p; K+ \6 R7 d

7 c; v& S+ g; W, s+ ^$ O4 _5 f5 V  n1 l
代码解析:
# t" y1 P3 M& A) Cmatshow( ) 绘制矩阵,alpha 透明度
- I9 k% f! K* @4 ]; j  q& z0 J9 q结果:+ n: \% a. U8 b3 L! q" p  ^1 f
3.png 6 _5 J7 N; f/ D
练习:
2 Z0 B/ ?! P6 G+ t4 D. V+ r! [" P
0 x) Z# m" S1 y+ x2 @关于混淆矩阵,说法正确的是( ABCD)。【不定项】
' y' }; \: U. n# MA 混淆矩阵可以用来评估分类模型。
) P* Q8 l) M9 T; f% k' ?$ k0 oB 混淆矩阵中,TP与TN的数值越大,则分类的效果越好。
% Q" ^( M7 x/ K( kC 混淆矩阵一行元素的和代表某个类别的实际数量。
. l! _5 k# {( l+ ~D 混淆矩阵一列元素的和代表某个类别的预测数量。. {& h9 B- S0 B$ z2 A: f8 |/ c& M$ F! M
3、评估指标) t4 u0 }& e, A9 V7 b5 f
6 a$ p5 Y& V+ W. T! ~, z
对于分类模型,我们可以提取如下的评估指标:1 m2 C+ Z* I% F& G7 g4 y

! ?: i; `" q- X正确率(accuracy)4 Z6 O7 D7 d9 m
精准率(precision)( }& u6 h- x& Q. P- k6 P4 B# G
召回率(recall)
: N! R) m6 s7 y3 i0 Y# |- }* vF1(调和平均值)8 D  M" n  e' u* D
3.1 正确率
# `" Z7 B) h; c: \" G) y; S 4.png , S6 j. d, b" e( B2 m! v' d$ }7 C
正确率(准确率)定义如下:4 C1 \" U4 o/ s# c8 _! ]
衡量所有样本被分类准确的比例。+ B' r2 }$ b3 M( X4 L
Accuracy = (TP+TN) / (TP+FP+TN+FN)* P$ ^; K. U: h1 n8 J" D
4 @) o9 V5 c% C/ S% ?
预测正确的数量除以总数量。
! K9 ^8 N7 v1 e2 y+ Z" _, R% H6 d5 b
3.2 精准率
8 |( ?! x+ z" l& M& X9 y 5.png ( ~- b+ ?  ~, }8 O. e
查准率(精准率)定义如下:
: b( E) ~0 i* A7 Q# P% P衡量正样本的分类准确率,就是说被预测为正样本的样本有多少是真的正样本。2 A6 S# ?' c1 ^) p6 v6 b3 b
Precision = TP / (TP+FP)7 q- X$ o. I3 f

! U' e" C( S) m6 G  Q. r! I( x8 g精准率只考虑正例。
! C; W. T' f7 H& H( {. m
, f* Y  y; n+ u, o5 y8 ^3 j5 t3.3 召回率/ [6 z; a1 B- \) ^% W$ O4 u* H
6.png
5 W7 T+ j8 g$ k1 f) c查全率(召回率)定义如下:
. K. D) P! h7 K: o3 T6 g1 m/ T8 W表示分类正确的正样本占总的正样本的比例。
6 ]3 m( H& \2 @' GRecall = TP / (TP+FN)" B) \5 I% ?$ ?, Z4 m- B0 T

* h  H. A% n6 {: H) V0 [& E$ N3 r4 X" X' ~- m- T3 _# r
3.4 调和平均值F1% a8 {" W, c6 s1 m  T2 M
7.png ' @2 \/ D. ^! F) @# E5 C0 m
F值(F1-scores)调和平均值F1定义如下:
+ }* ^! b6 Y; |5 @8 e* C精确率和召回率的调和平均。
( ]; S1 [* p7 H6 s1 r. ^精准率Precision和召回率Recall加权调和平均数,并假设两者一样重要。
% t+ V( z; ?$ P0 f  _' q6 L2 Q
: J; V3 ~; W9 ~$ x6 NF1-score = (2Recall*Precision) / (Recall + Precision). l! a$ |% D) K( Q- k" l( S5 k

  s9 S. E  S/ V- J精准率和召回率是一对矛盾的度量。一般来说,精准率高时,召回率往往偏低;而召回率高时,精准率往往偏低。通常只有在一些简单任务中,才可能使二者都很高。9 m2 T9 b' H$ E- W* C1 k
最好的分类器当然是准确率、精确率,召回率都为1,但实际场景中几乎是不可能的,而且精确率和召回率往往会相互影响,一个高了另一个会有所下降,因此在实际应用中要根据具体需求做适当平衡。
! T. l$ @3 P- \3 _让我们做个练习加深下印象吧!& N# b6 d- i( j/ T- P
) s( Q# u* [/ D" v: y
以下说法正确的是( C )。
7 n' ]4 E+ C& E6 O( lA 使用正确率去评估一个分类模型,效果会比精准率更好。
& ^* x" R' F# x) U  w! pB 使用精准率去评估一个分类模型,效果会比召回率更好。
: I8 O- T5 u& `C 精准率与召回率通常要联合使用。
2 w7 W0 W4 q, {1 z  G( |2 ED 精准率与召回率如果有一个值较低,F1值也可能会较高。
1 Z* f0 M# i# k  v如果精准率和召回率我们只能选择重视一个,我们会更看重( C )。+ {- d# Y8 g2 L2 V/ j* H: _8 k7 \
A 精准率。" M* l: N7 M5 Z* ?- c
B 召回率。
: n" d# B3 g2 K: }5 b' N2 GC 具体场景不同,重视谁也会不同。
$ N/ D: o- D, u1 ~; ]$ q. z3 V- V接下来我们通过程序来说明下:
& r) ^5 H2 e. i" ]from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
, E4 L( s( \9 N: \+ j+ N$ x- H. v" {- S; p% h/ v$ x. C( k
print("正确率:", accuracy_score(y_test, y_hat))
3 ?& ^: y: j5 ^4 e! ^1 m* W' X" [1 A# 默认将1类别视为正例,可以通过pos_label参数指定。8 P( A' I+ ^; B3 c7 n1 W
print("精准率:", precision_score(y_test, y_hat))
. P- S! K9 Q& D. A; ~* N" @print("召回率:", recall_score(y_test, y_hat))1 D% \7 U; M5 i. c3 S4 ~
print("F1调和平均值:", f1_score(y_test, y_hat))1 b  }. f5 t, ]
# 我们也可以调用逻辑回归模型对象的score方法,也能获取正确率。
# i. Y/ z/ {5 ?; ?# 但是需要注意,score方法与f1_score函数的参数是不同的。) y: s- X6 P, M
print("score方法计算正确率:", lr.score(X_test, y_test))
1 e( ~# K7 h# H* D+ n5 v
6 g4 Q6 A* C' R' s* ~. q9 K/ V9 H' H4 e9 ~% O3 ~  T
结果:0 `. T, F5 b+ ]0 [+ Z( t6 {+ E
8.png   C! l& m4 q* _! @
除此之外,我们也可以使用classification_report函数来查看模型的分类统计信息,该方法会返回字符串类型,给出相关的分类指标评估值。9 q/ _2 D/ F! b, ?" l) T" p- l2 D
from sklearn.metrics import classification_report6 E% A  m( l3 n' p* H' @9 T
& P: d' n0 N/ a' N
print(classification_report(y_true=y_test, y_pred=y_hat))
% H: f. @) w# r% C
2 e7 o4 ^) W) G& ^- ~/ r1 p2 c0 i
1 b7 y' X6 e4 [+ k结果:
  R- }4 Z- v  N6 ~4 P$ q- K* { 9.png
& W# ], B) G6 {) F* X. l5 B3 _! O' `4 O" P" W6 {) W6 m
练习:
- W  G- @& o& E' Z+ h  H+ `, \3 f4 y5 }/ n/ {( V/ [
如果使用精准率与召回率评估二分类模型时,我们应该将哪个类别设置为正例? (B)* \: r5 M* I9 h  K
A 随意
3 y. L- C& z9 a5 Z, b& kB 关注的类别$ c2 h9 L6 x1 O& ~& m8 L* E% i
C 不关注的类别* D0 ~+ Y' P4 {
4、ROC和AUC) p7 f) n2 e. q

2 p) u) l# [6 `, l* L6 g! wROC(Receiver Operating Characteristic)曲线和AUC常被用来评价一个二值分类器(binary classifier)的优劣。
- O' a: ~7 u- d5 u/ j2 W! i2 d7 `2 ~8 G1 h: _
4.1 ROC曲线
  k  j9 T* E: i: `* E/ l 10.png
; _1 h: i4 U# J. o7 u3 r) A; n- DROC曲线(Receiver Operating Characteristic——受试者工作特征曲线),使用图形来描述二分类系统的性能表现。图形的纵轴为真正例率(TPR——True Positive Rate),横轴为假正例率(FPR——False Positive Rate)。其中,真正例率与假正例率定义为:$ H2 Z( T/ i1 O3 W8 W& h

" h. C& n6 c6 m+ \/ K3 [5 D& y; VROC曲线通过真正例率(TPR)与假正例率(FPR)两项指标,可以用来评估分类模型的性能。真正例率与假正例率可以通过移动分类模型的阈值而进行计算。随着阈值的改变,真正例率与假负例率也会随之发生改变,进而就可以在ROC曲线坐标上,形成多个点。
4 m1 `$ Z6 b' W9 N( N3 x
+ J: E, M: M- |# `& V7 ~7 L. MROC曲线反映了FPR与TPR之间权衡的情况,通俗来说,即在TPR随着FPR递增的情况下,谁增长得更快,快多少的问题。TPR增长得越快,曲线越往上凸,模型的分类性能就越好。
; E% ]3 L7 W2 q8 C8 b- k& a
' _1 e8 @. E3 h0 M8 qROC曲线如果为对角线,则可以理解为随机猜测。如果在对角线以下,则其性能比随机猜测还要差。如果ROC曲线真正例率为1,假正例率为0,即曲线为与构成的折线,则此时的分类器是最完美的。
8 Y: N  v# V$ Q
$ A. l2 c& J% x3 o下图就是ROC曲线的一个示意图:
# S. H- P" }9 n 11.png 1 p8 E0 R2 J+ U6 ^* B2 p7 Y
ROC曲线横坐标是FPR(False Positive Rate),纵坐标是TPR(True Positive Rate)
# M: I, ^' p9 T! h% s4 r$ ^/ T8 G- o接下来我们考虑ROC曲线图中的四个点和一条线。9 y; u; q, r7 x- i1 L

+ f* O  a% f) Y第一个点,(0,1),即FPR=0, TPR=1,这意味着FN(false negative)=0,并且FP(false
9 q1 f1 `3 `; Q, \. K5 ~positive)=0。这是一个完美的分类器,它将所有的样本都正确分类。
% l3 I! q2 f# \+ f4 @- |6 B第二个点,(1,0),即FPR=1,TPR=0,类似地分析可以发现这是一个最糟糕的分类器,因为它成功避开了所有的正确答案。& Y* ?( K& `0 Y8 A* Y+ g/ K
第三个点,(0,0),即FPR=TPR=0,即FP(false positive)=TP(true' o+ Q4 C4 B, _9 b( }
positive)=0,可以发现该分类器预测所有的样本都为负样本(negative)。
  D4 j. V0 v" Y% F. t1 N' Y第四个点(1,1),分类器实际上预测所有的样本都为正样本。经过以上的分析,我们可以断言,ROC曲线越接近左上角,该分类器的性能越好。
3 I$ b4 `/ A4 v' E2 K如何画ROC曲线:
. Q5 F! [& R9 L5 [; L; G& q1 l+ R
$ {. w" G# c& K' _. M) a对于一个特定的分类器和测试数据集,显然只能得到一组FPR和TPR结果,而要得到一个曲线,我们实际上需要一系列FPR和TPR的值,这又是如何得到的呢?我们先来看一下wikipedia上对ROC曲线的定义:9 X, f: P% ]* _$ `& e. {

! c' ]! Q8 B4 P0 QA receiver operating characteristic curve, i.e. ROC curve, is a
0 c/ d8 c1 e* K$ @# D6 l6 K4 Mgraphical plot that illustrates the diagnostic ability of a binary' e) `( ~5 @3 m/ K' M7 B6 l2 m5 R
classifier system as its discrimination threshold is varied.+ ?- e4 `; A/ k. F6 Y
译:ROC曲线是由一系列因区分阈值变化产生的点,用于描述二分类模型的判断能力0 L( K0 q, r4 V7 j+ K
这里的关键在于 “its discrimination threshold is varied” ,因为对于一个二分类模型,它的输出结果其实是判断这个样本属于正样本的概率值,假如我们已经得到了所有样本的概率输出(属于正样本的概率),现在的问题是如何改变“discrimination threashold”?我们根据每个测试样本属于正样本的概率值从大到小排序。下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率
8 J* i7 n" ~. f5 n: r; _6 h 12.png ! H1 {' ~) [6 k5 V! a* J3 G3 R
然后我们按照样本的score值,从大到小依次作为阈值,当样本score值大于等于阈值时则判定为正样本,否则为负样本。
8 G* n$ \* x# v7 M5 K! o! N例如第一个阈值取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,而其他样本则都认为是负样本。! x. p4 |$ e  E9 N7 Y

! j( }( E. H3 m/ a# ~5 A详细如下:7 U- I' N# X9 n  n
13.png
6 U; q* h( T; R. N: D1 X由此我们便得到了一组(FPR,TPR)的值,可以绘制出ROC曲线:
/ f7 G. I' a! I1 \/ G# F 14.png - x" S) w! t( z* h# |8 x
当我们将threshold设置为1和0时,分别可以得到ROC曲线上的(0,0)和(1,1)两个点。将这些(FPR,TPR)对连接起来,就得到了ROC曲线。当threshold取值越多,ROC曲线越平滑。
$ F& C/ e9 F) v) a1 S2 s& v
2 ^3 f5 g1 t, V7 C/ I4.2 AUC
4 j+ ~  @6 i/ k  D* O. M 15.png
) t8 k& J  I, ]AUC(Area Under the Curve)是指ROC曲线下的面积,使用AUC值作为评价标准是因为有时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而AUC作为数值可以直观的评价分类器的好坏,值越大越好。3 k/ L& J. T5 x, N8 r7 h$ ~) ^
8 n3 x" O/ s3 Z$ Z6 x
AUC是ROC曲线下的面积。. }! s& C' w' e  u; _5 \) S/ f! Y
AUC的取值为[0.5-1],0.5对应于对角线的“随机猜测模型”。
% v" ^0 n$ R# I' S7 `' ]  a2 dAUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前面,从而能够更好地分类。4 x# K9 W8 O5 \: @. s! N# |( h

1 h" b# E% g, F5 J从AUC判断分类器(预测模型)优劣的标准:
) ~0 a1 B) `7 K* O: D
8 S  T% \# C8 }; T, J
2 W. L! S, Z/ |/ `& I* Y- N例如一个模型的AUC是0.7,其含义可以理解为:给定一个正样本和一个负样本,在70%的情况下,模型对正样本的打分(概率)高于对负样本的打分。
+ ?; f* {8 r) \& |
! H% R9 r: Z/ w0 n2 L) k三种AUC值示例:
8 T) A7 e" o; @. C 16.png
) k# D' Z7 w; P简单说:AUC值越大的分类器,正确率越高。
9 t" f) D1 Y! Q  M
% V- b: G* h6 Z0 \* j3 e那么为什么要用AUC作为二分类模型的评价指标呢?为什么不直接通过计算准确率来对模型进行评价呢?
/ e  F$ W( w$ y& p4 y( I3 E因为机器学习中的很多模型对于分类问题的预测结果大多是概率,即属于某个类别的概率,如果计算准确率的话,就要把概率转化为类别,这就需要设定一个阈值,概率大于某个阈值的属于一类,概率小于某个阈值的属于另一类,而阈值的设定直接影响了准确率的计算。也就是说AUC越高说明阈值分割所能达到的准确率越高。; N9 m: I$ z$ T7 d" p, C& F9 {" J
$ T+ U+ f" v; o; D% `
小练习:0 ?+ n* ~5 x' ]

; o6 {! M: G2 h$ r8 r' ]- M1 L以下说法正确的是( ABD)。【不定项】
" y9 a! b0 h! S/ M; Q+ C. WA 随着阈值的降低,TPR与FPR都会增大。
1 K$ U/ s; O* ^3 M/ v% k& g& uB TPR与召回率的值是相同的。/ c- z  U$ @$ Q+ N
C 如果AUC的值非常低,例如,0.1,则该模型效果很差,也很难调优。& d! E. M0 r: n! Y
D 无论是什么分类模型,ROC曲线一定会经过(0, 0)与(1,1)这两个点。
% S- R  z0 y# p6 E4 _4.3 ROC曲线程序示例% o  \7 n, e  x, j/ i. N' I6 b

& A- r- J) l9 ^  K我们首先来看一个简单的程序示例,借此来说明sklearn库中,ROC曲线的实现细节。# W. s! g# R( j2 d

4 z, {" q& Q) u; h5 I" x4.3.1 roc_curve函数的参数& p% C' d2 [3 U: N4 Q9 b
import numpy as np
: x# H8 Q% n1 y) ^! h. E7 t3 E  Rfrom sklearn.metrics import roc_curve, auc, roc_auc_score
( a* r+ n2 z* t7 ^" n1 M% e, h* |# Yy = np.array([0, 0, 1, 1])9 Z* u: D, u4 S3 \8 z# `8 T
scores = np.array([0.2, 0.4, 0.35, 0.8])- N- h8 u- P5 p5 N- E. t
# 返回ROC曲线相关值。返回FPR,TPR与阈值。当分值达到阈值时,将样本判定为正类,
% C6 h% N! ~" D+ o5 _3 `# 否则判定为负类。
" j  z9 o) _4 e4 W# y_true:二分类的标签值(真实值)。* p* R# f& i! E/ a* _. L
# y_score:每个标签(数据)的分值或概率值。当该值达到阈值时,判定为正例,否则判定为负例。1 U' x9 P9 C2 E$ v
# 在实际模型评估时,该值往往通过决策函数(decision_function)或者概率函数(predict_proba)获得。
4 g5 }& v, h, t1 U: ^# pos_label:指定正例的标签值。
% U$ o" X/ P! }* E- Hfpr, tpr, thresholds = roc_curve(y, scores, pos_label=1)' O8 |% t1 {/ C" f
print(f"fpr:{fpr}")
0 A  E% ], x% l$ Rprint(f"tpr:{tpr}")
( H9 N) D6 o' s  ~print(f"thresholds:{thresholds}"): ^& Z  T3 ^+ }$ }% {
# auc与roc_auc_score函数都可以返回AUC面积值,但是注意,两个函数的参数是不同的。
( Q; q; |  F7 R4 @print("AUC面积值:", auc(fpr, tpr))* f. J: D* v( S% ?; n
print("AUC面积得分:", roc_auc_score(y_true=y, y_score=scores))
, x, R; w" }& R+ I1 \% J, ~#### 3.3.2 roc_curve函数的返回值
0 @" D: D/ r0 M) K; `, i8 b, E
* j6 D0 ]( b; r+ e1 O8 e% S  `9 f结果:
/ `% p0 h9 B; L4 T- H; Y 17.png 1.8 是怎么来的?
1 b6 |' N8 h8 w1 b. W; s7 R# ~1.8是阈值中最大值+1(0.8+1)得来的。为什么这么算?因为要使得最开始得到的所有阈值都不会超过这个值,才能过(0,0)和(1,1)这两个点。
: ^, {$ U, _4 g% N) Q: p
- E, `( c- n" _( t4.3.2 roc_curve函数的返回值" y& I; ?- C3 v" S# W, i% n- c( k
  B) H' ?: a, E! f+ ^# ^( z) ~* @
roc_curve函数具有3个返回值:: l% ]0 D7 @3 E& l% o( x: {+ I

& @0 A7 j4 W/ {1 P9 Zfpr 对应每个阈值(thresholds)下的fpr值。' L; b2 o5 V& x+ ~
tpr 对应每个阈值(thresholds)下的tpr值。- c4 A7 ?  r& z- Z4 S# p1 Z, ?% d, {) a4 q) E
thresholds 阈值。: S2 C! a8 B8 q' x9 C1 N: m
roc_curve函数会从y_score参数中,选择部分元素作为阈值(选择哪些元素属于实现细节,会根据sklearn版本的不同,也可能会有所差异。),然后进行降序排列,作为roc_curve函数的第3个返回值(thresholds)。同时,根据thresholds中的每个元素(阈值),分别计算fpr与tpr。
9 \+ N  e: H! \5 e* B4 H+ [iris = load_iris()$ M% e- y3 P7 `
X, y = iris.data, iris.target
4 ~" }8 _9 S$ y1 U# F; @7 u+ oX = X[y != 0, 2:]
) H7 U# Z' Q- _$ o# Gy = y[y != 0]4 C0 r: B% o% K) z
y[y == 1] = 0
, j- }$ [. l1 R$ K4 [2 F" ey[y == 2] = 1
7 }- O6 ^  s  n' vX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25,1 S/ b* f; x3 \
random_state=2)+ H3 b6 j) e7 y# U* ^+ U
# lr = LogisticRegression(multi_class="multinomial", solver="lbfgs")
' w5 h' \0 ^2 l$ ~7 U! Zlr = LogisticRegression(multi_class="ovr", solver="liblinear")9 G' ?2 i; z! z  W# j
lr.fit(X_train, y_train); X+ u3 _1 I  F
# 使用概率来作为每个样本数据的分值。
; L- m" A# S% Z7 wprobo = lr.predict_proba(X_test)/ `/ h7 O$ l* v0 }- V" X& |
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=probo[:, 1],6 c& N5 G: s  b$ H* n/ y! k; @4 \
pos_label=1): Y( I) B  T$ R% ^& X- ^* Y0 C
display(probo[:, 1])
) i& ?2 Y" B( p& U+ E' j# 从概率中,选择若干元素作为阈值,每个阈值下,都可以确定一个tpr与fpr,& R7 {! E* P) [/ u
# 每个tpr与fpr对应ROC曲线上的一个点,将这些点进行连接,就可以绘制ROC曲线。, m, O: t1 e' V! a) K
display(thresholds)
1 U2 A$ {5 J% X/ \* `) u# W$ g1 S
结果:
/ T1 L* v, T5 g  X1 \0 E2 I* X 18.png % A+ T/ a0 u0 w5 s. x

6 ?! \3 M! k8 {4 n- c! @$ l2 {& ^8 f; F1 h( j0 l, ?
# 随着阈值的不断降低,fpr与tpr都在不断的增大。9 F* I: ^2 f/ G4 ?# A
fpr, tpr
& Q/ n* v" R& `6 h
) j) r. [+ y8 d5 {: p! f0 G& M结果:
! @; g! Z, ]  K. f. N$ y& d 19.png + R2 D% n' ~5 ^. S3 ^0 m) S

; j5 u5 \6 z  x  h. ?. I& @+ a3 T4.3.3 绘制ROC曲线+ }' o  Q+ }/ T1 J
有了fpr与tpr的值,绘制ROC曲线是非常容易的,只不过是最简单的一个plot而已。
) H  {$ a" B1 W5 h( vplt.figure(figsize=(10, 6))
" {. O: z" @8 D6 c- g. o3 Kplt.plot(fpr, tpr, marker="o", label="ROC曲线")
# N3 j8 S2 ]2 F- n7 ?! _plt.plot([0,1], [0,1], lw=2, ls="--", label="随机猜测")
" Z8 O5 E/ @1 @9 j" s/ ]9 Cplt.plot([0, 0, 1], [0, 1, 1], lw=2, ls="-.", label="完美预测")
/ G0 M; t  n- o4 aplt.xlim(-0.01, 1.02)2 h- G/ O# I. x% h# \) {
plt.ylim(-0.01, 1.02)
2 y3 y& `) z8 q) d- Fplt.xticks(np.arange(0, 1.1, 0.1))
$ J* U! o7 E) n  a7 ?$ o; Y- m# Wplt.yticks(np.arange(0, 1.1, 0.1))
. g& U- R; L. o0 R4 K5 H; \4 Hplt.xlabel("False Positive Rate(FPR)")
, N9 i1 Z6 B( R; u6 }& X( t+ qplt.ylabel("True Positive Rate(TPR)"). j* b9 Y( o  `0 ]
plt.grid()1 n5 Z( k3 V& p5 e; U' k! g/ f; ^4 V
plt.title(f"ROC曲线-AUC值为{auc(fpr, tpr):.2f}")
8 }$ ^) j5 P! Kplt.legend()8 f! x  o2 H4 E' @4 z- ?
plt.show()+ p% |& t4 ~1 E( D
20.png
$ J) k6 G9 d  W8 T* J3 ~' B0 Z* Y( v1 m6 I' p
5、总结
" h0 m: K2 S6 d' u2 \$ e5 m& g4 i5 O+ o( O+ b) }3 z2 H7 e6 L- `) n1 s
混淆矩阵的含义。% j9 A# @& a. @2 J
正确率,精准率,召回率与调和平均值F1的含义。! U5 a* n; p, U9 e
ROC与AUC。
( u1 u2 y( A" m- W  {1 u5 ^5 p
: ^1 a0 d5 B& M. @0 @& [9 ^( J参考资料:
1 f( \/ D5 {, A# x1 }: H7 |+ ?1、https://blog.csdn.net/zuolixiangfisher/article/details/81328297
5 i0 |6 z% M3 p5 V; j2、https://www.jianshu.com/p/2feb008391542 N5 x/ l8 S4 F3 i, C) u6 J
3、https://www.cnblogs.com/kamekin/p/9788730.html
! Y+ f( f1 C3 E# m( j; t4、https://www.jianshu.com/p/c61ae11cc5f6
8 ]& _; c5 J+ I, V————————————————% Y; s+ D7 [  D4 i5 Q8 N3 w
版权声明:本文为CSDN博主「糖潮丽子~辣丽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
3 x; M3 I* Z# {$ t) _原文链接:https://blog.csdn.net/qq_39783601/article/details/1056007009 c9 i7 I- x' u+ ~# |+ e+ p! `7 B" e

0 G; l+ V% e# p) m1 b% ~0 K7 O$ X, C# [# S& r

作者: 1336671542    时间: 2020-4-19 12:50
非常感谢!!!!!!!!!!" {* }3 ?  B' l





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5