明天就是中秋节了。这里就不发月饼了,祝大家吃好喝好玩好。
进入正题,看到一个模型叫slope one。然后查看了一些资料。现在总结下,以备后用。
先来说下基本原理:
用户 | 对事物A打分 | 对事物B打分 |
X | 3 | 4 |
Y | 2 | 4 |
Z | 4 | ? |
大家来猜下?处的值是多少?按照http://www.fuchaoqun.com/2008/09/slope_one/这篇博客上说的,slope one跟股票里有点联系,引用下里面所说的“股票上有个说法是平均值可以掩盖一切异常波动,所以股票上的各个技术指标收拾不同时间段的平均值的曲线图或者柱状图等。”Slope one算法也认为:平均值也可以代替某两个未知个体之间的打分差异,事物A对事物B的平均很差是:((3 – 4) + (2 – 4)) / 2 = -1.5,也就是说人们对事物B的打分一般比事物A的打分要高1.5,于是Slope one算法就猜测Z对事物B的打分是4 + 1.5 = 5.5。
加权算法:
有n个人对事物A和事物B打分了,R(A->B)表示这n个人对A和对B打分的平均差(A-B),有m个人对事物B和事物C打分了,R(C->B)表示这m个人对C和对B打分的平均差(C-B),注意都是平均差而不是平方差,现在某个用户对A的打分是ra,对C的打分是rc,那么A对B的打分可能是:rb = (n * (ra – R(A->B)) + m * (rc - R(C->B)))/(m+n)。
算法的优点:
用户推荐越来越热, Google使用MinHash, PLSI, LDA, SVD, SVM等算法,分析用户的喜好, 实现新闻的自动分类;新浪也用Slope One以及一些Item-based的算法对音乐进行推荐; 淘宝定期会启动MapReduce作业分析前一天或者一个月用户收藏的宝贝,给相同喜好的买家提供推荐服务。
本文描述的Slope One算法是一种对评分进行预测的算法, 它相对于SVD, PLSI, LDA这一类model-based算法来说有以下特点:
1. 简单, 容易实现
2. 训练得到的模型可以增量更新
3. 预测速度很快
4. 用户可以只做过一两次评分,就可以获得推荐.
5. 准确度比较理想
代码实现:
备注:代码是http://coderplay.iteye.com/blog/468623上的。
1.# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>. 2.# 3.# This software may be used and distributed according to the terms 4.# of the GNU General Public License, version 2 or later, which is 5.# incorporated herein by reference. 6. 7.class SlopeOne(object): 8. def __init__(self): 9. self.diffs = {} 10. self.freqs = {} 11. 12. def predict(self, userprefs): 13. preds, freqs = {}, {} 14. for item, rating in userprefs.iteritems(): 15. for diffitem, diffratings in self.diffs.iteritems(): 16. try: 17. freq = self.freqs[diffitem][item] 18. except KeyError: 19. continue 20. preds.setdefault(diffitem, 0.0) 21. freqs.setdefault(diffitem, 0) 22. preds[diffitem] += freq * (diffratings[item] + rating) 23. freqs[diffitem] += freq 24. return dict([(item, value / freqs[item]) 25. for item, value in preds.iteritems() 26. if item not in userprefs and freqs[item] > 0]) 27. 28. def update(self, userdata): 29. for ratings in userdata.itervalues(): 30. for item1, rating1 in ratings.iteritems(): 31. self.freqs.setdefault(item1, {}) 32. self.diffs.setdefault(item1, {}) 33. for item2, rating2 in ratings.iteritems(): 34. self.freqs[item1].setdefault(item2, 0) 35. self.diffs[item1].setdefault(item2, 0.0) 36. self.freqs[item1][item2] += 1 37. self.diffs[item1][item2] += rating1 - rating2 38. print self.diffs[item1][item2] 39. for item1, ratings in self.diffs.iteritems(): 40. for item2 in ratings: 41. ratings[item2] /= self.freqs[item1][item2] 42. 43.if __name__ == '__main__': 44. userdata = dict( 45. alice=dict(squid=1.0, 46. cuttlefish=0.5, 47. octopus=0.2), 48. bob=dict(squid=1.0, 49. octopus=0.5, 50. nautilus=0.2), 51. carole=dict(squid=0.2, 52. octopus=1.0, 53. cuttlefish=0.4, 54. nautilus=0.4), 55. dave=dict(cuttlefish=0.9, 56. octopus=0.4, 57. nautilus=0.5), 58. ) 59. s = SlopeOne() 60. s.update(userdata) 61. print s.predict(dict(octopus=0.4)
具体的算法时间复杂度和用法见http://coderplay.iteye.com/blog/468623。
此外,http://www.serpentine.com/blog/2006/12/12/collaborative-filtering-made-easy/上具体说了怎么用python编写slope one程序。