ROC 曲线讲解 (Receiver Operarating Curve)

概念

信号检测理论中,接收者操作特征曲线receiver operating characteristic curve,或者叫ROC曲线)是一种坐标图式的分析工具,在同一模型中设置最佳阈值by Wikipedia

ROC曲线的画法如下图所示,每个点表示不同阈值下 TP(横坐标) FP(纵坐标)的值,

TP,FP的定义如下

  实际值
 ture 真的false 假的
预测值ture 真的TP (true positive)FP (false positive)
false 假的FN (false negative)TN (true negative)

TP rate = TP/(TP+FN),分母就是实际上是真的那一类,这个算出来的是预测的真的占真正的真的改率。我们想要预测的准确,这个应该越大越好。

FP rate = FP/(FP+TN),分母就是实际上假的那一类,这个算出来的是被错分成真的(其实是假的)占所有的错的概率,我们希望错分的越小越好,所以这个值越小越好。


例子

AUC计算过程:

下面用两个正态分布的例子说明问题,

下图中左边蓝色是一类,右边绿色是一类。

(目的)ROC的作用是找到两个类,让红色的这条线能够将两类最好地分开。AUC值越大的分类器,正确率越高

(过程)从左到→右移动移动这条红色的虚线,计算ROC中的每个点,一个虚线就是一个阈值,对应的就是ROC上面的一个点,将ROC连成曲线。在这个图中已经标明了TP,FP,TN,FN,可以很方便的计算出来。

-------------------------------------------------------------------------------------------------------------------------------

我们知道TP rate越大越好,FP rate越小越好。那么画了ROC之后,怎么判断哪两个类能分的最开呢?怎么找到哪个阈值最好呢?

下面这张图画出了解决办法。就是算出AUC(Area Under Curve,曲线下的面积),也就是ROC与坐标轴形成的面积。

AUC图反映的是两个类的重叠程度,AUC的面积反应了分类的好坏。

我们可以看到不同的两个分类的AUC截然不同,

第一个例子:可以分开大多数点,它的AUC在0.9左右

第四个例子:两个类完全重合时,一半的点都会分类错误,相当于没分,它的AUC是0.5左右。

因此AUC面积越大的分类器的分类效果最好,这样的分类器在找到阈值后可以有较高的分类正确率。

代码 ROCcurve及AUC

import matplotlib.pyplot as plt
import numpy as np

def gauss2D(x, m, C):
  Ci = np.linalg.inv(C)  #求矩阵的逆
  dC = np.linalg.det(C)  #求矩阵的行列式
  num = np.exp(-0.5 * np.dot((x-m).T, np.dot(Ci,(x-m))))
  den = 2 * np.pi * (dC**0.5) #计算矩阵的密度函数

  return num/den

def twoDGaussianPlot(nx, ny, m, C):
  x = np.linspace(-6, 6, nx)
  y = np.linspace(-6, 6, ny)
  X, Y = np.meshgrid(x, y, indexing='ij')

  Z = np.zeros([nx,ny])
  for i in range(nx):
    for j in range(ny):
      xvec = np.array([X[i,j], Y[i,j]])
      Z[i,j] = gauss2D(xvec, m, C)
  
  return X, Y, Z

X = np.random.randn(200, 2)
C1 = np.array([[2,1],[1,2]])
C2 = np.array([[2,1],[1,2]])
m1 = np.array([0, 3])
m2 = np.array([3,2.5])
A = np.linalg.cholesky(C1)

Y1 = X @ A.T + m1
Y2 = X @ A.T + m2

plt.figure(1)
plt.scatter(Y1[:,0], Y1[:,1], c='c', s=4)
plt.scatter(Y2[:,0], Y2[:,1], c='m', s=4)

Xp, Yp, Zp = twoDGaussianPlot(40,50,m1,C1)
plt.contour(Xp, Yp, Zp, 5)

Xp2, Yp2, Zp2 = twoDGaussianPlot(40,50,m2,C2)
plt.contour(Xp2, Yp2, Zp2, 5)

# uF = [(np.mean(Y1[:,0])+np.mean(Y2[:,0]))/2,(np.mean(Y1[:,1])+np.mean(Y2[:,1]))/2]
# uF = np.array([-1,5])
uF = np.array(m1-m2)
print(uF)
# print(uF.shape)
#plt.arrow(0, 0, *(uF), color='b', linewidth=2.0, head_width=0.30, head_length=0.35)
plt.arrow(0, 0, uF[0], uF[1], color='b', linewidth=2.0, head_width=0.30, head_length=0.35)

plt.axis('equal')
plt.grid()
plt.xlim([-6,6])
plt.ylim([-5,8])

plt.savefig('density graph.png')

yp1 = Y1 @ uF
yp2 = Y2 @ uF

plt.figure(2)
plt.rcParams.update({'font.size':16})
plt.hist(yp1, bins=40)
plt.hist(yp2, bins=40)
plt.savefig('histogramprojections.png')

pmin = np.min( np.array( (np.min(yp1), np.min(yp2) ))) 
pmax = np.max( np.array( (np.max(yp1), np.max(yp2) )))
print(pmin, pmax)

nRocPoints = 50
thRange = np.linspace(pmin, pmax, nRocPoints)
ROC = np.zeros((nRocPoints, 2))

for i in range(len(thRange)):
  thresh = thRange[i]
  TP = len(yp2[yp2 > thresh]) * 100/len(yp2)
  FP = len(yp1[yp1 > thresh]) * 100/len(yp1)
  ROC[i,:] =[TP, FP]

fig, ax = plt.subplots(figsize=(6,6))
ax.plot(ROC[:,0],ROC[:,1], c='m')
ax.set_xlabel('False Positive')
ax.set_ylabel('True Positive')
ax.set_title("Receive Operating Charateristics")
ax.grid(True)
plt.savefig('rocCure.png')

print(np.trapz(ROC[:,1],x=ROC[:,0]))

                                 

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值