This repository has been archived by the owner on Jun 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
evaluation.py
62 lines (47 loc) · 1.9 KB
/
evaluation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from chainer import cuda, function
class NDCG(function.Function):
def __init__(self, k=0):
self.k = k
def forward(self, inputs):
xp = cuda.get_array_module(*inputs)
y, t = inputs
# Assert arrays have the same shape
if t.shape != y.shape:
raise ValueError("Input arrays have different shapes")
# Computing nDCG on empty array should just return 0.0
if t.shape[0] == 0:
return xp.asarray(0.0),
# Compute predicted indices by arg sorting
predicted_indices = xp.argsort(y)
best_indices = xp.argsort(t)
# Predicted and theoretically best relevance labels
predicted_relevance = xp.flip(t[predicted_indices], axis=0)
best_relevance = xp.flip(t[best_indices], axis=0)
# Compute needed statistics
length = predicted_relevance.shape[0]
arange = xp.arange(length)
last = min(self.k, length)
if last < 1:
last = length
# Compute regular DCG
dcg_numerator = 2 ** predicted_relevance[:last] - 1
dcg_denominator = xp.log2(arange[:last] + 2)
dcg = xp.sum(dcg_numerator / dcg_denominator)
# Compute iDCG for normalization
idcg_numerator = (2 ** best_relevance[:last] - 1)
idcg_denominator = (xp.log2(arange[:last] + 2))
idcg = xp.sum(idcg_numerator / idcg_denominator)
if idcg == 0.0:
return xp.asarray(1.0),
return xp.asarray(dcg / idcg),
def ndcg(y, t, k=0):
"""
Computes the nDCG@k for given list of true relevance labels (y_true) and
given list of predicted relevance labels (y_score)
:param y_true: The ground truth relevance labels
:param y_score: The predicted relevance scores
:param k: The cut-off point (if set to smaller or equal to 0, it does not
cut-off)
:return: The nDCG@k value
"""
return NDCG(k=k)(y, t)