zoukankan      html  css  js  c++  java
  • 基于物品过滤的Slope One 算法

       Slope One 算法是由 Daniel Lemire 教授在 2005 年提出的一个 Item-Based 推荐算法。 他的主要优点是简单,易于扩展。实际上有多个Slope One算法,在此主要学习加权的Slope One算法。它将分为两步,第一步 为计算所有物品间的偏差,第二步利用偏差进行预测。下面分两步介绍该算法,并给出python实现的程序。

    第一步 : 计算偏差

         基于下面用户对乐队的评分例子:

    先计算偏差,物品 i 到物品 j 的平均偏差为: 

    其中card(S)表示S中元素的个数,X是整个评分集合。因此card(Si,j(X))是所有同时对 i 和 j 进行评分的用户集合。从公式容易可以看出: 

    然后是维护问题,考虑如下问题:倘若又有新用户对其中的10个物品进行了评分,我们是否有必要重新计算dev矩阵。显然如果重新计算,性能问题将成为瓶颈,计算量会大的惊人。然而只要我们事先记录了两个物品的偏差同时,还记录下同时对两个物品评分的用户数目即可。这样可以在旧数据基础上更新了,大大减少了运算量,这也是Slope one算法的一个优点,易于维护。

    第二步,利用加权Slope One 算法进行预测

    Slope One的预测公式如下: 

    Pwsl(u,j)指的是利用加权Slope One算法给出用户 u 对物品 j 的评分预测值。S(u)表示所有u评级过的物品的集合。实际上这个加权的权重根据评分用户数得出的。

    基于python的实现:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # __author__ : '小糖果'
    
    import json
    import sys
    from math import sqrt
    from pprint import pprint
    
    
    class Recommender(object):
    	def __init__(self,data):
    		'''
    		frequencies用来记录共同评价i,j物品的用户数目
    		deviations用来记录物品i与j的评分差值
    		'''
    		self.frequencies = {}
    		self.deviations = {}    
    		self.data = data
    
    	def computeDeviations(self):
    		"""
    		计算dev(i,j)以及同时评级i,j物品的用户数,data数据为
    		json格式的字典
    		"""
    		
    		'''遍历每一个人的评分记录'''
    		for ratings in self.data.values():
    			for (item,rating) in ratings.items():
    				self.frequencies.setdefault(item,{})
    				self.deviations.setdefault(item,{})
    				''' item和item2是该用户评分记录中的两个物品'''
    				for (item2,rating2) in ratings.items():
    					if item != item2:
    						self.frequencies[item].setdefault(item2,0)
    						self.deviations[item].setdefault(item2,0.)
    						self.frequencies[item][item2] += 1
    						self.deviations[item][item2] += rating - rating2
    		# 接下来计算dev
    		for (item,ratings) in self.deviations.items():
    			for item2 in ratings:
    				self.deviations[item][item2] /= self.frequencies[item][item2]
    
    	def slopeOneRecommendations(self,username):
    		userRatings = self.data[username]
    		recommendtions = {}
    		frequencies = {}
    		for (userItem,userRating) in userRatings.items():
    			for (diffItem,diffRatings) in self.deviations.items():
    				if diffItem not in userRatings and 
    					userItem in diffRatings:
    					freq = self.frequencies[diffItem][userItem]
    					recommendtions.setdefault(diffItem,0.)
    					frequencies.setdefault(diffItem,0)
    					recommendtions[diffItem] += 
    						(self.deviations[diffItem][userItem] + userRating)*freq
    					frequencies[diffItem] += freq
    		recommendtions = [(item,rating/frequencies[item])
    						  for (item,rating) in recommendtions.items()]
    		recommendtions.sort(key = lambda ele:ele[1],reverse = True)
    		return recommendtions
    
    def test():
    	with open('records.json','r') as f:
    		users = json.load(f)
    	instance = Recommender(users)
    	instance.computeDeviations()
    	print instance.slopeOneRecommendations('Bill')
    
    if __name__ == '__main__':
    	test()
    

      

  • 相关阅读:
    学以致用十九-----shell脚本之引号
    学以致用十八-----shell脚本之基础概念及变量
    学以致用十七-----shell脚本之比较数字和字符串及if else
    学以致用十六-----Centos7.2编译安装mysql5.6.22
    学以致用十五-----前端里注意事项一
    学以致用十四-----打造一个简单的vim IDE
    学以致用十三-----Centos7.2+python3+YouCompleteMe成功历程
    json、javaBean、xml互转的几种工具介绍
    android课程第一节(TextView控件使用)
    Android Please ensure that adb is correctly located at问题解决
  • 原文地址:https://www.cnblogs.com/td15980891505/p/5994556.html
Copyright © 2011-2022 走看看