先从AP说起。假如从5男5女当中找出所有女生,搜索结果如下:
系统1:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|
| 女 | 男 | 男 | 男 | 女 | 女 | 女 |
准确率:4/7
召回率:4/5
系统1:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|
| 女 | 女 | 女 | 女 | 男 | 男 | 男 |
准确率:4/7
召回率:4/5
系统1和系统2的正确率和召回率相同,但明显第二个检索系统更好,因为还要考虑顺序。一个良好的检索系统当然希望越相关的排在越前面越好,因此就出现了AP这个概念。
针对每一个位置的准确率做计算,然后再取平均,例如系统1有五个女生的位置,第一个出现在第一位置,因此正确率为1/1。再来找寻第二个女生位置在第五顺位,代表预测中的五个有两个预测正确,因此正确率为2/5,其他以此类推因此可以算出AP为:
系统1:
AP:(1/1+2/5+3/6+4/7+0)/5
系统2:
AP:(1/1+2/2+3/3+4/4+0)/5
代码:
def apk(actual, predicted, k=12):
"""
Computes the average precision at k.
This function computes the average prescision at k between two lists of
items.
Parameters
----------
actual : list
A list of elements that are to be predicted (order doesn't matter)
predicted : list
A list of predicted elements (order does matter)
k : int, optional
The maximum number of predicted elements
Returns
-------
score : double
The average precision at k over the input lists
"""
if len(predicted) > k:
predicted = predicted[:k]
score = 0.0
num_hits = 0.0
for i, p in enumerate(predicted):
if p in actual and p not in predicted[:i]:
num_hits += 1.0
score += num_hits / (i + 1.0)
# remove this case in advance
# if not actual:
# return 0.0
return score / min(len(actual), k)
MAP:mean average percision
MAP就是对于多组预测的AP取个平均值。
这里的输入参数虽然也叫actual, predicted,但它们均为二维列表(A list of lists),和AP中的参数涵义是不同的。
def mapk(actual, predicted, k=12):
"""
Computes the mean average precision at k.
This function computes the mean average prescision at k between two lists
of lists of items.
Parameters
----------
actual : list
A list of lists of elements that are to be predicted
(order doesn't matter in the lists)
predicted : list
A list of lists of predicted elements
(order matters in the lists)
k : int, optional
The maximum number of predicted elements
Returns
-------
score : double
The mean average precision at k over the input lists
"""
return np.mean([apk(a,p,k) for a,p in zip(actual, predicted)])



