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