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, }