1 协同过滤算法介绍
1.什么是协同过滤算法
1. 协同过滤推荐算法是诞生最早,并且较为著名的推荐算法,主要的功能是预测和推荐。
2. 算法通过对用户历史行为数据的挖掘发现用户的偏好,基于不同的偏好对用户进行群组划分并推荐品味相似的商品。
3. 协同过滤推荐算法分为两类,分别是基于用户的协同过滤算法(user-based collaboratIve filtering),和基于物品的协同过滤算法(item-based collaborative filtering)。
4. 简单的说就是:人以类聚,物以群分。下面我们将分别说明这两类推荐算法的原理和实现方法。
2.基于用户的协同过滤算法
1. 协同过滤算法是一种基于关联规则的算法,以购物行为为例。
2. 假设有甲和乙两名用户,有a、b、c三款产品。
3. 如果甲和乙都购买了a和b这两种产品,我们可以假定甲和乙有近似的购物品味。
4. 当甲购买了产品c而乙还没有购买c的时候,我们就可以把c也推荐给乙。
5. 这是一种典型的user-based情况,就是以user的特性做为一种关联。
举例:
3.基于物品的协同过滤算法
举例:
1)物品组合(A,D)被同时偏好出现的次数最多,因而可以认为A/D两件物品的相似度最高
2)从而,可以为选择了A物品的用户推荐D物品
2 欧几里德距离评价
1.欧几里得度量 是什么?
1. 欧几里得度量(euclidean metric)(也称欧氏距离)是一个通常采用的距离定义
2. 指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。
3. 在二维和三维空间中的欧氏距离就是两点之间的实际距离
4. n维空间的公式
2. 借助“欧几里得度量” 寻找偏好相似的用户原理
1)在示例中,5个用户分别对两件商品进行了评分。
2)这里的分值可能表示真实的购买,也可以是用户对商品不同行为的量化指标。
3)例如,浏览商品的次数,向朋友推荐商品,收藏,分享,或评论等等。
4)这些行为都可以表示用户对商品的态度和偏好程度。
5)在散点图中,Y轴是商品1的评分,X轴是商品2的评分,通过用户的分布情况可以发现,A,C,D三个用户距离较近。
6)用户A(3.3 6.5)和用户C(3.6 6.3),用户D(3.4 5.8)对两件商品的评分较为接近。而用户E和用户B则形成了另一个群体。
7)散点图虽然直观,但无法投入实际的应用,也不能准确的度量用户间的关系。
8)因此我们需要通过数字对用户的关系进行准确的度量,并依据这些关系完成商品的推荐。
1. 通过公式我们获得了5个用户相互间的欧几里德系数,也就是用户间的距离。
2. 系数越小表示两个用户间的距离越近,偏好也越是接近。
3. 不过这里有个问题,太小的数值可能无法准确的表现出不同用户间距离的差异,因此我们对求得的系数取倒数,使用户间的距离约接近,数值越大。
4. 在下面的表格中,可以发现,用户A&C用户A&D和用户C&D距离较近。同时用户B&E的距离也较为接近。与我们前面在散点图中看到的情况一致。
3 使用协同过滤算法简单测试
第一步,将数据读取并格式化为字典形式,便于解析
第二步:借助"欧几里德"算法计算用户相似度
第三步:计算某个用户与其他用户的相似度
第四步:根据相似度最高的用户喜好商品排序,把相似度最高用户的喜好推荐给当前用户
#photo.txt
1,华为p30,2.0
1,三星s10,5.0
1,小米9,2.6
2,华为p30,1.0
2,vivo,5.0
2,htc,4.6
3,魅族,2.0
3,iphone,5.0
3,pixel2,2.6
---------------------------------------------------------
with open('./phone.txt', 'r', encoding='utf-8') as fp:
content = fp.readlines()
# 第一步,将数据读取并格式化为字典形式,便于解析
def parse_data():
with open('./phone.txt','r',encoding='utf-8') as fp:
content = fp.readlines()
# 将用户、评分、和手机写入字典data
data = {}
for line in content:
line = line.strip().split(',')
#如果字典中没有某位用户,则使用用户ID来创建这位用户
if not line[0] in data.keys():
data[line[0]] = {line[1]:line[2]}
#否则直接添加以该用户ID为key字典中
else:
data[line[0]][line[1]] = line[2]
return data
data = parse_data()
'''
{
"1":{
"华为p30":"2.0",
"三星s10":"5.0",
"小米9":"2.6"
},
"2":{
"华为p30":"1.0",
"vivo":"5.0",
"htc":"4.6"
},
"3":{
"魅族":"2.0",
"iphone":"5.0",
"pixel2":"2.6"
}
}
'''
# 第二步:借助"欧几里德"算法计算用户相似度
from math import *
def Euclid(user1, user2):
# 取出两位用户购买过的手机和评分
user1_data = data[user1]
user2_data = data[user2]
distance = 0
# 找到两位用户都购买过的手机,并计算欧式距离
for key in user1_data.keys():
if key in user2_data.keys():
# 注意,distance越大表示两者越相似
distance += pow(float(user1_data[key]) - float(user2_data[key]), 2)
return 1 / (1 + sqrt(distance)) # 这里返回值越小,相似度越大
# 第三步:计算某个用户与其他用户的相似度
def top_simliar(userID):
res = []
for userid in data.keys():
#排除与自己计算相似度
if not userid == userID:
simliar = Euclid(userID,userid)
res.append((userid,simliar)) # res = # [('2', 0.5), ('3', 1.0)]
res.sort(key=lambda val:val[1])
return res
# 第四步:根据相似度最高的用户喜好商品排序,把相似度最高用户的喜好推荐给当前用户
def recommend(userid):
#相似度最高的用户
top_sim_user = top_simliar(userid)[0][0] # top_sim_user=2 找到相似度最高的用户ID
#相似度最高的用户的购买记录
items = data[top_sim_user] # items = {'华为p30': '1.0', 'vivo': '5.0', 'htc': '4.6'}
recommendations = []
#筛选出该用户未购买的手机并添加到列表中
for item in items.keys():
if item not in data[userid].keys():
recommendations.append((item,items[item]))
recommendations.sort(key=lambda val:val[1],reverse=True)#按照评分排序
return recommendations
if __name__ == '__main__':
# 找到与用户id为1的用户相似度最高的用户
print(recommend('1')) # [('vivo', '5.0'), ('htc', '4.6')]
来源:oschina
链接:https://my.oschina.net/u/4346445/blog/4263309