吉吉于

【RecSys】Slope One算法

Slope One 算法是由 Daniel Lemire 教授在 2005 年提出的一个 Item-Based 推荐算法。

Slope One 算法试图同时满足这样的的 5 个目标:

易于实现和维护:普通工程师可以轻松解释所有的聚合数据,并且算法易于实现和测试。

运行时可更新的:新增一个评分项,应该对预测结果即时产生影响。

高效率的查询响应:快速的执行查询,可能需要付出更多的空间占用作为代价。

对初次访问者要求少:对于一个评分项目很少的用户,也应该可以获得有效的推荐。

合理的准确性:与最准确的方法相比,此方法应该是有竞争力的,准确性方面的微小增长不能以简单性和扩展性的大量牺牲为代价。

举例:

User A 给 Item I 打分为 1;给 Item J 打分为 1.5。

Uesr B 给 Item I 打分为 2。

问题是:User B 给 Item J 打分为多少?

使用 Slope One 算法,答案是:2.5,2+(1.5-1)=2.5。

python实现的简易slopeone算法:

class SlopeOne(object):
    def __init__(self):
        self.diffs = {}
        self.freqs = {}
 
    def predict(self, userprefs):
        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
        return dict([(item, value / freqs[item])
                     for item, value in preds.iteritems()
                     if item not in userprefs and freqs[item] > 0])
 
    def update(self, userdata):
        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__':
    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))

转载请注明:于哲的博客 » 【RecSys】Slope One算法