基于物品的协同过滤算法和SlopeOne的python实现

本文深入解析了SlopeOne算法的核心概念及其在推荐系统中的应用,通过具体例子展示了如何利用用户对物品的评分差异进行预测,以及如何在数据稀缺的情况下提供相对准确的推荐,有效解决冷启动问题。此外,文章还介绍了加权SlopeOne算法,通过计算物品间的平均差异来优化预测结果。

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

基本概念
       Slope One的基本概念很简单, 例子1, 用户X, Y和A都对Item1打了分. 同时用户X,Y还对Item2打了分, 用户A对Item2可能会打多少分呢?

UserRating to Item 1Rating to Item 2
X53
Y43
A4?


        根据SlopeOne算法, 应该是:4 - ((5-3) + (4-3))/2 = 2.5.
        解释一下. 用户X对Item1的rating是5, 对Item2的rating是3, 那么他可能认为Item2应该比Item1少两分. 同时用户Y认为Item2应该比Item1少1分. 据此我们知道所有对Item1和Item2都打了分的用户认为Item2会比Item1平均少1.5分. 所以我们有理由推荐用户A可能会对Item2打(4-1.5)=2.5分;

        很简单是不是? 找到对Item1和Item2都打过分的用户, 算出rating差的平均值, 这样我们就能推测出对Item1打过分的用户A对Item2的可能Rating, 并据此向A用户推荐新项目.
        这里我们能看出Slope One算法的一个很大的优点, 在只有很少的数据时候也能得到一个相对准确的推荐, 这一点可以解决Cold Start的问题.

利用上面的直观,我们定义item  i  相对于 item  j  的平均偏差:

其中  S j,i () 表示同时对item  i  和  j  给予了评分的用户集合,而  card()  表示集合包含的元素数量。

有了上面的定义后,我们可以使用  获得用户  u  对 item  j  的预测值。当把所有这种可能的预测平均起来,可以得到:

其中  Rj  表示所有用户  u  已经给予评分且满足条件 ( ij  且  S j,i 非空) 的item集合。


 加权SlopeOne 算法:
  1. 例子:
  2.   
  3. 首先计算item1和item2的平均差值,((5-3)+(3-4))/2=0.5,还有item1和item3的平均差值,就是5-2=3,然后推算lucy对item1的评分,根据item1和item2的平均差值来看lucy对item1的评分可能为2+0.5=2.5,同理根据item1和item3的平均差值lucy对item1的评分可能为5+3=8.
  4. 现在如何取舍那?使用加权平均数应该是一种比较好的方法:(因为2.5是根据两个值推算的,8是通过一个只推算的)
  5. slope one 算法差不多真的就是这么简单了!

# -*- coding: utf-8 -*-
"""
Created on Thu Apr 16 15:38:58 2015

@author: admin
"""
import os 
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'  #必须置于cx之前, 解决Oracle导入中文乱码问题
import cx_Oracle as co
import pandas as pd 

class SlopeOne(object):
    def __init__(self):
        self.diffs = {}
        self.freqs = {}
        self.userRatings = {}
                
    def sql2dict(self, data):   
        for line in data:
            user=line[0] 
            item=line[1]
            rating=line[3]
            if user in self.userRatings:
                item_rating=self.userRatings[user]  # 将行字典赋予用户
            else:
                item_rating={}
            item_rating[item]=rating
            self.userRatings[user]=item_rating
        return self.userRatings
        
    def predict(self, userprefs): #recieve the ItemRating from one user,output the recommend ItemRating
        preds, freqs = {}, {}
        for item, rating in userprefs.iteritems():
            for diffitem, diffratings in self.diffs.iteritems():
                try:
                    freq = self.freqs[diffitem][item]
                except KeyError:
                    continue
                preds.setdefault(diffitem, 0.0)
                freqs.setdefault(diffitem, 0)
                preds[diffitem] += freq * (diffratings[item] + rating)
                freqs[diffitem] += freq
        recommend = dict([(item, value / freqs[item])
                     for item, value in preds.iteritems()
                     if item not in userprefs and freqs[item] > 0])
        return recommend
                       
    def update(self, userdata): # calcu the card and diff
        for ratings in userdata.itervalues():
            for item1, rating1 in ratings.iteritems():
                self.freqs.setdefault(item1, {})
                self.diffs.setdefault(item1, {})
                for item2, rating2 in ratings.iteritems():
                    self.freqs[item1].setdefault(item2, 0)
                    self.diffs[item1].setdefault(item2, 0.0)
                    self.freqs[item1][item2] += 1
                    self.diffs[item1][item2] += rating1 - rating2
        for item1, ratings in self.diffs.iteritems():
            for item2 in ratings:
                ratings[item2] /= self.freqs[item1][item2]

if __name__=='__main__':
    dsn=co.makedsn('192.168.113.226','11521','boss')
    db =  co.connect('zsboss','zsboss123',dsn)
    cursor=db.cursor()    
    cursor.execute ("select * from recommendation.live_preference_02  where devno in (select devno from recommendation.user_sample_1000)")  
    data=cursor.fetchall()
    cursor.close()
    db.commit()
    s=SlopeOne()
    userdata=s.sql2dict(data)
    s.update(userdata)
    recommend_all={}
    k=0
    for instance in userdata:
        recommend_all[instance]=s.predict(userdata[instance])
        k+=1
        if k%100==0:
          print k




'''
oppps!! dict type can be used like this 
if __name__ == '__main__':
    userdata = dict(
        alice=dict(squid=1.0,
                   cuttlefish=0.5,
                   octopus=0.2),
        bob=dict(squid=1.0,
                 octopus=0.5,
                 nautilus=0.2),
        carole=dict(squid=0.2,
                    octopus=1.0,
                    cuttlefish=0.4,
                    nautilus=0.4),
        dave=dict(cuttlefish=0.9,
                  octopus=0.4,
                  nautilus=0.5),
        )
    s = SlopeOne()
    s.update(userdata)
    print s.predict(dict(squid=0.4))
  
#for print   
c=0
for i in recommend_all.iteritems():
    c+=1
    if c == 2 : 
        break
    print i 
    
'''


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值