数学建模社区-数学中国

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

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

# o0 t2 @7 Z2 [& c( @0 I0 ?详细讲解分类模型评估分类模型评估
6 H- w- _; q9 Z0 Y) l2 m# p# O4 @8 b5 B2 ~6 X
1、分类模型% n& y& A+ Q" m3 b+ {! n
主题:如何对分类模型进行评估) D2 U, x# x) J5 B0 Y  X: d
目标:
( D0 W) x  [7 G/ z$ J2、混淆矩阵
. Z% f& B, A$ [  q1 p9 x3 e6 {3、评估指标/ a2 \4 \0 d  X, T# x
3.1 正确率' J1 K- l+ F6 L( ?
3.2 精准率
" @( T$ g  k3 F* E6 G3.3 召回率
" [7 f0 i5 e( v6 i+ F2 h- W3.4 调和平均值F1; _/ I  ?# b1 T* S7 T
4、ROC和AUC! R- ~$ H# V) ^
4.1 ROC曲线
2 n# @! i! W* c/ l! p如何画ROC曲线:
" U/ {1 G& Y" z6 R9 ^1 C. N4.2 AUC0 V! s1 J" s2 \% Y( c! T$ Y
4.3 ROC曲线程序示例* a. o8 A8 x7 j0 G( I, u
4.3.1 roc_curve函数的参数
3 B3 Y7 C4 t3 h4.3.2 roc_curve函数的返回值
& g0 V, Z6 N2 \- E, {  e4.3.3 绘制ROC曲线
: c8 C  `5 U3 j  q3 {' p( t5、总结
) O# T" o- @& g" d5 P1、分类模型
, S; C( Q  K( y- O6 ^
# c2 `& f- m/ H2 ^0 M# u分类问题在我们日常生活中处处可见,比如我们对帅哥的分类,可能对帅哥分为非常帅和一般帅。比如我们平时刷淘宝,淘宝根据我们平时的喜好给我们推送产品,那我们就会把产品分为感兴趣和不感兴趣两类。
8 o3 L" T% M: W上述所说的问题就是典型的分类问题,确切的说其实就是二分类问题。
! K) d+ z9 [9 i( C! u能够解决这些二分类问题的数学模型就被称为二分类模型。/ I0 a3 m" |/ [# l! y
用数学的方式表达就是,给定自变量X,代入到我们的分类模型F,会输出因变量y,y的取值为0或1,其中0代表负样本(一般帅的帅哥、不感兴趣的推送),1代表正样本(非常帅气的帅哥、感兴趣的推送)。
  ^( c' r, H6 ^1 T7 v- h* W' r: |  G* _+ O9 ~3 m6 F* z! `. e0 W
主题:如何对分类模型进行评估
( i3 j6 O% K* S) `
5 R- U% e. f- R& v/ c目标:
9 N4 d' a! R- R( Q* H2 v$ [- e% G- t; h
能够熟知混淆矩阵的含义。
& w+ X2 \1 |( \! a8 W能够使用各种指标对分类模型进行评估。
2 t% o( D2 w) T0 J3 \& ~3 @7 ~能够独立绘制ROC曲线,并熟悉该曲线细节。
2 T  C( Z7 _5 {/ C5 u能够对样本不均衡进行处理(扩展内容)。
, C- |& q! m+ C2、混淆矩阵
& E6 M3 r+ ]  D! u' V& m3 v/ V8 E4 u! O) Z1 c7 B3 t& a
混淆矩阵,可以用来评估模型分类的正确性。
6 _( R" {7 ~2 G. k5 i. V- i; h该矩阵是一个方阵,矩阵的数值用来表示分类器预测的结果,包括真正例(True Positive),假正例(False Positive),真负例(True Negative),假负例(False Negative)。
5 m  u& W8 S$ o" K! s9 H: O$ m- r 1.png
6 D, N5 a& a: ]) P矩阵的形状是2 x 2,其中, - 矩阵的左上角表示,预测值为1,实际值为1(True Positive,简称TP); - 右上角表示预测值为1,实际值为0(False Positive,简称FP); - 左下角表示预测值为0,实际值为1(False Negative,简称FN); - 右下角表示预测值为0,实际值为0(True Negative,简称TN);8 \0 V/ `# A& G) y

1 m8 E7 X& K$ f真负例(TN)+ 假正例(FP)——每个类别真实存在的负例的数量
% @- [! {6 _  B/ Z+ f- a) R假负例(FN)+ 真正例(TP)——每个类别真实存在的正例的数量6 `* W: N# r' u; C; J& g: Q, G
真负例(TN)+ 假负例(FN)——每个类别预测的真负例数量& |, Z$ S+ I3 N) f$ _7 |9 K
假正例(FP)+ 真正例(TP)——每个类别预测的真正例数量( X" ^  b4 g- s: f9 X& t
其中:
+ s$ W! s  \5 f' U2 X+ }2 i: s0 H
TP:真正例,实际为正预测为正;
5 L3 \/ a- k% F& V/ C  ~FP:假正例,实际为负但预测为正;+ H  n! q  x! C$ n
FN:假反例,实际为正但预测为负;- m" X) w# ]; E' A' H' y
TN:真反例,实际为负预测为负+ d2 q% V: z1 h; @2 F4 o: c
接下来,我们通过数据来看下鸢尾花的混淆矩阵:( C9 t3 ^# A( n& p2 ~# A3 }
import numpy as np
7 q% e  u& Z- b) v# N  rfrom sklearn.datasets import load_iris0 t) ?% d) e- A9 l2 z/ N. l' R
from sklearn.linear_model import LogisticRegression1 b& s; u+ P5 m$ ]2 q: I* H1 N3 c
from sklearn.model_selection import train_test_split8 E/ n/ O- x. B4 F/ D
# 混淆矩阵3 W% i/ W# [# h" v
from sklearn.metrics import confusion_matrix
3 O' n7 b( A5 T  R9 ?import matplotlib.pyplot as plt
" `; z! f6 `. {! Q$ l$ L6 Himport warnings
1 j- l8 k# B0 w! \/ g7 N+ F7 a- \- q; f+ ~* x  O* l1 S) f
plt.rcParams["font.family"] = "SimHei"
7 m( g/ @4 u' ?, I' v- W. r) B. ]plt.rcParams["axes.unicode_minus"] = False. A$ x- O) |# i8 ?2 P" }
plt.rcParams["font.size"] = 12- W7 u1 L$ G8 ~" d' D4 V
warnings.filterwarnings("ignore")! ~5 _% V3 K' X% t5 t2 d
: V. P2 u5 z/ G& b+ s3 ~  `5 ^
iris = load_iris()  #导入鸢尾花数据集
/ O$ d0 ^# `. A4 o& G( m1 AX, y = iris.data, iris.target3 d, b' u! k" L& N6 E; ]- ~
X = X[y != 0, 2:]6 s8 c/ L: u8 q1 r$ E) m
y = y[y != 0]' A: s+ N' ?1 e- m  J  l
y[y == 1] = 06 T$ w$ n! j  k- F+ j4 A
y[y == 2] = 1
1 L) o$ D& o* R* O# C% F( i" iX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=2)
& d: d" n- w1 N  o" w3 Elr = LogisticRegression()  #使用逻辑回归
1 t! |3 Z* y6 S1 Ilr.fit(X_train, y_train), ^! {3 L8 {) F
y_hat = lr.predict(X_test)  u% u- x! f) n* @- L
# 根据传入的真实值与预测值,创建混淆矩阵。, a( D' y% Y: o2 t: J( m$ R
matrix = confusion_matrix(y_true=y_test, y_pred=y_hat)
  _; y7 w5 l8 m: e" g7 hprint(matrix)2 W" m2 o* B, K3 U4 H+ H* d

% j) M. q7 Y5 K% w
( D: {# a7 a% R+ i' D( I3 {% t  c输出结果:1 K3 B( A) R; W% o/ `
2.png 4 T8 v/ L/ b$ w( |
我们还可以对其进行可视化操作:# R% G: R. X% W7 d7 E
mat = plt.matshow(matrix, cmap=plt.cm.Blues, alpha=0.5)    #cmap 指定颜色图色系,alpha透明度
/ F! t0 Y) W2 Llabel = ["负例", "正例"]
& N* ~" j7 o% ^& B$ Q! r1 S5 Zax = plt.gca()) H) Y. @6 u* O: {( T3 q9 t% A
ax.set(xticks=np.arange(matrix.shape[1]), yticks=np.arange(matrix.shape[0]),# g, [0 U0 L  o8 s, k; e
        xticklabels=label, yticklabels=label, title="混淆矩阵可视化\n",
2 r' G! Y2 z: i7 d4 W+ k        ylabel="真实值", xlabel="预测值")  |. j3 `( a  |8 k; [$ F5 |
for i in range(matrix.shape[0]):0 D% G( y* ?, r
    for j in range(matrix.shape[1]):  k6 P) d5 z/ E1 G
        plt.text(x=j, y=i, s=matrix[i, j], va="center", ha="center")
: y- R/ J( j, Sa, b = ax.get_ylim()
8 o, v0 p0 I! }' Gax.set_ylim(a + 0.5, b - 0.5)) I  e" Z6 y' j8 m1 d: w. y4 e
plt.show()
+ V: Z8 S; f3 `
! M3 F! z$ e/ i7 g! i5 d( n* d% w, n( q' w
代码解析:
' R# ]& ~& f+ M0 Bmatshow( ) 绘制矩阵,alpha 透明度
0 U' ]6 j1 G5 h7 {! A# n结果:
7 \' {+ f1 T* G* [9 _ 3.png * E3 G) Z  Z6 ?# `' w# V
练习:
* B; P; u/ s8 W) @: A) M! w* i; L' L+ N7 C* \
关于混淆矩阵,说法正确的是( ABCD)。【不定项】- K& g1 {7 ?# a
A 混淆矩阵可以用来评估分类模型。
" B# r3 [9 q; c; iB 混淆矩阵中,TP与TN的数值越大,则分类的效果越好。
+ B% Z/ v+ O% x6 FC 混淆矩阵一行元素的和代表某个类别的实际数量。3 \! i! q+ N0 {8 Y, H! J
D 混淆矩阵一列元素的和代表某个类别的预测数量。. e* l3 J5 {# b. Y% b
3、评估指标8 L% x; r+ K9 ~

0 j$ w' g4 q4 X) [( b: @5 O对于分类模型,我们可以提取如下的评估指标:
) d% t! E$ W8 K, l
6 q: p5 }% j9 u+ r% x. J' |6 k正确率(accuracy)
' b' @# ], b% k. F( l0 I% C" j精准率(precision)1 h+ o3 d- S; ^# Y# N
召回率(recall)% ~4 M8 v5 m) q) B5 f% P) E
F1(调和平均值)
: }+ I$ ]3 [) g, U- N% F% e2 @: w2 }3.1 正确率) `( j& I  ^2 {8 C7 I6 E
4.png
! n9 ^& ^8 }; a正确率(准确率)定义如下:
2 p) Z- V7 }& Z" w& V3 w( _6 n- @衡量所有样本被分类准确的比例。
2 v; r$ k: J0 v0 g0 s3 m7 {  T* tAccuracy = (TP+TN) / (TP+FP+TN+FN)2 Q) h1 y: g7 w) m2 X( k, b9 z

! v" M3 D  K' Q预测正确的数量除以总数量。
% O! l4 ?3 U8 O- Y) J4 a3 e* o: Q, i" K7 |- j0 \% o
3.2 精准率
: V4 P' l+ Z3 A' C; o 5.png 3 ^& g$ s% k, b0 Y" r
查准率(精准率)定义如下:( C6 w8 b+ [7 {$ f9 f/ z+ b
衡量正样本的分类准确率,就是说被预测为正样本的样本有多少是真的正样本。
) G5 I2 r3 b4 f6 @Precision = TP / (TP+FP)
6 [+ w& f. o) N9 f% u/ \/ l2 G5 q% }2 F* `  T4 m) B$ b/ F# b
精准率只考虑正例。
/ ^7 v, P4 Z# G# ^' z$ T- Y  k; z- J9 Y7 U2 d" O$ g4 ^
3.3 召回率
0 c& R2 c: @- T$ D. U( a 6.png " N+ Y! H, ?5 W7 l: F( `( ]: g+ S* `% F
查全率(召回率)定义如下:2 d6 T: r, s/ `& `
表示分类正确的正样本占总的正样本的比例。9 A2 C. f  |/ }6 d) Y
Recall = TP / (TP+FN)1 I. c& Q4 T1 \* O
! a. g5 Q5 M5 P; h
! r1 `7 ^3 ~# W6 Z$ o
3.4 调和平均值F1
  X+ O& P, i% X  v/ c% l 7.png
7 Z( V7 |1 h# E, u' EF值(F1-scores)调和平均值F1定义如下:( o  E5 w8 F3 ]: m  R& _& `& r9 u: @
精确率和召回率的调和平均。, g( e& Q6 ]# ?/ U* G. N
精准率Precision和召回率Recall加权调和平均数,并假设两者一样重要。
4 ]5 X) V# Y  X# L$ h  U+ h( j- z, t, x0 _5 N9 X- D
F1-score = (2Recall*Precision) / (Recall + Precision)
3 B* k- y9 u0 o5 }2 E  j
! I/ c4 q! }& N: F. A1 _, ]) @精准率和召回率是一对矛盾的度量。一般来说,精准率高时,召回率往往偏低;而召回率高时,精准率往往偏低。通常只有在一些简单任务中,才可能使二者都很高。
$ C5 |; {) |5 V8 u: Q最好的分类器当然是准确率、精确率,召回率都为1,但实际场景中几乎是不可能的,而且精确率和召回率往往会相互影响,一个高了另一个会有所下降,因此在实际应用中要根据具体需求做适当平衡。
( s0 @4 i) e8 |% _" k0 C让我们做个练习加深下印象吧!
' k. k$ k0 b7 |+ M  S# O" W  l5 j  @6 v8 C
以下说法正确的是( C )。! F6 F; z: C' O0 p+ r9 X! e
A 使用正确率去评估一个分类模型,效果会比精准率更好。9 L  d1 X! m5 L4 x' j3 W# {2 U
B 使用精准率去评估一个分类模型,效果会比召回率更好。
0 h/ p# T3 |! k" `) fC 精准率与召回率通常要联合使用。
- }, N+ [# b# h5 iD 精准率与召回率如果有一个值较低,F1值也可能会较高。
& r6 _3 p7 V2 l9 l2 k7 K  O. n如果精准率和召回率我们只能选择重视一个,我们会更看重( C )。
6 W! o% {" K) i3 O, w, U  IA 精准率。- g0 F/ v* C% r# r& g( @
B 召回率。
& ^9 n" h0 }/ F1 u$ LC 具体场景不同,重视谁也会不同。1 Y$ Q  a1 W9 x  j9 j5 w' a9 f
接下来我们通过程序来说明下:! ~! [$ G) l- w" J7 O/ G
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score6 X5 f" \  r2 J9 l' P
0 g( t3 A" K6 n. h- q
print("正确率:", accuracy_score(y_test, y_hat))
. o) e& H; j+ d5 p( |/ b  z8 v# 默认将1类别视为正例,可以通过pos_label参数指定。; w3 n1 A0 J. s
print("精准率:", precision_score(y_test, y_hat))* W* r2 Z( W/ M- }- ?7 Q
print("召回率:", recall_score(y_test, y_hat))5 S! ~, _2 ]7 N3 D  m$ W- i
print("F1调和平均值:", f1_score(y_test, y_hat))' E3 F. ^5 ]( B6 S  U6 z5 ^
# 我们也可以调用逻辑回归模型对象的score方法,也能获取正确率。) k5 u0 d1 M9 A) p# M
# 但是需要注意,score方法与f1_score函数的参数是不同的。
. z+ d' w( m  z" Y5 tprint("score方法计算正确率:", lr.score(X_test, y_test))
7 q" d% O  f9 g) r+ }9 i, |' z( k# C$ a' x' x: Z( C

8 g: q/ _8 ^! y* L! [6 e9 u结果:
7 y+ n* O$ m/ S/ p: n 8.png 2 e$ b/ |" H) T& i
除此之外,我们也可以使用classification_report函数来查看模型的分类统计信息,该方法会返回字符串类型,给出相关的分类指标评估值。
8 C4 g: ~. T' Bfrom sklearn.metrics import classification_report3 R8 i. N: {$ T: ~2 N6 @  m
4 b7 G: [$ p! ]- Z
print(classification_report(y_true=y_test, y_pred=y_hat))
1 i, |+ @& w5 g& {7 d- I, @3 f& S( q% X3 v( `% E. s! R

) _, w8 j% |7 i结果:5 e4 d% o& f0 m2 l5 E& R3 [. u
9.png
- P& u' A) ~  k- ?. b
: {7 W# K8 Q( H7 t  e  h练习:
0 v: e; Z9 c. D( v" j- X) i6 V# n0 i' N2 O+ A& W
如果使用精准率与召回率评估二分类模型时,我们应该将哪个类别设置为正例? (B)
, L1 G: X4 t$ C( ?! Q/ oA 随意
5 c6 X" S( ^( `5 n3 }B 关注的类别4 h  [' y+ ?$ h* D2 A( l
C 不关注的类别3 a& n( X9 g  }9 C' p1 Y
4、ROC和AUC$ `& R) ?- T; L6 T- }  B: i

' n  y! }9 e5 ~9 ?! y" {ROC(Receiver Operating Characteristic)曲线和AUC常被用来评价一个二值分类器(binary classifier)的优劣。& {7 s' a( ]8 u$ X( p: i. T7 Z- p' I7 R
6 \. w4 x6 {6 ~7 l5 k
4.1 ROC曲线4 ^: R" G) ^5 S3 B* L$ g
10.png : B9 w% h* ~5 s' l
ROC曲线(Receiver Operating Characteristic——受试者工作特征曲线),使用图形来描述二分类系统的性能表现。图形的纵轴为真正例率(TPR——True Positive Rate),横轴为假正例率(FPR——False Positive Rate)。其中,真正例率与假正例率定义为:7 c7 E& Q. ^7 v/ @( ^6 i) R
2 D3 I' ~5 }& k0 }2 A- w8 O  ^) Z
ROC曲线通过真正例率(TPR)与假正例率(FPR)两项指标,可以用来评估分类模型的性能。真正例率与假正例率可以通过移动分类模型的阈值而进行计算。随着阈值的改变,真正例率与假负例率也会随之发生改变,进而就可以在ROC曲线坐标上,形成多个点。
- ~/ m6 O. s1 `( s5 f7 ?/ |! v, l0 |/ p( Y6 I' s9 c, `
ROC曲线反映了FPR与TPR之间权衡的情况,通俗来说,即在TPR随着FPR递增的情况下,谁增长得更快,快多少的问题。TPR增长得越快,曲线越往上凸,模型的分类性能就越好。, z0 Q1 q* ]4 ~* o

6 a5 f% z: J( f) QROC曲线如果为对角线,则可以理解为随机猜测。如果在对角线以下,则其性能比随机猜测还要差。如果ROC曲线真正例率为1,假正例率为0,即曲线为与构成的折线,则此时的分类器是最完美的。2 Q1 r( _" W& s+ ]5 _% G
1 A" |* W' n; }5 W' U) L: U
下图就是ROC曲线的一个示意图:
' _4 n& q+ _( s 11.png 5 J0 ?& m3 V5 k5 F' T0 n  r
ROC曲线横坐标是FPR(False Positive Rate),纵坐标是TPR(True Positive Rate)
6 H3 ?/ O( \8 I$ E- s接下来我们考虑ROC曲线图中的四个点和一条线。, H' I9 m0 Y& p3 i: _  e
2 R% v3 f5 H6 Y3 M
第一个点,(0,1),即FPR=0, TPR=1,这意味着FN(false negative)=0,并且FP(false3 S- C. D" U* E1 N% D) e6 {
positive)=0。这是一个完美的分类器,它将所有的样本都正确分类。1 b! a7 u7 V" e  D7 [: f2 P
第二个点,(1,0),即FPR=1,TPR=0,类似地分析可以发现这是一个最糟糕的分类器,因为它成功避开了所有的正确答案。. v& a& X3 ?' k
第三个点,(0,0),即FPR=TPR=0,即FP(false positive)=TP(true) M: b- L& K. g
positive)=0,可以发现该分类器预测所有的样本都为负样本(negative)。
0 w! _6 s/ f+ I5 H) g第四个点(1,1),分类器实际上预测所有的样本都为正样本。经过以上的分析,我们可以断言,ROC曲线越接近左上角,该分类器的性能越好。$ a# f$ D/ ~: N0 ]. L/ |0 v
如何画ROC曲线:" s. x/ |: `7 W

3 K; L" S& r: C3 u/ e4 U% D对于一个特定的分类器和测试数据集,显然只能得到一组FPR和TPR结果,而要得到一个曲线,我们实际上需要一系列FPR和TPR的值,这又是如何得到的呢?我们先来看一下wikipedia上对ROC曲线的定义:
4 D- Q" j3 ]0 `! _
- m% H8 S& |6 `. {" d  dA receiver operating characteristic curve, i.e. ROC curve, is a
0 g6 ~3 w' t. ]graphical plot that illustrates the diagnostic ability of a binary# N: K% f  B8 [# ?) X" w
classifier system as its discrimination threshold is varied.
8 ?# ^5 E1 }  T- k$ j译:ROC曲线是由一系列因区分阈值变化产生的点,用于描述二分类模型的判断能力
' k" C# I# H4 s5 A, u" R这里的关键在于 “its discrimination threshold is varied” ,因为对于一个二分类模型,它的输出结果其实是判断这个样本属于正样本的概率值,假如我们已经得到了所有样本的概率输出(属于正样本的概率),现在的问题是如何改变“discrimination threashold”?我们根据每个测试样本属于正样本的概率值从大到小排序。下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率
0 o6 }. \+ Q  t' D: y2 d 12.png
& {" X/ q) w3 C然后我们按照样本的score值,从大到小依次作为阈值,当样本score值大于等于阈值时则判定为正样本,否则为负样本。
/ o' \- `7 R3 j5 z3 Y* x例如第一个阈值取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,而其他样本则都认为是负样本。
$ Q! m, J5 q) c  n$ H  J4 J( I- u  g) I" ?" O
详细如下:
; _# F. |9 G, G2 o) y5 c1 b 13.png
( s7 L4 j  W* Q% g: a( F" ~9 Y& C由此我们便得到了一组(FPR,TPR)的值,可以绘制出ROC曲线:6 A4 V, E! L! u7 ?3 S
14.png $ g7 A; e) j, b! e6 W/ ]6 k; @+ n  C
当我们将threshold设置为1和0时,分别可以得到ROC曲线上的(0,0)和(1,1)两个点。将这些(FPR,TPR)对连接起来,就得到了ROC曲线。当threshold取值越多,ROC曲线越平滑。
! w8 ]  K+ O% c! ]5 u6 A) Q2 ]$ [) a; w6 h6 n8 L  m
4.2 AUC
: A/ @) Y( P& n+ v. F( [) W0 h 15.png
3 U2 g6 H3 }! d" T5 T8 zAUC(Area Under the Curve)是指ROC曲线下的面积,使用AUC值作为评价标准是因为有时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而AUC作为数值可以直观的评价分类器的好坏,值越大越好。7 V9 P6 y/ \0 ?! l! W  _
; x  M# k: B5 C: C1 X# L
AUC是ROC曲线下的面积。
2 E# I* k' e, W+ o4 ]( _" cAUC的取值为[0.5-1],0.5对应于对角线的“随机猜测模型”。
( y5 W( f" s: O7 @AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前面,从而能够更好地分类。1 T* n' n1 A) V& q+ u
) X6 a# ~/ @# P+ j& E- Z# Q
从AUC判断分类器(预测模型)优劣的标准:5 G0 ^! P0 ]% W
3 o1 i7 i* p7 A5 V: |% H

# C  O7 M) w+ o; `# M0 ]% e例如一个模型的AUC是0.7,其含义可以理解为:给定一个正样本和一个负样本,在70%的情况下,模型对正样本的打分(概率)高于对负样本的打分。! G/ z6 }" f% }+ l$ z# I
; h, V3 X8 _, g4 ]7 `
三种AUC值示例:
5 a' C$ x, q& V, {0 e' H% } 16.png
, B3 R& k# B1 ~# I8 z0 \! ?简单说:AUC值越大的分类器,正确率越高。0 d$ h" y: ^( ?, s0 p

# ~) x! d4 j7 @& p4 X那么为什么要用AUC作为二分类模型的评价指标呢?为什么不直接通过计算准确率来对模型进行评价呢?7 V$ e- T5 L4 P
因为机器学习中的很多模型对于分类问题的预测结果大多是概率,即属于某个类别的概率,如果计算准确率的话,就要把概率转化为类别,这就需要设定一个阈值,概率大于某个阈值的属于一类,概率小于某个阈值的属于另一类,而阈值的设定直接影响了准确率的计算。也就是说AUC越高说明阈值分割所能达到的准确率越高。. p6 w: z, _2 q9 k1 e

( y8 L, W: w+ R小练习:
3 Z+ @, y8 p, y7 y% A( V: \: E, O0 u( S0 `5 i' d
以下说法正确的是( ABD)。【不定项】
: q* E. J2 `* H/ ?! }# yA 随着阈值的降低,TPR与FPR都会增大。6 g0 J; I( Z  W8 z, C* v5 |% N
B TPR与召回率的值是相同的。
8 v1 F* r5 {# c' vC 如果AUC的值非常低,例如,0.1,则该模型效果很差,也很难调优。. _4 M, D% |, N" `5 D( Z+ b
D 无论是什么分类模型,ROC曲线一定会经过(0, 0)与(1,1)这两个点。, Z6 t4 g% N) ?& `4 G; c9 @5 s3 |
4.3 ROC曲线程序示例9 k" B: r0 h1 ^8 D& P9 G

. w6 m  A0 m' n8 y' d8 ?" @我们首先来看一个简单的程序示例,借此来说明sklearn库中,ROC曲线的实现细节。
6 X5 a7 K& r- j9 n4 W8 J1 y5 O5 J" Z3 @( f& Y* [
4.3.1 roc_curve函数的参数' w% K; V! d. H
import numpy as np
8 E+ o* T! D% f/ b! s; I/ T  Cfrom sklearn.metrics import roc_curve, auc, roc_auc_score( ?5 u: f7 Z, b* y6 ^
y = np.array([0, 0, 1, 1])
8 d7 Y2 Z' x! F* D# C5 Nscores = np.array([0.2, 0.4, 0.35, 0.8])6 A( w$ o" {: e
# 返回ROC曲线相关值。返回FPR,TPR与阈值。当分值达到阈值时,将样本判定为正类,; r6 T8 ?1 H, @& v2 }; z
# 否则判定为负类。
9 V/ ?* A" U' H# p9 Q# y_true:二分类的标签值(真实值)。  i, m& _8 A% U9 H$ Y+ U0 B4 e
# y_score:每个标签(数据)的分值或概率值。当该值达到阈值时,判定为正例,否则判定为负例。
' z% }  U% P( p% N7 l# 在实际模型评估时,该值往往通过决策函数(decision_function)或者概率函数(predict_proba)获得。
% a! T+ j( Q- x. `1 j3 {# pos_label:指定正例的标签值。
5 M- P- B( {' L0 u% r! y  d/ ?+ k' Lfpr, tpr, thresholds = roc_curve(y, scores, pos_label=1)
% `5 l, |, J/ A  Pprint(f"fpr:{fpr}")
* f0 [" i) r5 j* ]2 u# S5 H- ~print(f"tpr:{tpr}")
1 X! _& H$ j$ \+ n8 lprint(f"thresholds:{thresholds}")
: Z5 \: h- a. `: G) u2 n8 ]5 V3 e# auc与roc_auc_score函数都可以返回AUC面积值,但是注意,两个函数的参数是不同的。
& U- {$ {6 D  p7 \1 g8 V& qprint("AUC面积值:", auc(fpr, tpr))
9 b  H1 L! G5 w3 B  [  gprint("AUC面积得分:", roc_auc_score(y_true=y, y_score=scores))# w8 R- V: ]- Z; \( d
#### 3.3.2 roc_curve函数的返回值
* \0 N. Y. h5 @3 d7 y, m# Y0 T8 k% i2 Q$ Q* N# E9 O) }
结果:7 k4 X1 `) H' L6 C- Q
17.png 1.8 是怎么来的?9 D4 v/ t- e3 c9 q1 I- [2 D" h
1.8是阈值中最大值+1(0.8+1)得来的。为什么这么算?因为要使得最开始得到的所有阈值都不会超过这个值,才能过(0,0)和(1,1)这两个点。* N4 x- i- m1 x/ }/ Q* i7 e! B9 V( Y

$ M( ^4 H4 b+ A9 F7 L4.3.2 roc_curve函数的返回值
+ r+ l6 x3 o$ q4 x+ Z8 X- o2 \4 F
roc_curve函数具有3个返回值:0 n4 J# H( f2 Z9 \. g1 n, Q% U

& v9 X: K' k8 a* ofpr 对应每个阈值(thresholds)下的fpr值。
1 A1 R! c, i' A! V" E7 qtpr 对应每个阈值(thresholds)下的tpr值。
) T7 F- L: c0 m) U2 ~; k0 cthresholds 阈值。9 @$ x- v; K$ J3 U9 X; O: ]
roc_curve函数会从y_score参数中,选择部分元素作为阈值(选择哪些元素属于实现细节,会根据sklearn版本的不同,也可能会有所差异。),然后进行降序排列,作为roc_curve函数的第3个返回值(thresholds)。同时,根据thresholds中的每个元素(阈值),分别计算fpr与tpr。
6 K+ d+ L: b* `: C- Xiris = load_iris()
7 H$ V' M' z9 K) P, NX, y = iris.data, iris.target
8 S0 @! ^: Y; T: j: ]$ pX = X[y != 0, 2:]
: A+ D5 M% m& H( _" Vy = y[y != 0]
/ v0 L- r' [* E1 I. F: ]  a- H: |5 Fy[y == 1] = 0
* t) r+ X' R) v. v+ P! }y[y == 2] = 1
2 K- z$ E" B) s& mX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25,  t& x' t: R( H2 x  P+ S
random_state=2)" g2 o& \+ n0 w  h6 E
# lr = LogisticRegression(multi_class="multinomial", solver="lbfgs")( M) e1 O' [* [3 X% F! D1 a
lr = LogisticRegression(multi_class="ovr", solver="liblinear")
* D2 C% D1 j7 ]$ Q5 G0 i$ llr.fit(X_train, y_train)4 s/ r/ f' j+ o0 K7 r* B5 A" e
# 使用概率来作为每个样本数据的分值。
. Z" o* U' n! Y. u$ J9 \# lprobo = lr.predict_proba(X_test)1 z3 O3 f1 A  t) r( ]
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=probo[:, 1],& G% T; a: U, c( G$ q9 K, `
pos_label=1)" W5 q4 Y' c0 B. p
display(probo[:, 1])
% v2 \4 Y0 |$ i) C) N2 u# 从概率中,选择若干元素作为阈值,每个阈值下,都可以确定一个tpr与fpr,5 b% I& X. w! u* n# ]2 K
# 每个tpr与fpr对应ROC曲线上的一个点,将这些点进行连接,就可以绘制ROC曲线。
9 l5 y5 U1 `6 C% F$ qdisplay(thresholds)
' h$ M7 S* O2 V8 q8 {* J! F
& g+ j' A! n  t; o结果:0 E% _0 T% t( O' H1 i2 m' T
18.png
) d( K; ?7 ~7 e
4 `  R/ @+ P/ v3 w5 w5 [
- F; {! [' O0 j( @% F5 C- e: i% R# 随着阈值的不断降低,fpr与tpr都在不断的增大。
! i1 ^3 o3 M; C+ rfpr, tpr& @! c, y' D8 V3 @2 U
. D6 x. S% m0 |0 H4 z0 S
结果:, Z/ C/ ?: ~8 p1 y
19.png + s# b  f- Z9 @  t  a  S0 R( y. r5 I

% `3 E4 w) C% j7 o4.3.3 绘制ROC曲线
* n3 n: A- ^* T- K" d有了fpr与tpr的值,绘制ROC曲线是非常容易的,只不过是最简单的一个plot而已。, d* M3 y! A, ]# \; U' L0 X/ p
plt.figure(figsize=(10, 6))5 T! E! A- Q# L7 v
plt.plot(fpr, tpr, marker="o", label="ROC曲线")  H* X7 V* r" V
plt.plot([0,1], [0,1], lw=2, ls="--", label="随机猜测")* ^# K! Y$ O1 r, d$ h* A
plt.plot([0, 0, 1], [0, 1, 1], lw=2, ls="-.", label="完美预测")- Z4 s2 h+ r2 T6 z1 w: }# g' i, n
plt.xlim(-0.01, 1.02)9 L8 k( y- B2 ~4 q, m) Z6 U
plt.ylim(-0.01, 1.02)9 [0 m' {/ w) ]- N) n
plt.xticks(np.arange(0, 1.1, 0.1))
$ P9 h/ S* I+ T; i4 Tplt.yticks(np.arange(0, 1.1, 0.1))
$ D2 i' p6 K$ s$ M( Lplt.xlabel("False Positive Rate(FPR)")% f* g7 d3 T& ?. q4 S
plt.ylabel("True Positive Rate(TPR)")
1 C# a! n  L4 z2 }2 rplt.grid()
/ d, H- _9 ^* K% @0 n5 Hplt.title(f"ROC曲线-AUC值为{auc(fpr, tpr):.2f}")$ h' u$ X- u) P$ Z% v+ {5 u
plt.legend()
5 Z- w  m/ x6 @4 z8 l' p0 `. eplt.show(): r6 E' @. t+ t5 j/ `: D) T
20.png
4 t7 l7 D( l. g0 B' a1 \# S9 ]1 x3 {7 p1 g/ w" t- W$ n
5、总结- ?% z0 f- }. N$ Y, l1 d1 a# ~

! `0 F( a! i4 P, t" R( ~' Q混淆矩阵的含义。
/ H( P  E# ^. X0 Q9 |& w正确率,精准率,召回率与调和平均值F1的含义。# O0 D% @$ b" c1 }
ROC与AUC。
  C) C3 a; P' Q$ Y! ]
) q, N/ I4 @0 r5 {5 H参考资料:9 s( o& S6 J+ w& B: ?, m
1、https://blog.csdn.net/zuolixiangfisher/article/details/81328297) e2 g1 e4 S$ ]; v5 g9 J! ~
2、https://www.jianshu.com/p/2feb00839154. U' Y# a: u# I' `# M5 d
3、https://www.cnblogs.com/kamekin/p/9788730.html7 f, u$ `9 a, |
4、https://www.jianshu.com/p/c61ae11cc5f6
: Y. k) {4 Q' {# \  s* Q————————————————
5 n- L4 U5 `$ P; z7 J! l+ r1 R版权声明:本文为CSDN博主「糖潮丽子~辣丽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
8 Q# b% F  F. M- a原文链接:https://blog.csdn.net/qq_39783601/article/details/105600700
: J2 i6 [! y, S2 F2 H; L/ ~3 X$ n' e! b; W% M: S
  A1 y+ y1 X6 T/ N7 [; R. Z

作者: 1336671542    时间: 2020-4-19 12:50
非常感谢!!!!!!!!!!
5 L5 F9 H5 A  \: m




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