简述
机器学习很多是为测试样本产生一个预测值,然后将这个预测值与阈值进行对比,若大于阈值则分为正类,否则分为反类。这个预测值的好坏,直接决定了学习器泛化能力。根据这个预测值,我们可以对测试样本进行排序,“最可能”是正例的排在最前面,“最不可能”是正例的排在最后面。这样,分类过程就相当于在这个排序中以某个截断点将样本分为两部分,前面一部分作为正例,后面一部分作为反例。
如果我们更加重视“查准率”,则可以选择排序中靠前的位置进行阶段(尽可能的准确预测正例);若更加重视“查全率”,则可以选择排序中靠后的位置进行截断(尽可能多的包含正例)。因此排序的好坏,直接体现了综合考虑学习器在不同任务下的“期望泛化性能”的好坏。ROC曲线就是从这个角度出发来研究学习器泛化性能的。
真正例率和假正例率
- 真正例率:前半部分预测为正的样例占实际为正的样例的比例
TPR=TPTP+FN
T
P
R
=
T
P
T
P
+
F
N
- 假正例率:后半部分预测为正的样例占实际为反的样例的比例
FPR=FPTN+FP F P R = F P T N + F P
数据集:
x1 0.9894352 1
x2 0.9794352 1
x3 0.977945262 1
x4 0.960783037 1
x5 0.944241384 1
x6 0.93664411 1
x7 0.924929575 1
x8 0.920406882 0
x9 0.888570298 1
x10 0.882629706 1
x11 0.882401646 1
x12 0.853832401 1
x13 0.839347591 1
x14 0.836771262 1
x15 0.833144033 1
x16 0.828867488 1
x17 0.815303556 0
x18 0.805622582 1
x19 0.802897991 1
x20 0.789226942 0
x21 0.758042059 1
x22 0.716307689 1
x23 0.69443123 1
x24 0.693818886 1
x25 0.684523938 1
x26 0.672463705 1
x27 0.629302653 0
x28 0.58780351 1
x29 0.548529475 1
x30 0.488394372 0
x31 0.483994649 0
x32 0.43695701 1
x33 0.408835528 1
x34 0.393323919 0
x35 0.374834691 1
x36 0.349519471 0
x37 0.29704696 0
x38 0.273542305 0
x39 0.205748558 0
x40 0.187974058 1
x41 0.179264057 0
x42 0.164596829 0
x43 0.142258075 0
x44 0.138514809 0
x45 0.128892511 0
x46 0.126119067 0
x47 0.113361272 0
x48 0.083327915 0
x49 0.071568497 0
x50 0.031525573 0
测试样本包含三列,第一列样本序号,第二列为预测值,第三列为真实标记值。
#-*- coding: utf-8 -*-
import matplotlib.pyplot as plt
def get_data(path):
f = open(path)
data_list = f.readlines()
return data_list
def get_truth_value():
threshold_list = []
truth_value = []
data_list = get_data('test.txt')
for item in data_list:
truth_value.append(
item.strip().split('\t')[2])
return truth_value
def plot_curve(x,y):
plt.scatter(x,y)
plt.xlabel(u"假正例率",fontproperties='SimHei')
plt.ylabel(u"真正例率",fontproperties='SimHei')
plt.show()
def get_tpr_fpr():
truth_value = get_truth_value()
tpr = []
fpr = []
for i in range(1,len(truth_value)):
forecast = []
forecast.extend([1]*(i))
forecast.extend([0]*(len(truth_value) - i))
tmp_list = [forecast[j]*int(truth_value[j]) for j in range(len(forecast))]
tp = sum(tmp_list[0:i])
fp = i - tp
fn = sum([int(x) for x in truth_value[i:len(truth_value)]])
tn = len(truth_value)-i - fn
print(tp,fp,fn,tn)
tpr.append(tp*1.0/(tp+fn))
fpr.append(fp*1.0/(tn+fp))
return tpr,fpr
if __name__ == "__main__":
x,y = get_tpr_fpr()
plot_curve(y,x)
绘图
这里绘图方法是将测试样本的每一个值作为阈值,然后分别计算出真正例率和假正例率,如图所示:
对于同一个测试样本,不同的学习器产生的预测值不同,绘制的ROC曲线也不同,当一个曲线将另一个曲线完全包住时,包住的曲线对应的学习器的泛化能力是强于另外一个的,当两条曲线有交点时,需要计算ROC曲线围住的面积:
AUC=12∑i=1m−1(xi+1−xi)∗(yi+yi+1)
A
U
C
=
1
2
∑
i
=
1
m
−
1
(
x
i
+
1
−
x
i
)
∗
(
y
i
+
y
i
+
1
)
提示:这里讲面积划分为许多梯形的面积,然后求和,梯形面积公式:
S=12(上底+下底)∗高
S
=
1
2
(
上
底
+
下
底
)
∗
高