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