| import numpy as np | |
| def cal_recall(pos_index, pos_len): | |
| rec_ret = np.cumsum(pos_index, axis=1) / pos_len.reshape(-1, 1) | |
| return rec_ret.mean(axis=0) | |
| def cal_ndcg(pos_index, pos_len): | |
| len_rank = np.full_like(pos_len, pos_index.shape[1]) | |
| idcg_len = np.where(pos_len > len_rank, len_rank, pos_len) | |
| iranks = np.zeros_like(pos_index, dtype=float) | |
| iranks[:, :] = np.arange(1, pos_index.shape[1] + 1) | |
| idcg = np.cumsum(1.0 / np.log2(iranks + 1), axis=1) | |
| for row, idx in enumerate(idcg_len): | |
| idcg[row, idx:] = idcg[row, idx - 1] | |
| ranks = np.zeros_like(pos_index, dtype=float) | |
| ranks[:, :] = np.arange(1, pos_index.shape[1] + 1) | |
| dcg = 1.0 / np.log2(ranks + 1) | |
| dcg = np.cumsum(np.where(pos_index, dcg, 0), axis=1) | |
| result = dcg / idcg | |
| return result.mean(axis=0) | |
| def cal_map(pos_index, pos_len): | |
| pre = pos_index.cumsum(axis=1) / np.arange(1, pos_index.shape[1] + 1) | |
| sum_pre = np.cumsum(pre * pos_index.astype(float), axis=1) | |
| len_rank = np.full_like(pos_len, pos_index.shape[1]) | |
| actual_len = np.where(pos_len > len_rank, len_rank, pos_len) | |
| result = np.zeros_like(pos_index, dtype=float) | |
| for row, lens in enumerate(actual_len): | |
| ranges = np.arange(1, pos_index.shape[1] + 1) | |
| ranges[lens:] = ranges[lens - 1] | |
| result[row] = sum_pre[row] / ranges | |
| return result.mean(axis=0) | |
| def cal_precision(pos_index, pos_len): | |
| rec_ret = pos_index.cumsum(axis=1) / np.arange(1, pos_index.shape[1] + 1) | |
| return rec_ret.mean(axis=0) | |
| """Function name and function mapper. | |
| Useful when we have to serialize evaluation metric names | |
| and call the functions based on deserialized names | |
| """ | |
| metrics_dict = { | |
| 'Precision': cal_precision, | |
| 'Recall': cal_recall, | |
| 'NDCG': cal_ndcg, | |
| 'MAP': cal_map, | |
| } | |