基于物品协同过滤实现商品推荐系统
Posted leimu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于物品协同过滤实现商品推荐系统相关的知识,希望对你有一定的参考价值。
一、背景
某电商平台,有一批用户浏览、收藏、购买物品的日志数据。实现用户进入APP之后第一页显示商品的个性化推荐。ps:当前阶段,显示数据为随机选取。
二、思考
1、因为是某一品类的特殊电商平台,卖的商品几百种,但是用户几十万。这种情况,考虑使用ItemCF,至于为什么不是UserCF:物品相似度矩阵为 500*500,用户相似度矩阵为 500000*500000。但是也有一个问题,使用物品相似度矩阵会不会使信息丢失更多。
2、类似电影评分数据集,用户-电影-评分数据,要把原始数据转换为用户-物品-评分格式。
浏览:1,收藏:3,购买:5 # 每种行为对应的得分
三、代码实现
1、从mysql数据库读取数据,并转换为 用户-商品-评分 字典
class DataPro:
def __init__(self):
self.train = dict()
logs = mysql.fetchall(select_sql)
for temp in logs: # mysql查询得到的用户日志
user = temp[‘user_id‘]
item = temp[‘product_id‘]
type = temp[‘type‘]
#print(user,item)
score = int(type_score_dict[type])
if user not in self.train.keys():
self.train.setdefault(user, {})
if item not in self.train[user].keys():
self.train[user].setdefault(item,0)
if score > self.train[user][item]:
self.train[user][item] = score
2、可以将结果序列化,保存到本地,在实验过程就不需要查询数据库
# 保存到本地
output = open(‘../model/data.pkl‘, ‘wb‘)
pickle.dump(self.train, output)
output.close()
# 读取文件
pkl_file = open(‘../model/data.pkl‘, ‘rb‘)
self.data = pickle.load(pkl_file)
3、计算物品-物品相似度矩阵
显示评分和隐式评分的数据,其相似度矩阵的计算公式有所不同
隐式评分:
(N(i))和(N(j))分别表示喜欢物品(i)和物品(j)的人数。
显式评分
其中(r_{ui})和(r_{uj})分别表示用户 (u) 对物品 (i)和 (j) 的评分,(U_{ij})代表同时喜欢物品 (i)和 (j) 的用户集合。
3.1 基于隐式评分
def ItemSimilarity(self):
# 一个字典,记录 rui*ruj
# 一个字典 记录 rui^2
# 建立物品-物品的共现矩阵
item2item = dict() # 物品-物品的共现矩阵。分子
buy = dict() # 物品被多少个不同用户进行过评分。分母
for user, items in self.data.items():
for i in items.keys():
buy.setdefault(i, 0)
buy[i] += 1
item2item.setdefault(i, {})
for j in items.keys():
if i == j: continue
item2item[i].setdefault(j, 0)
item2item[i][j] += 1
# 计算相似度矩阵
self.similar_matrix = dict()
for i, related_items in item2item.items():
self.similar_matrix.setdefault(i, {})
for j, cij in related_items.items():
self.similar_matrix[i][j] = cij / (math.sqrt(buy[i]) * math.sqrt(buy[j]))
return self.similar_matrix
3.2 基于显式评分
def ItemSimilarity(self):
# 一个字典,记录 rui*ruj
# 一个字典 记录 rui^2
# 建立物品-物品的共现矩阵
item2item = dict() # 物品-物品的共现矩阵。记录rui*ruj,分子
buy = dict() # 物品被多少个不同用户进行过评分。记录rui*rui分母
for user, items in self.data.items():
for i in items.keys():
buy.setdefault(i, 0)
temp = items[i]*items[i]
buy[i] += temp
item2item.setdefault(i, {})
for j in items.keys():
if i == j: continue
item2item[i].setdefault(j, 0)
item2item[i][j] += items[i]*items[j]
# 计算相似度矩阵
self.similar_matrix = dict()
for i, related_items in item2item.items():
self.similar_matrix.setdefault(i, {})
for j, cij in related_items.items():
self.similar_matrix[i][j] = cij / (math.sqrt(buy[i]) * math.sqrt(buy[j]))
return self.similar_matrix
4、相似度矩阵计算完成之后,根据用户id进行商品推荐。需要的参数:K:某个物品其相似物品的个数。N:给用户推荐N个商品。
def get_recommend(self,user_id):
K = 20 # 和某物品相似的k个物品
N = 10 # 推荐最相似的10个物品
rank = {}
watched_items = self.data[user_id]
for item,rating in watched_items.items():
for related_item,w in sorted(self.similar_matrix[item].items(),key=itemgetter(1),reverse=True)[:K]:
rank.setdefault(related_item,0)
rank[related_item] += w*float(rating)
return sorted(rank.items(),key=itemgetter(1),reverse=True)[:N]
四、后续思考
1、用户多次浏览同一个商品,其权重如何在代码中体现
2、基于当前数据的ItemCF完成之后,之后对每天活跃的用户进行推荐结果更新。此时,要实现相似度矩阵的增量更新。
以上是关于基于物品协同过滤实现商品推荐系统的主要内容,如果未能解决你的问题,请参考以下文章