Slope one:简单高效的推荐算法

Wednesday, September 3rd, 2008

本博客所有原创文章采用知识共享署名-非商业性使用-相同方式共享,转载请保留链接http://chaoqun.17348.com/2008/09/slope_one/ 推荐系统最早在亚马逊的网站上应用,根据以往用户的购买行为,推荐出购买某种产品同时可能购买的其他产品,国内做的不错的当当网,有时候买书,它总能给我推荐出我感兴趣的其他书来,也算是技术极大的促进了销售。 一般的协同过滤算法,首先是收集用户对事物(产品)的评分情况,一种直接对某本书,或者某个歌曲打分,另种是隐性的打分,比如商务系统中,购买了表示打2分,浏览了打1分,其他的0分。我比较看好隐性打分,因为直接打分需要用户的参与程度比较高,很多网站都在内容页中留一个打分的按钮,从1~5选一个,我可能喜欢这篇文章,可我哪里知道我喜欢的程度是几分啊,还要我去思考,而网站设计中一条很重要的原则是:Do not let me think!,于是我就胡打一个分数或者不打,而隐性的打分则不同,只有你喜欢的图书你才会购买,只有你喜欢的歌曲才会听多次。 收集好用户的打分之后,通过最近邻搜索到和某个事物或者某个人特征或者兴趣相近的其他事物或者人,最近邻搜索算法一般是皮尔森相关系数(Person Correlation Coefficient)、余弦相似性(Cosine-based Similarity)以及调整余弦相似性(Adjusted Cosine Similarity)。关于余弦定理在数据挖掘中的应用,google黑白报有过介绍,可以参考数学之美 系列 12 - 余弦定理和新闻的分类。 剩下的工作就是根据最近邻集进行推荐了。 最近邻集的运算相对来说成本比较高,尤其是大量数据的时候,今天和大家分享的是一种简单高效的协同过滤算法:Slope one 基本原理 用户          对事物A打分 对事物B打分 X 3 4 Y 2 4 Z 4 ? 用户Z对事物B的打分可能是多少呢?股票上有个说法是平均值可以掩盖一切异常波动,所以股票上的各个技术指标收拾不同时间段的平均值的曲线图或者柱状图等。同样的,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) 开源的Slope one的程序包 Python http://www.serpentine.com/blog/2006/12/12/collaborative-filtering-made-easy/ Java http://taste.sourceforge.net/ http://www.daniel-lemire.com/fr/documents/publications/SlopeOne.java http://www.nongnu.org/cofi/ PHP http://sourceforge.net/projects/vogoo http://www.drupal.org/project/cre http://www.daniel-lemire.com/fr/documents/publications/webpaper.txt Slope one算法作者写的,简单明了,强烈推荐。 Erlang http://chlorophil.blogspot.com/2007/06/collaborative-filtering-weighted-slope.html C# http://www.cnblogs.com/kuber/articles/SlopeOne_CSharp.html 国人写的C#版本 T-SQL http://blog.charliezhu.com/2008/07/21/implementing-slope-one-in-t-sql/ 还有一些其他语言的版本,请参考http://en.wikipedia.org/wiki/Slope_One,即将面世的,居于PHP & Mysql的Slope one算法实现将会在http://code.google.com/p/openslopeone/开源出来,主要优化的是海量数据以及分布式处理,目前在我的笔记本上(迅驰+1.5G内存),对440W打分记录进行测试,单一线程,3小时47分处理完。速度还算是不错了,最近工作实在太忙了,等我整理好会开源出来放在上面的地址。过几天会有一篇我的算法的详细介绍,盼诸位批评指正,共同学习,共同进步。

利用orange进行关联规则挖掘

Tuesday, August 26th, 2008

本博客所有原创文章采用知识共享署名-非商业性使用-相同方式共享,转载请保留链接http://chaoqun.17348.com/2008/08/data-mining-with-python-orange-association_rule/ 最近,趁着项目的间隙,折腾了一阵数据挖掘,在同事的帮助下,对新浪音乐用户的听歌记录进行了一个简易挖掘,希望能根据用户以往的听歌记录,推荐出用户可能感兴趣的其他歌曲。 Orange: 一个模块化的C++数据挖掘包,提供python接口(好像也只提供了python接口),网址是http://www.ailab.si/orange/ 关联分析: 我这里用的是类似购物篮分析,每个用户的听歌id是一个事务,不熟悉关联分析的同学可以去搜一些相关方面的资料。 数据准备: 简单清洗掉一些“脏”数据(逻辑上有问题的数据,比如某个用户在5s听了200首歌),得到类似下面的数据 15615,355029,750367,762147,803787,805014,999712,999712,999712,1013641,1024215,1028429 871029,952779,962769 1023040,1024077,1024215,1025600 757946,873801,873801,873801 862257,873479 286056,286056,286056,286056,286056,286056,286056,286056,286056,286056 873801,873801,873801,873801,873801,947750,947750 473221,473537,504206,504206,504206,504206,504206,504206 947750,1005430,1005430 974748,1024215 873479,873479,873801,873801,947750,965748,999721,1024215,1024215,1024215,1024215,1024215 873801,873801,873801 每一行是一个用户的听歌记录,没有做去重处理(orange示例中也没有,是不是可能会增加歌曲的权重?不清楚,没有去阅读orange代码),注意文件名一定要以.basket为扩展名,程序中文件地址是d:/datamining/sample.basket。 程序: # 导入orange包 import orange # 导入数据,注意不需要后缀 data = orange.ExampleTable("d:/datamining/sample") # 挖掘关联规则,输入最低支持度、最低置信度、最大项集数 rules = orange.AssociationRulesSparseInducer(data, support = 0.5, confidence = 0.6, maxItemSets = 1000000) # 打印出规则来 for r in rules: print "%5.3f %5.3f %s" % (r.support, r.confidence, r) 是不是非常的简单?Orange实现的是Apriori算法,由于Apriori算法的问题,一旦数据量非常大,你就等着你的内存消耗光吧,反正我这边要是把所有数据都导入进去的话,笔记本1.5G的的内存根本不够用,可以试试FP-tree算法,我这边参考文章利用sql改良构建fp-tree之技术,已经把fp-tree的前缀路径都找出来了,需要的朋友可以私下找我要,由fp前缀路径挖频繁集需要用到递归,用sql去处理就非常费劲了,所以后面的算法还需要自己去探索。 居于关联规则的挖掘就告一段落,因为算法的计算复杂度非常高,效果倒不是太好(因为对于音乐,用户可能听多遍,这样打分就不一样,可能用关联规则去挖电影类的数据比较好,因为电影一般最多就看一遍),现在研究的是协同过滤,如果不出意外的话,一个改良版的PHP+Mysql实现slope one算法过几天就要出来了,到时候我会开源出来的。