题目👇
根据顾客对菜品的打分,实现菜品推荐系统
思路分析👇
推荐系统主要有两种思路,一种是用户-产品协同过滤,也就是要找到与目标用户最相似的人,他喜欢什么,目标用户大概率喜欢什么,另一种思路是产品-产品协同过滤,意思是要根据其他用户的选择推断出产品之间的相关联属性,进而推断出目标用户还可能喜欢什么。
两种不同的思路各有利弊,本文选择了前者的用户-产品协同过滤思路,核心是找到与目标用户最相似的人。
在整个数据集中构建一个顾客-菜品的二维矩阵,行代表不同的顾客,列代表不同的菜品,第0行对应着user,顾客可以给1分-100分,0就代表没有品尝过。
另外,我们还需要几点注意的地方:
①对菜品的喜爱度具有时效性。例如,用户如果第二次打分和第一次不一样,要以第二次为准。
②为了防止数据丢失,每处用户交互都需要异常处理来维护。因为Python程序一旦退出所有数据都没了。
代码示例👇
#coding:utf-8
#author:Mitchell
#date:12.9
#根据顾客对菜品的打分,实现菜品推荐系统
import numpy as np
import random
while(1):
try:
print('欢迎来到菜品推荐系统!')
users=int(input("请输入顾客数量:"))
meals=int(input("请输入菜品数量:"))
except:
print("请输入一个数字!")
else:
if users>1 and meals>1 :
DataSet=np.zeros((users,meals))
while(1):
try:
module=int(input("请选择系统模式(1->训练/2->测试/3->查库/4->删库):"))
except:
print("请输入一个数字!")
else:
if module==1:
while(1):
try:
isRandom=int(input("请输入训练模式(1->随机/2->手动/3->返回):"))
except:
print("请输入一个数字!")
else:
if isRandom==1:#随机训练
try:
p=int(input("请输入随机训练次数:"))
except:
print("请输入一个数字!")
else:
if p>0:
for i in range(p):
ClientTarget=random.randint(1,users-1)#随机确定训练目标,除了user外的所有人
MealTarget=random.randint(0,meals-1)#随机确定品尝的菜品
RandomScore=random.randint(1,100)#打分
DataSet[ClientTarget][MealTarget]=RandomScore
print('随机训练结束!')
break
else:
print('p需要大于0!')
elif isRandom==2:#手动训练
try:
p=int(input("请输入手动训练次数:"))
except:
print("请输入一个数字!")
else:
if p>0:
for i in range(p):
try:
ClientTarget=int(input("请输入训练目标号码:"))#确定训练目标,除了user外的所有人
MealTarget=int(input("请输入品尝的菜品号码:"))#确定品尝的菜品
Score=int(input("请输入分数:"))#打分
except:
print("请输入一个数字!")
else:
if not 0<=ClientTarget<users:
print('训练目标号码超出范围!')
i+=1
continue
if not 0<=MealTarget<meals:
print('菜品号码超出范围!')
i+=1
continue
if not 0<Score<=100:
print('分数超出范围!')
i+=1
continue
DataSet[ClientTarget][MealTarget]=RandomScore
print('手动训练结束!')
break
else:
print('p需要大于0!')
elif isRandom==3:
break
elif module==2:
#如果目前最高分仍为0,也就是第一次点菜,随机推荐一个新的菜品即可
if np.amax(DataSet[0])==0:
MealTarget=random.randint(0,meals-1)#随机确定品尝的菜品
print('为您推荐第',MealTarget,'道菜!')
while(1):
try:
Score=int(input('请为这道菜打分(1-100):'))
except:
print("请输入一个数字!")
else:
if 0<Score<=100:
DataSet[0][MealTarget]=Score
break
else:
print('打分不符合规范!')
else:
#找到一个最相似的用户
MostLike=0
Smallest=np.Infinity
for i in range(1,users):
k=0#记录二者同时品尝过的菜数
LikeIndex=0#记录二者相似度=平均偏差平方和
for j in range(meals):
#前提是两个人都品尝过这道菜,且打分近似
if DataSet[0][j]!=0 and DataSet[i][j]!=0:
k+=1
LikeIndex+=(DataSet[0][j]-DataSet[i][j])**2
if LikeIndex!=0 and LikeIndex/k<Smallest:
Smallest=LikeIndex/k
MostLike=i
#找到最相似用户最喜欢的菜品
for i in range(meals):
if DataSet[MostLike][i]==np.amax(DataSet[MostLike]):
suggest=i
print('为您推荐第',suggest,'道菜!')
while(1):
try:
Score=int(input('请为这道菜打分(1-100):'))
except:
print("请输入一个数字!")
else:
if 0<Score<=100:
DataSet[0][MealTarget]=Score
break
else:
print('打分不符合规范!')
elif module==3:
print('目前的数据集为:\n',DataSet)
pass
elif module==4:
break
else:
print('请输入1或2或3或4!')
else:
print('顾客数量和菜品数量都需要大于1!')
运行效果👇