衡量两个次序的差异的指标
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∑α(∣pi−qj∣+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(N−1)2i=1∑N−1j<i∑Nk(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 i, j is in same order)(if i, j 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=1∑Nlog2(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=1∑Nlog2(1+j)2rj−1
- 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 m⋅n) 即为AUC。
只需遍历一次,复杂度为 O ( N ) O(N) O(N)
2,在按 score 排序的样本序列中,每个正样本之后的负样本的个数的和,除以 m ⋅ n m \cdot n m⋅n。
复杂度为 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=m⋅n∑i+∣{sj−∣sj−<si+}∣
3,方法2换个角度看,就是把正负样本之间两两组合,其中正样本 score 大于负样本 score 的组合的个数(score相等的算0.5) 。结果再除以 m ⋅ n m \cdot n m⋅n
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=m⋅n∣{(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=m⋅n∑riyi−m(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 9−m。对于第 i + i_+ i+ 个正例,其后共有 r i + − 1 r_{i+} - 1 ri+−1 个样本,其中正例有 m − i m-i m−i 个,所以其后的负例个数是 r i + − 1 − ( m − i + ) r_{i_+} - 1 - (m-i_+) ri+−1−(m−i+)。所以求和过程做以下整理后,即与方法 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+=1∑m[ri+−1−(m−i+)]=i+=1∑mri+−m−m2+i+=1∑mi+=i+=1∑mri+−m(m+1)/2=i∑riyi−m(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)