Model selection and evaluation

查准率、查全率与F1

对于二分类问题,可将样例根据其真实类别与学习器预测类别的组合划分为

  • 真正例(true positive) :真的正样本,本来就是正样本
  • 假正例(false positive) :假的正样本,其实是负样本
  • 真反倒(true negative) :真的负样本,本来就是负样本
  • 假反例(false negative) 假的负样本,其实是正样本

显然有TP+FP+TN+FN=样例总数.上述4种情况可以理解为: 以预测结果的角度对每个样本的判决产生看法

  • 查准率/正确率P(确保预测为正的样本中有更多样本是正确的) :P = \frac{TP}{TP+FP},分类正确的正样本/所有判断为正的样本总数
  • 查全率/召回率R(确保所有正样本中有更多样本被正确分类):R=\frac{TP}{TP+FN},分类正确的正样本/数据集中的正样本

查准率和查全率是一对矛盾的度量.一般来说,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低.

例如,若希望将好瓜尽可能多地选出来,则可通过增加选瓜的数量来实现,如果将所有西瓜都选上,那么所有的好瓜也必然都被选上了,但这样查准率就会较低;若希望选出的瓜中好瓜比例尽可能高,则可只挑选最有把握的瓜, 但这样就难免会漏掉不少好瓜,使得查全率较低.通常只有在一些简单任务中才可能使查全率和查准率都很高.

P-R 曲线

在很多情形下我们可根据学习器的预测结果对样例进行排序,排在前面的是学习器认为"最可能"是正例的样本,排在最后的则是学习器认为"最不可能"是正例的样本.通过置信度就可以对所有样本进行排序,再逐个样本的选择阈值,在该样本之前的都属于正例,该样本之后的都属于负例。每一个样本作为划分阈值时,都可以计算对应的P和R.

  • 若一个学习器的P-R 曲线被另一个学习器的曲线完全"包住" , 则可断言后者的性能优于前者,中学习器A 的性能优于学习器C;
  • 两个学习器的P-R 曲线发生了交叉,
  1. "平衡点"一个度量,它是" 查准率=查全率"时的取值,越大性能越好,所以学习器A 优于B
  2. F1度量:F1 = \frac{2\times P \times R}{P+R}=\frac{2\times TP}{N +TP-TN},N为样例总数,

在一些应用中,对查准率和查全率的重视程度有所不同.例如在商品推荐系统中,为了尽可能少打扰用户,更希望推荐内容确是用户感兴趣的,此时查准率更重要;而在逃犯信息检索系统中,更希望尽可能少漏掉逃犯,此时查全率更重要. F1 度量的一般形式F_{\beta }能让我们表达出对查准率/查全率的不同偏好,

F_{\beta } = \frac{(1+\beta^{2})\times P \times R}{(\beta^{2}\times P)+R}

\beta = 1退化为标准的F1; \beta > 1时查全率有更大影响; \beta < 1时查准率有更大影响.

ROC 与AUC

根据上一小节,在不同的应用任务中,我们可根据任务需求来采用不同的截断点,例如若我们更重视"查准率",则可选择排序中靠前的位置进行截断;若更重视"查全率",则可选择靠后的位置进行截断.因此,排序本身的质量好坏,体现了综合考虑学习器在不同任务下的"期望泛化性能"的好坏,或者说"一般情况下"泛化性能的好坏. ROC 曲线则是从这个角度出发来研究学习器泛化性能的有力工具.

  • 纵轴是"真正例率" (True Positive Rate,TPR) TPR = \frac{TP}{TP+FN}.所有正样本中被正确分类的比例
  • 横轴是"假正例率" (False PositiveRate,FPR)FPR = \frac{FP}{TN+FP}.所有负样本中被错误分类的比例

  • 若一个学习器的ROC曲线被另一个学习器的曲线完全"包住" , 则可断言后者的性能优于前者.
  • 两个学习器的P-R 曲线发生了交叉, AUC度量,AUC = \frac{1}{2}\sum_{i=1}^{m-1}(x_{i+1}-x_{i})\cdot (y_{i}+y_{i+1})
import numpy as np
import matplotlib.pylab as plt
from sklearn.datasets import make_hastie_10_2
from sklearn.ensemble import AdaBoostClassifier

def plotROC(predStrengths, classLabels):
    """
    每遇到一个+1标签,沿着y轴下降一个步长,降低真正例率;
    每遇到一个其他标签,沿着x轴倒退一个步长,降低假正例率;
    :param predStrengths:
    :param classLabels:
    :return:
    """
    cursor = (1.0, 1.0)                                 # 游标位置
    ySum = 0.0                                          # 计算AUC的变量
    numPositiveClass = sum(np.array(classLabels) == 1.0)
    yStep = 1 / float(numPositiveClass)                 # 确定了y轴步长
    xStep = 1 / float(len(classLabels) - numPositiveClass)# 确定了y轴步长
    #数组值从小到大的索引值
    sortedIndicies = predStrengths.argsort()             #从小到大顺序排列,从(1.0,1.0)开始画一直到(0,0)
    fig = plt.figure()
    fig.clf()
    ax = plt.subplot(111)
    # loop through all the values, drawing a line segment at each point
    for index in sortedIndicies.tolist():
        if classLabels[index] == 1.0:
            delX = 0
            delY = yStep
        else:
            delX = xStep
            delY = 0
            ySum += cursor[1]
        # draw line from cursor to (cursor[0]-delX,cursor[1]-delY)
        ax.plot([cursor[0], cursor[0] - delX], [cursor[1], cursor[1] - delY], c='b')
        cursor = (cursor[0] - delX, cursor[1] - delY)
    ax.plot([0, 1], [0, 1], 'b--')
    plt.xlabel('False positive rate');
    plt.ylabel('True positive rate')
    plt.title('ROC cursorve for AdaBoost horse colic detection system')
    ax.axis([0, 1, 0, 1])
    plt.show()
    # 每个小矩形相加,矩形的宽度为xStep,因此对矩形的高度进行相加得到ySum
    print("the Area Under the cursorve is: ", ySum * xStep)

if __name__ == "__main__":
    X, y = make_hastie_10_2(n_samples=4000, random_state=1)
    X_test, y_test = X[2000:], y[2000:]
    X_train, y_train = X[:2000], y[:2000]
    clf = AdaBoostClassifier(n_estimators=100)
    clf.fit(X_train,y_train)
    preds = clf.predict_proba(X_test)
    plotROC(preds[:,1],y_test)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值