排序比较指标

来源:互联网 发布:大数据分析师培训课程 编辑:程序博客网 时间:2024/05/14 09:30

衡量两个次序的差异的指标

1. Fitness

F=1Zjwjα(|piqj|+1)+(1α)pi

其中:

  • pj: 待排序中第 j 条结果的位置
  • qj: 待测排序的第 j 条结果在标准排序中的位置
  • wj: 标准排序中位置 j 上的权重
  • Z: 归一化因子

2. Kendall tau distance (wikipedia)

K=2N(N1)i=1N1j<iNk(i,j)

where

k(i,j)={01(if ij is in same order)(if ij is not in same order)

K 的取值范围是 [0,1],两种顺序完全相同时为 0,完全相反时为 1.

3. NDCG (wikipedia)

两种定义(第一个有改动):

NDCG=1Zj=1Nrjlog2(1+j)

NDCG=1Zj=1N2rj1log2(1+j)

  • rj: 第 j 条结果的评分等级
  • Z: 归一化因子,理想最大值

4. AUC(wikipedia)

数据样例

  • y: 正负样本标记,预测目标, y{0,1}
  • s: 预测分数 score
  • r:按 score 排序后的顺序标记 rank
  • m,n:正负样本个数
score 0.86 0.81 0.73 0.66 0.52 0.43 0.36 0.31 0.26 rank 9 8 7 6 5 4 3 2 1 y 1 1 0 1 1 0 1 0 0

ROC曲线

  • ROC:receiver operating characteristic curve。
  • 横坐标:FP (false positive),纵坐标:TF(True positive)。
  • 遍历分类器阈值,可得到一系列不同的 (FP,TP) ,这些点构成的曲线即为ROC。
  • 等效于,在排序好的数据列表中,从左向右扫过score。若将当前扫过的位置作为分类线,当前 score 作为分类阈值,则每个位置对应一个 (FP, TP) 值对。FP、TP 分别等于当前位置左侧的 y=1,y=0 的个数。
    (0,0),(0,1),(0,2),(1,2),(1,3),(1,4),(2,4),(2,5),(3,5),(4,5)

AUC

  AUC 即 ROC 曲线下的面积。5 种计算方式:

  1,根据定义:遍历排好序的样本,每个样本画出ROC上的一个点。每遇一个正样本,纵轴升一个(TP++);每遇一个负样本,横轴加一个(FP++),同时累积面积增加TP。遍历完后,TP = m, FP = n,所得面积除以总面积 (mn) 即为AUC。

  只需遍历一次,复杂度为 O(N)

  2,在按 score 排序的样本序列中,每个正样本之后的负样本的个数的和,除以 mn

  复杂度为 O(N2)

    

AUC=i+|{sj|sj<si+}|mn

  3,方法2换个角度看,就是把正负样本之间两两组合,其中正样本 score 大于负样本 score 的组合的个数(score相等的算0.5) 。结果再除以 mn

    

AUC=|{(si+,sj)|si+>sj}|mn

  4,计算正样本的 rank 的和,然后按下式计算

  

AUC=riyim(m+1)/2mn

  5,区块方法。以上方法都是对单例计算的,无法计算 AUC_UP。将值相近的 score 聚合成区块,用一个得分 ti 表示,统计每个区块 i 中的正负例个数 mi,ni,形成压缩的新数据元:(ti,mi,ni)。按 ti 排序后,再按 1 中的方法计算累积面积(用梯形面积近似,所以每次增加面积是 (TP+mi/2)ni)。每次纵轴、横轴增加的量分别为 mi,ni

    计算 AUC_UP 时,只需将序列按新数据元的经验概率 mi/(mi+ni) 排序,再按相同方法计算 AUC。

计算方法的的等效性

  2 1 方法的等效性:

  方法 2 中,每个正例之后的负例的个数,等于在 ROC 曲线中,该正例点向右的长度。即每个正例对 ROC 下的面积的贡献,是其对应的点向右的宽度为1的横带。这是因为正例的出现只使 ROC 曲线在纵向上增长。

  2 4 方法的等效性:

  对于第一个正例,其后的负样本的个数为 9m。对于第 i+ 个正例,其后共有 ri+1 个样本,其中正例有 mi 个,所以其后的负例个数是 ri+1(mi+)。所以求和过程做以下整理后,即与方法 3 相同。

i+=1m[ri+1(mi+)]=i+=1mri+mm2+i+=1mi+=i+=1mri+m(m+1)/2=iriyim(m+1)/2

  5 1 方法的等效性:

  单数据元中,正负例 yi=0,1 分别对应batch方法中 (mi,ni) 等于 (1,0),(0,1)。所以方法 1 是 4 的特例,可从实现代码中看出。

示例代码

#!/usr/bin/env python#!encoding:utf-8s = [0.86, 0.81, 0.73, 0.66, 0.52, 0.43, 0.36, 0.31, 0.26]y = [1,    1,    0,    1,    1,    0,    1,    0,    0]ll = [[s[i], y[i]] for i in range(len(s)) ]def auc_1(ll):    m, n, area = 0, 0, 0    for s, y in ll:        if y == 1:            m += 1        if y == 0:            n += 1            area += m    return 1. * area / (m * n)def auc_2(ll):    m, n, cnt = 0, 0, 0.     for i, (s, y) in enumerate(ll):         if y == 0:             n += 1            continue         if y == 1:             m += 1            for j in range(i, len(ll)):                 if ll[j][1] == 0:                     cnt += 1    return cnt / (m * n) def auc_3(ll):    m, n, cnt = 0, 0, 0    for i in range(len(ll)):        if ll[i][1] == 1:            m += 1        elif ll[i][1] == 0:            n += 1        for j in range(i+1, len(ll)):            if ll[i][0] == ll[j][0]:                    cnt += 0.5            elif ll[i][0] > ll[j][0] and ll[i][1] > ll[j][1]:                cnt += 1            if ll[i][0] < ll[j][0] and ll[i][1] < ll[j][1]:                cnt += 1    return 1. * cnt / (m * n)def auc_4(ll):    m, n, q = 0, 0, 0    for i, (s, y) in enumerate(ll):        if y == 1:            m += 1            q += len(ll) - i        if y == 0:            n += 1    auc = 1. * ( q - m * (m + 1) / 2) / (m * n)    return aucdef for_auc_5(score_np):     m, n, area = 0, 0, 0.      for t, [mi, ni] in score_np:         area += (m + mi /2.)*ni        m += mi        n += ni    return area / (m * n)  def auc_5(ll):    score_block = {}          for s, y in ll:         t = round(s, 5)   # 粗粒化。省略则与方法1相同。粒度越粗AUC_UP越低        if t in score_block:            score_block[t][0] += y            score_block[t][1] += 1-y        else:            score_block[t] = [y, 1-y]    score_np = sorted(score_block.items(), key = lambda x: -x[0])    auc = for_auc_5(score_np)     score_np = sorted(score_block.items(), key = lambda x: -x[1][0]/(x[1][0]+x[1][1]))    auc_up = for_auc_5(score_np)     return auc, auc_up ll.sort(key = lambda x: -x[0]) print "auc1:", auc_1(ll)print "auc2:", auc_2(ll)print "auc3:", auc_3(ll)print "auc4:", auc_4(ll)print "auc5:", auc_5(ll)
0 0
原创粉丝点击