"""
#slope one算法是基于 ”同物品“ 之间的 ”评分差“ 的线性算法,预测用户对物品评分的个性化算法
#适用商品的更新不频繁,数量相对稳定且物品数明显小于用户数的场景,依赖用户的行为日志和物品偏好的相关内容
#优点:1算法简单,2可以发现用户潜在的兴趣爱好
#缺点:依赖用户行为,存在冷启动问题和稀疏性问题
"""
#计算物品之间评分差的平均值,输入如下
#items 物品-用户评分数据items
#users 用户-物品评分数据users
#averages 存放平均分字典类型数据
def buildAverageDiffs(items, users, averages):
#遍历每条物品-用户评分数据
for itemId in items:
#遍历每条其他物品-用户评分数据
for otherItemId in items:
#物品间的评分偏差
average = 0.0
#两件物品均评过分的用户数
userRatingPairCount = 0
#若为不同的物品项
if itemId != otherItemId:
#遍历每条用户-物品评分数据
for userId in users:
#每条数据为用户对物品的评分
userRatings = users[userId]
#当前物品项在用户的评分数据中,且用户也对其他物品有评分
if itemId in userRatings and otherItemId in userRatings:
#两件物品均评过分的用户数加1
userRatingPairCount += 1
#评分偏差为每项当前物品评分-其他物品评分求和
average += (userRatings[otherItemId] - userRatings[itemId])
#物品间的评分偏差等于评分偏差和/两件物品均评过分的用户数
averages[(itemId,otherItemId)] = average / userRatingPairCount
#推荐评分,输入如下
#users 用户-物品评分数据users
#items 物品-用户评分数据items
#averages 物品间的评分偏差
#targetUserId 推荐用户targetUserId
#targetItemId 推荐物品targetItemId
#return 预测评分
def suggestedRating(users, items, averages, targetUserId, targetItemId):
#预测评分分母
runningRatingCount = 0
#预测评分分子
weightedRatingTotal = 0.0
#遍历需要推荐的用户targetUserId对有过评分的物品
for i in users[targetUserId]:
#保存当前物品与要推荐物品targetItemId,共同评分用户数
ratingCount = usersWhoRatedBoth(users, i, targetItemId)
#分子
weightedRatingTotal += (users[targetUserId][i] - averages[(targetItemId, i)]) * ratingCount
#分母
runningRatingCount += ratingCount
#返回预测评分
return weightedRatingTotal / runningRatingCount
#物品itemId1与itemId2共同有多少用户评分
def usersWhoRatedBoth(users, itemId1, itemId2):
count = 0
#用户-物品评分数据users
for userId in users:
#用户对物品itemId1与itemId2都有过评分则计数值加1
if itemId1 in users[userId] and itemId2 in users[userId]:
#加1
count += 1
#返回itemId1与itemId2共同评分用户数
return count
if __name__ == '__main__':
items = {'A': {1:5, 2:3},
'B': {1:3, 2:4, 3:2},
'C': {1:2, 3:5}}
users = {1: {'A':5, 'B':3, 'C':2},
2: {'A':3, 'B':4},
3: {'B':2, 'C':5}}
#物品间评分偏差初始化
averages = {}
#计算物品之间评分差的平均值
buildAverageDiffs(items, users, averages)
print averages
#输出:总共的物品项、用户数
print({'ItemCount': len(items), 'UserCount': len(users)} )
print("Guess that user A will rate item 3= " + str(suggestedRating(users,items, averages, 3, 'A')))