目录标题
- 题目:使用协同过滤(基于用户)构建简单的电影推荐系统
- 1.1.1 实验目的
- 1.1.2 实验内容及步骤
- 1.1.3 程序运行过程、方法和运行结果
- 1.1.4 实验小结
题目:使用协同过滤(基于用户)构建简单的电影推荐系统
1.1.1 实验目的
1.了解协同过滤理论基础
2.平台实现算法
3. 编程实现协同过滤算法
1.1.2 实验内容及步骤
假设我们以字典形式保存用户关于电影的评分数据,请构建一个电影推荐程序。
STEP1:编写函数计算欧式距离字典数据中两两用户的欧式距离。
STEP2:编写函数依据欧式距离大小以及协同过滤算法(用户)实现电影的推荐。
1.1.3 程序运行过程、方法和运行结果
此处采用欧氏距离计算相似性
# 自定义数据集 电影及其最低评分
# A dictionary of movie critics and their ratings of a small#
critics = {
'A': {'老炮儿':3.5,'唐人街探案': 1.0},
'B': {'老炮儿':2.5,'唐人街探案': 3.5,'星球大战': 3.0, '寻龙诀': 3.5,
'神探夏洛克': 2.5, '小门神': 3.0},
'C': {'老炮儿':3.0,'唐人街探案': 3.5,'星球大战': 1.5, '寻龙诀': 5.0,
'神探夏洛克': 3.0, '小门神': 3.5},
'D': {'老炮儿':2.5,'唐人街探案': 3.5,'寻龙诀': 3.5, '神探夏洛克': 4.0},
'E': {'老炮儿':3.5,'唐人街探案': 2.0,'星球大战': 4.5, '神探夏洛克': 3.5,
'小门神': 2.0},
'F': {'老炮儿':3.0,'唐人街探案': 4.0,'星球大战': 2.0, '寻龙诀': 3.0,
'神探夏洛克': 3.0, '小门神': 2.0},
'G': {'老炮儿':4.5,'唐人街探案': 1.5,'星球大战': 3.0, '寻龙诀': 5.0,
'神探夏洛克': 3.5}
}
print(critics['B']['星球大战'])
3.0
# STEP1:编写函数计算欧式距离 字典数据中两两用户的欧式距离。
from math import sqrt
# Returns a distance-based similarity score for person1 and person2
def sim_distance(prefs, person1, person2):
# Get the list of shared_items
si = {}
# 判断person1和person2是否有相同同的观影经历,“是”将si[item]结果置为1,“否”则返回0
for item in prefs[person1]:
if item in prefs[person2]:
si[item] = 1
#print(item)
# if they have no ratings in common, return 0
if len(si) == 0:
return 0
# Add up the squares of all the differences
# 列表推导式 :如果A用户和B用户有相同同的观影经历,则求它们距离的平方和
sum_of_squares = sum([pow(prefs[person1][item] - prefs[person2][item], 2) for item in prefs[person1] if item in prefs[person2]])
#在欧氏距离公式中,取值范围会很大,一般通过如下方式归一化:sim = 1 / (1 + 欧氏距离)
return 1 / (1 + sqrt(sum_of_squares))
print("A用户和B用户之间的欧氏距离:",sim_distance(critics, 'A', 'B'))
A用户和B用户之间的欧氏距离: 0.2708131845707603
# STEP2:编写函数依据欧式距离大小以及协同过滤算法(用户)实现电影的推荐。
# Gets recommendations for a person by using a weighted average
# of every other user's rankings similarity=sim_distance重命名计算欧几里得距离函数
def getRecommendations(prefs, person, similarity=sim_distance):
totals = {}
simSums = {}
for other in prefs:
# don't compare me to myself
if other == person:
continue
#计算相似度
sim = similarity(prefs, person, other)
# ignore scores of zero or lower
if sim <= 0:
continue
for item in prefs[other]:
# only score movies I haven't seen yet
if item not in prefs[person] or prefs[person][item] == 0:
# Similarity * Score
totals.setdefault(item, 0)
#求该用户没看过的电影的加权分的和 把相似性和对于每个电影的实际评分相乘,就是电影的加权分
totals[item] += prefs[other][item] * sim
# Sum of similarities
simSums.setdefault(item, 0)
#求这些电影的相似度之和
simSums[item] += sim
# Create the normalized list
#标准化 推荐度 = 总相似度之和(总分/加权分的和)/相似性
rankings = [(total / simSums[item], item) for item, total in totals.items()]
# Return the sorted list
rankings.sort()
# 对列表的元素进行反向排序
rankings.reverse()
return rankings
print("给A用户推荐以下电影:\n",getRecommendations(critics, 'A'))
给A用户推荐以下电影:
[(4.152703901679927, '寻龙诀'), (3.304207244554503, '神探夏洛克'), (3.045124682040546, '星球大战'), (2.5333970389243956, '小门神')]
1.1.4 实验小结
基于用户的协同过滤算法
思想:
寻找相似用户邻居,用相似邻居偏好来推荐物品
步骤:
一、使用欧氏距离(或其它方法)计算相似性;
二、把相似性和对于每个电影的实际评分相乘,就是电影的加权分;
三、计算推荐度=加权分之和/相似性;
四、将推荐度最高的电影推荐给用户。