热门推荐就是给用户推荐热门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)