概念
在信号检测理论中,接收者操作特征曲线(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]))
![](https://i-blog.csdnimg.cn/blog_migrate/d55461c5297c82aea4f40c17713fd3a5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0a5f89cd18aa630ca0879dfe5e795e93.png)