协同过滤算法Python实现源代码

本文介绍了一个基于皮尔森相关系数的商品推荐系统实现过程,详细解释了如何从Excel文件读取商品评分数据,通过计算用户间的相似度来推荐商品,同时展示了如何使用Python进行数据处理和结果输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# -*- coding: utf-8 -*-
"""
Created on Thu Aug 9 10:43:15 2018

@author: 01379668
"""
from math import *
import xlrd
from numpy import *
from xlutils.copy import copy
def addtwodimdict(thedict, key_a, key_b, val):
if key_a in thedict:
thedict[key_a].update({key_b: val})
else:
thedict.update({key_a:{key_b: val}})


data = xlrd.open_workbook('E:/cf.xlsx')
#货架、商品、评分(GMV)
gmvPoint = dict()
table1 = data.sheets()[2]
nrows1 = table1.nrows #行数
ncols1 = table1.ncols #列数
for i in range(nrows1):
addtwodimdict(gmvPoint,table1.row_values(i)[0], table1.row_values(i)[2],table1.row_values(i)[5])
#输出
new_excel=copy(data)
ws=new_excel.get_sheet(3)#第三张sheet

class recommendation:
def __init__(self):
self.critics = gmvPoint
self.ws = ws
self.new_excel=new_excel

def sim_pearson(self,person1, person2):
"""
计算皮尔森相关系数. 度量两个向量之间的线性相关性.
如果一个人总是给出比另一个人更高的分支,但二者的分值只差基本保持一致,则他们仍然存在很好的相关性.
:return:两个向量之间的皮尔森相关系数,返回浮点数
"""
movielist1 = self.critics[person1]
movielist2 = self.critics[person2]
commonlist = []
for item in movielist1:
if item in movielist2:
commonlist.append(item) # key
if len(commonlist) == 0: # 没有共同项
return 0

sum1 = sum([self.critics[person1][item] for item in commonlist]) # person1评分和
sum2 = sum([self.critics[person2][item] for item in commonlist]) # person2评分和

sum1sq = sum([pow(self.critics[person1][item], 2) for item in commonlist]) # person1评分平方和
sum2sq = sum([pow(self.critics[person2][item], 2) for item in commonlist]) # person2评分平方和

psum = sum([self.critics[person1][item] * self.critics[person2][item]
for item in commonlist]) # 交叉项乘积和

# calculate perarson
n = len(commonlist)
num = (psum - (sum1 * sum2 / n))
den = sqrt((sum1sq - pow(sum1, 2) / n) * (sum2sq - pow(sum2, 2) / n))
if den == 0:
return 0
r = num / den
return r
def getRecommendations(self,person,similarity=sim_pearson):
"""
用与person的相似度对其他人对person未看过的影片进行加权平均,对person未看影片进行加权打分
:param person:
:param similarity: 相似度度量方法
:return: 返回对 person 未看影片的推荐评分,按评分排序进行推荐
"""
moviescore_dict = {} # 影片--影片对应的评分和
moviesim_dict = {} # 影片--影片对应的相似度和
for other in self.critics:
sim = similarity(self,other, person) # 人之间的相似度
if other == person:
continue
if sim <= 0:
continue
for item in self.critics[other]:
if item not in self.critics[person]: # 如果person未对该电影进行评价
moviescore_dict.setdefault(item, 0)
moviescore_dict[item] += self.critics[other][item] * sim
moviesim_dict.setdefault(item, 0)
moviesim_dict[item] += sim
result = [(float(moviescore_dict[item]/moviesim_dict[item]),item) for item in moviescore_dict]
result = sorted(result, key=lambda e1: -e1[0])
return result
def result_output(self):
'''
调用函数并输出结果
'''
#商品字典
table2 = data.sheets()[1]
product = dict()
nrows2 = table2.nrows #行数
ncols2 =table2.ncols #列数
for i in range(nrows2):
product.update({table2.row_values(i)[0]: table2.row_values(i)[1]})
#货架字典
table3 = data.sheets()[0]
shelf = dict()
nrows3 = table3.nrows #行数
ncols3 = table3.ncols #列数
for i in range(nrows3):
shelf.update({table3.row_values(i)[0]: table3.row_values(i)[1]})
#要推荐的货架(列表)
table4 = data.sheets()[3]
ls=list()
nrows4 = table4.nrows #行数
ncols4 = table4.ncols #列数
for i in range(nrows4):
ls.append(table4.row_values(i)[0])
#遍历每一个需求货架,推荐商品,并输出预计GMV占比
#打开excel,修改excel
for i in range(nrows4):
a=ls[i]#要推荐的货架ID
result=self.getRecommendations(a)[0:5]
no_reconmmendations=self.getRecommendations(a)[-5:]#不推荐
#将这五个推荐商品、预计GMV占比、最低GMV占比写到单元格
for j in range(5):
self.ws.write(i,2+j,\
'推荐商品ID为:'+str(int(result[j][1]))+ \
',商品名称:'+product[result[j][1]]+ \
',该商品预计GMV占比'+str('%.2f%%' % (result[j][0] * 100)))
self.ws.write(i,7,'以下五款商品不推荐上架:'+\
'【1】商品ID:'+str(int(no_reconmmendations[0][1]))+'商品名称:'+product[no_reconmmendations[0][1]]+ \
',【2】商品ID:'+str(int(no_reconmmendations[1][1]))+'商品名称:'+product[no_reconmmendations[1][1]]+ \
',【3】商品ID:'+str(int(no_reconmmendations[2][1]))+'商品名称:'+product[no_reconmmendations[2][1]]+ \
',【4】商品ID:'+str(int(no_reconmmendations[3][1]))+'商品名称:'+product[no_reconmmendations[3][1]]+ \
',【5】商品ID:'+str(int(no_reconmmendations[4][1]))+'商品名称:'+product[no_reconmmendations[4][1]])
#保存excel
new_excel.save('E:/推荐结果.xls')
if __name__ == '__main__':
system = recommendation()
system.result_output()
'''
# 1.欧几里得距离计算相似度
print ("\n欧几里得相似度:", system.sim_distance('货架ID1', '货架ID2'))

# 2.皮尔森相关系数计算
print ("\n皮尔森相关系数:", system.sim_pearson('货架ID1', '货架ID2'))

'''

转载于:https://www.cnblogs.com/wenj17/p/9737129.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值