-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevaluation.py
51 lines (41 loc) · 1.96 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
import numpy as np
import pandas as pd
def downvote_seen_items(scores, data, data_description):
assert isinstance(scores, np.ndarray), 'Scores must be a dense numpy array!'
itemid = data_description['items']
userid = data_description['users']
# get indices of observed data, corresponding to scores array
# we need to provide correct mapping of rows in scores array into
# the corresponding user index (which is assumed to be sorted)
row_idx, test_users = pd.factorize(data[userid], sort=True)
assert len(test_users) == scores.shape[0]
col_idx = data[itemid].values
# downvote scores at the corresponding positions
scores[row_idx, col_idx] = scores.min() - 1
def topn_recommendations(scores, topn=10):
recommendations = np.apply_along_axis(topidx, 1, scores, topn)
return recommendations
def topidx(a, topn):
parted = np.argpartition(a, -topn)[-topn:]
return parted[np.argsort(-a[parted])]
def model_evaluate(recommended_items, holdout, holdout_description, topn=10):
itemid = holdout_description['items']
holdout_items = holdout[itemid].values
assert recommended_items.shape[0] == len(holdout_items)
hits_mask = recommended_items[:, :topn] == holdout_items.reshape(-1, 1)
# HR calculation
hr = np.mean(hits_mask.any(axis=1))
# MRR calculation
n_test_users = recommended_items.shape[0]
hit_rank = np.where(hits_mask)[1] + 1.0
mrr = np.sum(1 / hit_rank) / n_test_users
# coverage calculation
n_items = holdout_description['n_items']
cov = np.unique(recommended_items).size / n_items
return hr, mrr, cov
def calculate_rmse(scores, holdout, holdout_description):
user_idx = np.arange(holdout.shape[0])
item_idx = holdout[holdout_description['items']].values
feedback = holdout[holdout_description['feedback']].values
predicted_rating = scores[user_idx, item_idx]
return np.mean(np.abs(predicted_rating-feedback)**2)