推荐算法:基于物品的协同过滤算法
- 参考《推荐系统实践》项亮
- 概念: 基于物品的协同过滤算法,优化算法
- 对比:用户协同过滤的优缺点
- python编码实现
1,算法定义
基于用户的协同过滤算法 | 基于商品的协同过滤算法 | |
---|---|---|
适用场景 | 时效性较强,用户个性化兴趣不太明显的领域 | 长尾物品丰富,用户个性化需求强烈的领域 |
用户较少的场合:新闻推荐 | 物品数远小于用户数的场合:图书、电子商务和电影网站 | |
注重点 | 兴趣相似的小群体的热点 | 维系用户的历史兴趣,推荐结果解释性强 |
用户交互特点 | 用户有新行为,不一定造成推荐结果的立即变化 | 推荐结果的实时变化 |
缺点 | 计算复杂度 --用户数的增长:近似于平方关系 ,推荐结果解释性不强 |
1.1算法优化
假定<用户-商品数据>如下,可以计算出商品之间的相似度
1::a 1::b 1::c 2::a
2::b 3::c 4::a 4::d
2,python实现
第一步: 计算商品之间的相似度(余弦相似度计算公式)
第二步: 过滤&生成推荐列表,偏好值累加求和
具体代码如下
# -*-coding:utf-8-*-
import math
#第一步: 计算每个商品之间的相似度
def getMostLikeItemsGroupK(itemUsersDict):
recommDict = {}
for i, usersI in itemUsersDict.items():
for j, usersJ in itemUsersDict.items():
if i < j:
if i not in recommDict.keys():
recommDict[i] = {}
if j not in recommDict.keys():
recommDict[j] = {}
# 计算相似度,共同交互商品数
ratio= 0.0
setA = set(usersI)
setB = set(usersJ)
common = setA.intersection(setB)
if common.__len__() == 0:
ratio= 0.0
else:
bot = math.sqrt(setA.__len__() * setB.__len__())
ratio= float(common.__len__()) / bot
recommDict[i][j] = ratio
recommDict[j][i] = ratio
# 对M中每个用的相似度字典按照相似度倒排序
dict2 = {}
for k,v in recommDict.items():
dict2[k] = sorted(v.items(), key=lambda e: e[1], reverse=True)
#1,物品相似度的未归一化
#return dict2
#2,物品相似度的归一化:Karypis 在研究中发现如果将
def normalItemLike(parmDict):
dict3 = {}
for k,v in parmDict.items():
dict3[k] = []
mx = v[0][1]
for t in v:
dict3[k].append((t[0] , float(t[1]) / mx))
return dict3
return normalItemLike(dict2)
##############第二步: 过滤& 生成推荐列表,偏好值累加求和
def recommItemCF(u,K):
# 准备数据:返回的推荐字典[],用户->商品之间的字典, 商品->用户之间的字典
recommDict = {}
userItemsDict = {}
itemUsersDict = {}
file = open("/home/wang/IdeaProjects/big124/mypython/a")
while True :
line = file.readline()
if line != '':
arr = line.replace("\n","").split("::")
uid = int(arr[0])
iid = str(arr[1])
# userItemDict
if uid in userItemsDict.keys():
userItemsDict[uid].append(iid)
else :
userItemsDict[uid] = [iid]
# itemUsersDict
if iid in itemUsersDict.keys():
itemUsersDict[iid].append(uid)
else:
itemUsersDict[iid] = [uid]
else:
break ;
# 1,寻找每个用户history商品: 其他相似的商品组
dict1 = getMostLikeItemsGroupK(itemUsersDict)
for i in userItemsDict[u]: # 找到每个用户的历史商品
itemsK = dict1[i][:K] #取出k个相似商品
for j in itemsK:
if j[0] not in userItemsDict[u]:
#2, 生成商品推荐列表
if j[0] not in recommDict.keys():
recommDict[j[0]] = 0.0
recommDict[j[0]] = recommDict[j[0]] + j[1]
#3,排序商品推荐列表
return sorted(recommDict.items() , key=lambda e:e[1] ,reverse=True)
###############第三步, 测试结果############################
if __name__ =="__main__":
recommList=recommItemCF(2,3)
for i in recommList:
print i
对比结果:基于商品的协同过滤,物品相似度的归一化后准确率变高
#基于用户的协同过滤:推荐结果
# ('c', 1.533734661597076)
# ('d', 0.8304820237218405)
#基于商品的协同过滤: 物品相似度未归一化,推荐结果
# ('c', 0.9082482904638631)
# ('d', 0.5773502691896258)
#基于商品的协同过滤: 物品相似度的归一化,推荐结果
# ('c', 1.1123724356957945)
# ('d', 0.7071067811865476)