排序比较指标

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

1. Fitness

F = 1 Z ∑ j w j α ( ∣ p i − q j ∣ + 1 ) + ( 1 − α ) p i F = \frac{1}{Z} \sum_j \frac{w_j}{\alpha (|p_i - q_j|+1) + (1-\alpha) p_i} F=Z1jα(piqj+1)+(1α)piwj

其中:

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

2. Kendall tau distance (wikipedia)

K = 2 N ( N − 1 ) ∑ i = 1 N − 1 ∑ j < i N k ( i , j ) K = \frac{2}{N(N-1)} \sum_{i=1}^{N-1} \sum_{j<i}^N k(i,j) K=N(N1)2i=1N1j<iNk(i,j)

where

k ( i , j ) = { 0 (if  i ,  j  is in same order) 1 (if  i ,  j  is not in same order) k(i,j) = \begin{cases} 0 & \text{(if $i$, $j$ is in same order)} \\ 1 & \text{(if $i$, $j$ is not in same order)} \end{cases} k(i,j)={01(if ij is in same order)(if ij is not in same order)

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

3. NDCG (wikipedia)

两种定义(第一个有改动):
N D C G = 1 Z ∑ j = 1 N r j log ⁡ 2 ( 1 + j ) NDCG = \frac{1}{Z} \sum_{j = 1}^N \frac{r_j}{\log_2 (1+j)} NDCG=Z1j=1Nlog2(1+j)rj

N D C G = 1 Z ∑ j = 1 N 2 r j − 1 log ⁡ 2 ( 1 + j ) NDCG = \frac{1}{Z} \sum_{j = 1}^N \frac{2^{r_j}-1}{\log_2 (1+j)} NDCG=Z1j=1Nlog2(1+j)2rj1

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

4. AUC(wikipedia)

数据样例

  • y y y: 正负样本标记,预测目标, $ y \in {0, 1} $
  • s s s: 预测分数 score
  • r r r:按 score 排序后的顺序标记 rank
  • m , n m, n 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 y=1, y=0 y=1,y=0 的个数。
    ( 0 , 0 ) , ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 1 , 4 ) , ( 2 , 4 ) , ( 2 , 5 ) , ( 3 , 5 ) , ( 4 , 5 ) (0,0), (0,1), (0,2), (1,2), (1,3), (1,4), (2, 4), (2,5), (3,5), (4,5) (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 m m, FP = n n n,所得面积除以总面积 ( m ⋅ n m \cdot n mn) 即为AUC。

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

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

复杂度为 O ( N 2 ) O(N^2) O(N2)

A U C = ∑ i + ∣ { s j − ∣ s j − < s i + } ∣ m ⋅ n AUC = \frac{\sum_{i_+} | \{ s_{j_-} |s_{j_-} < s_{i_+}\}|} {m \cdot n} AUC=mni+{sjsj<si+}

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

A U C = ∣ { ( s i + , s j − ) ∣ s i + > s j − } ∣ m ⋅ n AUC = \frac{|\{(s_{i_+}, s_{j_-}) | s_{i_+} > s_{j_-}\}|}{m \cdot n} AUC=mn{(si+,sj)si+>sj}

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

A U C = ∑ r i y i − m ( m + 1 ) / 2 m ⋅ n AUC = \frac{\sum r_i y_i - m (m + 1) / 2}{m \cdot n} AUC=mnriyim(m+1)/2

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

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

计算方法的的等效性

2 ⇒ \Rightarrow 1 方法的等效性:

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

2 ⇒ \Rightarrow 4 方法的等效性:

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

∑ i + = 1 m [ r i + − 1 − ( m − i + ) ] = ∑ i + = 1 m r i + − m − m 2 + ∑ i + = 1 m i + = ∑ i + = 1 m r i + − m ( m + 1 ) / 2 = ∑ i r i y i − m ( m + 1 ) / 2 \sum_{i_+ = 1}^m [ r_{i+} - 1 - (m-i_+) ] = \sum_{i_+ = 1}^m r_{i+} - m - m^2 + \sum_{i_+ = 1}^m i_+ \\ \qquad = \sum_{i_+ = 1}^m r_{i+} - m (m+1)/2 \\ \qquad = \sum_i r_i y_i - m (m+1)/2 i+=1m[ri+1(mi+)]=i+=1mri+mm2+i+=1mi+=i+=1mri+m(m+1)/2=iriyim(m+1)/2

5 ⇒ \Rightarrow 1 方法的等效性:

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

示例代码

#!/usr/bin/env python
#!encoding:utf-8

s = [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 = sorted([(s[i], y[i]) for i in range(len(s))], key=lambda x: -x[0])

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 auc

def 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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值