通用
RMSE(均方根误差)
R M S E = ∑ t = 1 n ( y ^ t − y t ) 2 n RMSE= \sqrt \frac{\sum _{t=1}^n (\hat y_t -y_t)^2}{n} RMSE=n∑t=1n(y^t−yt)2
MAE(均方误差)
M A E = ∑ t = 1 n ∣ y ^ t − y t ∣ n MAE= \sqrt \frac{\sum _{t=1}^n |\hat y_t -y_t|}{n} MAE=n∑t=1n∣y^t−yt∣
recall / precision / auc
详情见这里。
ROI
R
O
I
=
r
e
t
u
r
n
−
c
o
s
t
c
o
s
t
ROI = \frac{return - cost}{cost}
ROI=costreturn−cost
ROI越大证明推荐系统越好。
排序
Mean Average Precision (MAP)
对于一个query i i i, 如果某个系统检索出来的文档集合 D O C DOC DOC中排在前面的文档都和 i i i相关,排在后面的都不相关,则证明这个系统的检索能力较强,因而基于这个思想,query i i i的平均准确率(Average Precision, AP)应运而生,公式如下:
A P = ∑ j = 1 n i P ( j ) ⋅ y i , j AP = \sum_{j=1}^{n_i} P(j)\cdot y_{i,j} AP=j=1∑niP(j)⋅yi,j
其中
y
i
,
j
y_{i,j}
yi,j代表的是doc
j
j
j和query
i
i
i是否相关,相关为1,反之为0,
P
(
j
)
P(j)
P(j)代表的是文档集合的排序分布状况,公式如下:
P
(
j
)
=
∑
k
:
π
i
(
k
)
≤
π
i
(
j
)
y
(
i
,
k
)
π
i
(
j
)
P(j)=\frac{\sum_{k:\pi_i(k)\le\pi_i(j)}y(i,k)}{\pi_i(j)}
P(j)=πi(j)∑k:πi(k)≤πi(j)y(i,k)
其中 π i ( j ) \pi_i(j) πi(j)代表的是doc j j j在排序中的位置,下标从1开始。
举例说明上述抽象概念,例如针对一个query,一个系统检索出的资源为1,2,3,4,而其中只有1,2,4和这个query相关,因而上述信息列成表格如下所示,
资源 | 相关性 |
---|---|
doc_1 | 1 |
doc_2 | 1 |
doc_3 | 0 |
doc_4 | 1 |
因而根据上面平均准确率的计算公式可得
A
P
=
(
(
1
/
1
)
×
1
+
(
2
/
2
)
×
1
+
(
2
/
3
)
×
0
+
(
3
/
4
)
×
1
)
/
3
=
11
/
12
AP=((1/1) \times 1 + (2 / 2) \times 1 + (2 / 3) \times 0 + (3/4) \times 1) / 3 = 11/12
AP=((1/1)×1+(2/2)×1+(2/3)×0+(3/4)×1)/3=11/12
MAP代表的是所有AP的平均值。个人认为MAP的缺点为其并没有考虑与一个query相关的文档集合的内部排序该如何做,比如说上述表格中,系统检索出<doc_1, doc_2, doc_3, doc_4>与检索出<doc_4, doc_2, doc_3, doc_1>的效果是相同的,因为前后两个序列的相关性分布是相同的。
Mean Reciprocal Rank(MRR)
该指标依然关注的是针对一个query,其相关的doc的排序情况如何,而与MAP不同的是,MRR只关注第一个相关doc的排序情况如何,公式如下所示:
M
R
R
=
1
∣
Q
∣
∑
i
=
1
∣
Q
∣
1
r
a
n
k
i
MRR = \frac{1}{|Q|} \sum_{i=1}^{|Q|} \frac{1}{rank_i}
MRR=∣Q∣1i=1∑∣Q∣ranki1
其中 ∣ Q ∣ |Q| ∣Q∣代表的是query的个数, r a n k i rank_i ranki代表的是第i个query其第一个相关结果在某个系统返回的检索结果中的排序位置。
NDCG(Normalized Discounted Cumulative Gain)
与MAP和MRR不同的是,NDCG关注了与query相关的文档之间的排序关系,其工作原理如下:
首先,针对一个query,某个系统检索出一系列文档,如下所示:
[ d o c 1 , d o c 2 , d o c 3 , . . . , d o c j , . . . , d o c n ] [doc_1, doc_2, doc_3,..., doc_j, ... , doc_n] [doc1,doc2,doc3,...,docj,...,docn]
而每个文档对于这个query的真实相关度如下所示,
[ r ( 1 ) , r ( 2 ) , r ( 3 ) , . . . , r ( j ) , . . . , r ( n ) ] [r(1), r(2), r(3), ...,r(j), ..., r(n) ] [r(1),r(2),r(3),...,r(j),...,r(n)]
通过上述信息可以计算出DCG,公式如下所示:
D C G = ∑ j = 1 n 2 r ( j ) − 1 l o g ( 1 + j ) DCG = \sum_{j=1}^n\frac{2^{r(j)}-1}{log(1+j)} DCG=j=1∑nlog(1+j)2r(j)−1
注意,上述的 l o g log log指的是 l o g 2 log2 log2,而且j是从1开始的,上述除以 l o g ( 1 + j ) log(1+j) log(1+j)的目的是因为排在前面的用户会优先去点,因而占的权重要高一些,而上述的文档列表的展现形式在理想状态中应该是根据相关度从大到小排的,因而这里将上述的文档经过降序排序之后,得到的文档序列如下所示:
[ R ( 1 ) , R ( 2 ) , R ( 3 ) , . . . , R ( j ) , . . . , R ( n ) ] [R(1), R(2), R(3), ...,R(j), ..., R(n) ] [R(1),R(2),R(3),...,R(j),...,R(n)]
这个时候计算出的DCG一定是最大的,即:
m a x D C G = ∑ j = 1 n 2 R ( j ) − 1 l o g ( 1 + j ) maxDCG = \sum_{j=1}^n\frac{2^{R(j)}-1}{log(1+j)} maxDCG=j=1∑nlog(1+j)2R(j)−1
最终得到nDCG为如下公式:
n D C G = D C G m a x D C G nDCG = \frac{DCG}{maxDCG} nDCG=maxDCGDCG
NDCG@k(Normalized Discounted Cumulative Gain@k)
另一种表达方式为:
D
C
G
=
∑
j
=
1
K
r
(
j
)
l
o
g
(
1
+
j
)
DCG = \sum_{j=1}^K\frac{r(j)}{log(1+j)}
DCG=j=1∑Klog(1+j)r(j)
其只关注前K个元素的排列顺序,而不关注尾部数据的排序情况。参考代码如下:
def NDCG_binary_at_k_batch(X_pred, heldout_batch, k=100):
'''
Normalized Discounted Cumulative Gain@k for binary relevance
ASSUMPTIONS: all the 0's in heldout_data indicate 0 relevance
'''
batch_users = X_pred.shape[0]
idx_topk_part = bn.argpartition(-X_pred, k, axis=1)
topk_part = X_pred[np.arange(batch_users)[:, np.newaxis],
idx_topk_part[:, :k]]
idx_part = np.argsort(-topk_part, axis=1)
# X_pred[np.arange(batch_users)[:, np.newaxis], idx_topk] is the sorted
# topk predicted score
idx_topk = idx_topk_part[np.arange(batch_users)[:, np.newaxis], idx_part]
# build the discount template
tp = 1. / np.log2(np.arange(2, k + 2))
DCG = (heldout_batch[np.arange(batch_users)[:, np.newaxis],
idx_topk].toarray() * tp).sum(axis=1)
IDCG = np.array([(tp[:min(n, k)]).sum()
for n in heldout_batch.getnnz(axis=1)])
NDCG = DCG / IDCG
return NDCG