假设对于一个查询,真实相关的结果是{A,C,E, Q},搜索模型得到5个结果{A, B, C, D, E},则其中只有A,C,E是相关的,标记为{1, 0, 1, 0, 1},1表示相关,0表示不相关。
即预测正确的相关结果占返回的所有结果的比例:
P
r
e
c
i
s
i
o
n
@
k
=
T
P
@
k
T
P
@
k
+
F
P
@
k
Precision@k = \frac{TP@k}{TP@k+FP@k}
Precision@k=TP@k+FP@kTP@k
取值范围[0,1],越大越好。
例子:
Precision@3 = 2/3 = 0.67
Precision@4 = 2/4 = 0.50
Precision@5 = 3/5 = 0.60
即预测正确的相关结果占所有相关结果的比例:
R
e
c
a
l
l
@
k
=
T
P
@
k
T
P
@
k
+
F
N
@
k
Recall@k = \frac{TP@k}{TP@k+FN@k}
Recall@k=TP@k+FN@kTP@k
取值范围[0,1],越大越好。
例子:
Recall@3 = 2/4 = 0.50
Recall@4 = 2/4 = 0.50
Recall@5 = 3/4 = 0.75
即Precision@k和Recall@k的调和平均数:
F
1
@
k
=
2
×
P
r
e
c
i
s
i
o
n
@
k
×
R
e
c
a
l
l
@
k
P
r
e
c
i
s
i
o
n
@
k
+
R
e
c
a
l
l
@
k
F1@k = \frac{2 \times Precision@k \times Recall@k}{Precision@k+Recall@k}
F1@k=Precision@k+Recall@k2×Precision@k×Recall@k
取值范围[0,1],越大越好。
例子:
F1@3 = (2 * 0.67 * 0.50)/(0.67 + 0.50) = 0.57
F1@4 = (2 * 0.50 * 0.50)/(0.50 + 0.50) = 0.50
F1@5 = (2 * 0.60 * 0.75)/(0.60 + 0.75) = 0.67
注意:Precision@k、Recall@k、F1@k评价指标都是与返回顺序无关的。
归一化折损累计增益(Normalized Discounted Cumulative Gain,NDCG),是一种考虑了返回顺序的评价指标。取值范围[0,1],越大效果越好。
N
D
C
G
@
k
=
D
C
G
@
k
I
D
C
G
@
k
NDCG@k = \frac{DCG@k}{IDCG@k}
NDCG@k=IDCG@kDCG@k
其中,
D
C
G
@
k
=
∑
i
=
1
k
r
e
l
i
l
o
g
2
(
i
+
1
)
DCG@k=\sum_{i=1}^{k}\frac{rel_{i}}{log_{2}(i+1) }
DCG@k=i=1∑klog2(i+1)reli
r
e
l
i
rel_i
reli指第
i
i
i个结果的真实相关性分数。
I
D
C
G
@
k
=
∑
i
=
1
∣
R
E
L
∣
r
e
l
i
l
o
g
2
(
i
+
1
)
IDCG@k=\sum_{i=1}^{|REL|}\frac{rel_{i}}{log_{2}(i+1) }
IDCG@k=i=1∑∣REL∣log2(i+1)reli
IDCG也就是理想的DCG(Ideal DCG)。|REL| 表示,结果按照真实相关性从大到小排序,取前k个结果组成的集合的个数。
举个例子:
假设对于一个查询,搜索模型得到8个结果{A, B, C, D, E, F, G, H},分数是{0.94, 0.93, 0.92, 0.91, 0.8, 0.7, 0.6, 0.5},其真实相关性分数是{3, 2, 3, 0, 1, 2, 3, 0},求NDCG@6。
首先求DCG@6:
Item | r e l i rel_i reli | r e l i l o g 2 ( i + 1 ) \frac{rel_{i}}{log_{2}(i+1)} log2(i+1)reli |
---|---|---|
A | 3 | 3 |
B | 2 | 1.26185950 |
C | 3 | 1.5 |
D | 0 | 0 |
E | 1 | 0.38685280 |
F | 2 | 0.71241437 |
N D C G @ 6 = 3 + 1.26185950 + 1.5 + 0 + 0.38685280 + 0.71241437 = 6.86112667 NDCG@6=3+1.26185950+1.5+0+0.38685280+0.71241437=6.86112667 NDCG@6=3+1.26185950+1.5+0+0.38685280+0.71241437=6.86112667
再求IDCG@6:
对真实相关性分数排序,得到{3, 3, 3, 2, 2, 1, 0, 0}
r e l i rel_i reli | r e l i l o g 2 ( i + 1 ) \frac{rel_{i}}{log_{2}(i+1)} log2(i+1)reli |
---|---|
3 | 3 |
3 | 1.89278926 |
3 | 1.5 |
2 | 0.86135311 |
2 | 0.77370561 |
1 | 0.35620718 |
I D C G @ 6 = 3 + 1.89278926 + 1.5 + 0.86135311 + 0.77370561 + 0.35620718 = 8.38405516 IDCG@6=3+1.89278926+1.5+0.86135311+0.77370561+0.35620718=8.38405516 IDCG@6=3+1.89278926+1.5+0.86135311+0.77370561+0.35620718=8.38405516
最终, N D C G @ 6 = 6.86112667 / 8.38405516 = 0.81835419 NDCG@6=6.86112667/8.38405516=0.81835419 NDCG@6=6.86112667/8.38405516=0.81835419,约82%。
注意点:
1、分母
l
o
g
2
(
i
+
1
)
log_2{(i+1)}
log2(i+1)相当于对返回位置进行了惩罚,越往后惩罚越大。分母
I
D
C
G
@
k
IDCG@k
IDCG@k是为了将分数归一化到[0,1]之间。
2、模型分数{0.94, 0.93, 0.92, 0.91, 0.8, 0.7, 0.6, 0.5}的大小不会影响最终NDCG的值,比如改为{100, 90, 80, 70, 60, 50, 40, 30},最终NDCG分数是一样的,只要保证是从大到小排序就行,因为在实际中,一般也是按照模型分数从大到小的顺序返回结果。
代码:
import numpy as np
from sklearn import metrics
# NDCG
true_relevance = np.array([[3, 2, 3, 0, 1, 2, 3, 0]])
scores = np.array([[0.94, 0.93, 0.92, 0.91, 0.8, 0.7, 0.6, 0.5]])
print(metrics.ndcg_score(true_relevance, scores, k=6)) # 0.8183541904922857
参考文章:
[1] 搜索评价指标——NDCG
[2] 信息检索中的度量指标全解析