动手实现推荐系统评价指标

2022 年 6 月 1 日 机器学习与推荐算法

代码地址:https://github.com/dqdallen/Torch-RecHub/blob/main/torch_rechub/basic/metric.py

点击阅读原文可以前往代码仓库

导入必要的模块


from sklearn.metrics import roc_auc_score
import numpy as np

工具函数

用于对数据按用户分组,去每个用户的前topk个推荐列表。


def get_user_pred(y_true, y_pred, users):
  """divide the result into different group by user id

  Args:
    y_true: array, all true labels of the data
    y_pred: array, the predicted score
    users: array, user id

  Return:
    user_pred: dict, key is user id and value is the labels and scores of each user
  """

  user_pred = {}
  for i, u in enumerate(users):
    if u not in user_pred:
      user_pred[u] = [[y_true[i]], [y_pred[i]]]
    else:
      user_pred[u][0].append(y_true[i])
      user_pred[u][1].append(y_pred[i])

  return user_pred


def get_user_topk(y_true, y_pred, users, k):
  """sort y_pred and find topk results
  this function is used to find topk predicted scores
  and the corresponding index is applied to find the corresponding labels

  """

  user_pred = get_user_pred(y_true, y_pred, users)
  for u in user_pred:
    idx = np.argsort(user_pred[u][1])[::-1][:k]
    user_pred[u][1] = np.array(user_pred[u][1])[idx]
    user_pred[u][0] = np.array(user_pred[u][0])[idx]
  return user_pred

AUC


def auc_score(y_true, y_pred):

  return roc_auc_score(y_true, y_pred)

GAUC


def gauc_score(y_true, y_pred, users, weights=None):
  """compute GAUC

  Args:
    y_true: array, dim(N, ), all true labels of the data
    y_pred: array, dim(N, ), the predicted score
    users: array, dim(N, ), user id
    weight: dict, it contains weights for each group.
        if it is None, the weight is equal to the number
        of times the user is recommended
  Return:
    score: float, GAUC
  """

  assert len(y_true) == len(y_pred) and len(y_true) == len(users)

  user_pred = get_user_topk(y_true, y_pred, users, len(users))
  score = 0
  num = 0
  for u in user_pred.keys():
    auc = auc_score(user_pred[u][0], user_pred[u][1])
    if weights is None:
      wg = len(user_pred[u][0])
    else:
      wg = weights[u]
    auc *= wg
    num += wg
    score += auc
  return score / num

LogLoss


def log_loss(y_true, y_pred):
  score = y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred)
  return -score.sum() / len(y_true)


NDCG


def ndcg_score(user_pred, k):
  """compute NDCG
  Args:
    user_pred: dict, computed by get_user_topk()
  """

  rank = np.arange(1, k+1, 1)
  idcgs = 1. / np.log2(rank + 1)
  idcg = sum(idcgs)
  score = 0
  for u in user_pred:
    dcgs = idcgs[np.where(user_pred[u][0] == 1)]
    dcg = sum(dcgs)
    score += dcg / idcg
  return score / len(user_pred.keys())


HitRate


def hit_score(user_pred):
  score = 0
  for u in user_pred:
    if 1 in user_pred[u][0]:
      score += 1.0
  return score / len(user_pred.keys())

MRR


def mrr_score(user_pred):
  score = 0
  for u in user_pred:
    if 1 in user_pred[u][0]:
      score += 1.0 / (np.where(user_pred[u][0] == 1)[0][0] + 1)
  return score / len(user_pred.keys())

Recall


def recall_score(user_pred):
  score = 0
  for u in user_pred:
    score += sum(user_pred[u][0]) * 1. / len(user_pred[u][0])
  return score / len(user_pred.keys())

选择topk评价指标


def topk_metrics(y_true, y_pred, users, k, metric_type):
  """choice topk metrics and compute it
  the metrics contains 'ndcg', 'mrr', 'recall' and 'hit'

  Args:
    y_true: array, dim(N, ), all true labels of the data
    y_pred: array, dim(N, ), the predicted score
    k: int, the number of topk
    metric_type: string, choice the metric,
    it can be lowercase 'ndcg' or uppercase 'NDCG' or 'Ndcg' and so on

  Return:
    the score of topk metric

  """

  assert len(y_true) == len(y_pred) and len(y_true) == len(users)

  user_pred = get_user_topk(y_true, y_pred, users, k)
  if metric_type.lower() == 'ndcg':
    return ndcg_score(user_pred, k)
  elif metric_type.lower() == 'mrr':
    return mrr_score(user_pred)
  elif metric_type.lower() == 'recall':
    return recall_score(user_pred)
  elif metric_type.lower() == 'hit':
    return hit_score(user_pred)
  else:
    raise ValueError('metric_type error, choice from \'ndcg\', \'mrr\', \'recall\', \'hit\'')

测试用例


y_pred = np.array([0.3, 0.2, 0.5, 0.9, 0.7, 0.31, 0.8, 0.1, 0.4, 0.6])
y_true = np.array([1, 0, 0, 1, 0, 0, 1, 0, 0, 1])
users_id = np.array([ 2, 1, 0, 2, 1, 0, 0, 2, 1, 1])

print('auc: ', auc_score(y_true, y_pred))
print('gauc: ', gauc_score(y_true, y_pred, users_id))
print('log_loss: ', log_loss(y_true, y_pred))

for mt in ['ndcg', 'mrr', 'recall', 'hit','s']:
  tm = topk_metrics(y_true, y_pred, users_id, 3, metric_type=mt)
  print(f'{mt}: {tm}')



欢迎干货投稿 \ 论文宣传 \ 合作交流

推荐阅读

预训练模型在信息流推荐中的应用与探索

论文周报 | 推荐系统领域最新研究进展

基于Prompt的用户自选公平性推荐算法

由于公众号试行乱序推送,您可能不再准时收到机器学习与推荐算法的推送。为了第一时间收到本号的干货内容, 请将本号设为星标,以及常点文末右下角的“在看”。

喜欢的话点个在看吧👇
登录查看更多
1

相关内容

专知会员服务
24+阅读 · 2021年8月3日
专知会员服务
76+阅读 · 2021年3月16日
专知会员服务
50+阅读 · 2020年12月14日
【干货书】机器学习速查手册,135页pdf
专知会员服务
125+阅读 · 2020年11月20日
专知会员服务
123+阅读 · 2020年9月8日
【推荐系统/计算广告/机器学习/CTR预估资料汇总】
专知会员服务
87+阅读 · 2019年10月21日
强化学习最新教程,17页pdf
专知会员服务
174+阅读 · 2019年10月11日
机器学习入门的经验与建议
专知会员服务
92+阅读 · 2019年10月10日
【电子书推荐】Data Science with Python and Dask
专知会员服务
43+阅读 · 2019年6月1日
Python推荐系统框架:RecQ
专知
12+阅读 · 2019年1月21日
【推荐】用TensorFlow实现LSTM社交对话股市情感分析
机器学习研究会
11+阅读 · 2018年1月14日
【推荐】用Python/OpenCV实现增强现实
机器学习研究会
15+阅读 · 2017年11月16日
【推荐】MXNet深度情感分析实战
机器学习研究会
16+阅读 · 2017年10月4日
【推荐】用Tensorflow理解LSTM
机器学习研究会
36+阅读 · 2017年9月11日
【推荐】RNN/LSTM时序预测
机器学习研究会
25+阅读 · 2017年9月8日
【推荐】SVM实例教程
机器学习研究会
17+阅读 · 2017年8月26日
【推荐】深度学习思维导图
机器学习研究会
15+阅读 · 2017年8月20日
国家自然科学基金
1+阅读 · 2015年12月31日
国家自然科学基金
6+阅读 · 2014年12月31日
国家自然科学基金
1+阅读 · 2013年12月31日
国家自然科学基金
4+阅读 · 2013年12月31日
国家自然科学基金
5+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2009年12月31日
Arxiv
0+阅读 · 2022年7月29日
Arxiv
14+阅读 · 2018年4月18日
VIP会员
相关VIP内容
专知会员服务
24+阅读 · 2021年8月3日
专知会员服务
76+阅读 · 2021年3月16日
专知会员服务
50+阅读 · 2020年12月14日
【干货书】机器学习速查手册,135页pdf
专知会员服务
125+阅读 · 2020年11月20日
专知会员服务
123+阅读 · 2020年9月8日
【推荐系统/计算广告/机器学习/CTR预估资料汇总】
专知会员服务
87+阅读 · 2019年10月21日
强化学习最新教程,17页pdf
专知会员服务
174+阅读 · 2019年10月11日
机器学习入门的经验与建议
专知会员服务
92+阅读 · 2019年10月10日
【电子书推荐】Data Science with Python and Dask
专知会员服务
43+阅读 · 2019年6月1日
相关资讯
Python推荐系统框架:RecQ
专知
12+阅读 · 2019年1月21日
【推荐】用TensorFlow实现LSTM社交对话股市情感分析
机器学习研究会
11+阅读 · 2018年1月14日
【推荐】用Python/OpenCV实现增强现实
机器学习研究会
15+阅读 · 2017年11月16日
【推荐】MXNet深度情感分析实战
机器学习研究会
16+阅读 · 2017年10月4日
【推荐】用Tensorflow理解LSTM
机器学习研究会
36+阅读 · 2017年9月11日
【推荐】RNN/LSTM时序预测
机器学习研究会
25+阅读 · 2017年9月8日
【推荐】SVM实例教程
机器学习研究会
17+阅读 · 2017年8月26日
【推荐】深度学习思维导图
机器学习研究会
15+阅读 · 2017年8月20日
相关基金
国家自然科学基金
1+阅读 · 2015年12月31日
国家自然科学基金
6+阅读 · 2014年12月31日
国家自然科学基金
1+阅读 · 2013年12月31日
国家自然科学基金
4+阅读 · 2013年12月31日
国家自然科学基金
5+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2009年12月31日
Top
微信扫码咨询专知VIP会员