热门推荐:基于评分排序推荐

503 阅读1分钟

热门推荐就是给用户推荐热门item,且每个用户的推荐结果几乎一样。不满足个性化推荐,且覆盖率较低,不利于挖掘长尾信息。但是在冷启动时可以采用。

以电影评分数据为例,步骤如下:

  • (1)计算每部电影的评分权重;
  • (2)为用户推荐排序靠前且用户没有看过的电影。
步骤(1)中采用了IMDB网站的评分权重计算公式:
weighted rating = [v / (v+m)] * R + [m / (v+m)] * C,
其中v代表该电影被评分的次数(即有多少人对这部电影进行了评分),
m代表最小被评分次数(可取所有电影被评分次数的85%~95%百分位数,只有当某部电影被评分次数超过该值时其评分才具有可信度),
R代表该电影的平均评分,C代表所有电影平均评分的平均值。

代码实现:

import os
import random
from operator import itemgetter
from utils.movielen_read import loadfile

base_path = os.path.dirname(os.path.abspath(__file__)) + "/../../data/"

def load_data(train_rate=1):
   train_items_ratings = {}
   test_data = {}
   for line in loadfile(base_path + "ml-1m/ratings.dat"):
       arr = line.split("::")
       if random.random() < train_rate:
           train_items_ratings.setdefault(arr[1], set())
           train_items_ratings[arr[1]].add(arr[2])
       else:
           test_data.setdefault(arr[0], set())
           test_data[arr[0]].add(arr[1])

   return train_items_ratings, test_data

def calculate_weigh(items_ratings):
   """计算权重"""
   items_weigh = {}
   # 每个item的平均分及评分的次数
   items_means = {}
   sum_rating = 0
   sum_rating_times = 0
   for item, values in items_ratings.items():
       items_means.setdefault(item, list())
       sum = 0
       for value in values:
           sum += int(value)
       mean_rating = sum / len(values)
       sum_rating += mean_rating
       sum_rating_times += len(values)
       items_means[item].append(mean_rating)
       items_means[item].append(len(values))

   all_mean_rating = sum_rating / len(items_ratings)
   all_mean_rating_time = sum_rating_times / len(items_ratings)

   for item, values in items_means.items():
       weigh = (values[1] / (values[1] + all_mean_rating_time)) * values[0] + \
               (all_mean_rating / (values[1] + all_mean_rating_time)) * all_mean_rating
       items_weigh.setdefault(item, weigh)
   items_weigh = sorted(items_weigh.items(), key=itemgetter(1), reverse=True)
   print(items_weigh)