自己动手写一个推荐系统
2015-10-10 10:02
281 查看
以下为转载,原文地址:http://www.cnblogs.com/flclain/archive/2013/03/03/2941397.html
开工:
上面给了一些reading lists,并不是说要读完所有的才能开工,只是说,先看完个目录,哪里不懂查哪里。在下面介绍的做推荐系统的流程中,我只是想给大家介绍个普通的推荐系统该怎么做,所以很多地方都有偷懒,还请大家见谅。而且由于我不是做的在线的推荐系统,而是属于隔天推荐的那种离线的,所以叙述工程的时候就是只叙述离线的推荐。
数据准备:
一般来说,做推荐系统的数据一般分两种,一种从在线的读取,比如用户产生一个行为,推荐系统就反应下(传说豆瓣fm就是这么做的?),还有一种就是从数据库里读。
我个人一般是这样做的:跟做反作弊的人打个招呼,让他们在记用户行为数据的时候顺便存到各个线上服务器上,再写个php脚本,从各个服务器上把我需要的日志抓过来,然后当日要的最新的数据就来了。
但是这种地方其实存储的数据是加了一些判断的,也就是说是分类记录的(因为很多记录是别人刷的,比如丢一个链接到qq群里让别人帮忙投票什么的),这里不细说,到后面fighting spam的地方再讨论。
数据过滤:
当我们得到了每天产生的数据后,说实在这些数据实在是太多了,我们当然用不到这么多,就要写个过滤模块,把一些我们用不到的数据过滤掉。
我一般是这样做的:写个python的脚本,把过滤器放到一个单独的模块,要用的过滤器就到责任链里面注册下。这样别人和自己维护起来也方便点,顺便一说,过滤的东西一般来说有这样几种:一种是一个item只有一个user打过分的,而且以前没有人打分的,这样的数据放到推荐的模型里去跑虽然mahout会自动无视它,但其实按照power law来说是有不少的,内存能省就省吧;还有一种是有些黑名单的,有item和user各自的黑名单,这些也是事先要去掉的。
数据存储:
这个就是大家仁者见仁,智者见智的时候了,因为一般来说,是你选用的算法和算法具体的实现方式以及基础架构决定了你的存储方式,就不多说了。
我一般是这样做的:一般做成增量处理的方式,然后每天一计算,一周一回滚。由于算法实现的特殊性,每40个item user对存储在一起,有点类似于bitmap吧。
推荐系统算法部分:
这部分以前写过类似的小记录和心得笔记之类的东西,就直接贴了_(:з」∠)_
这里的推荐系统的核心算法主要用mahout实现。
各种算法对于推荐都有着自己的特定的假设,对于什么时候什么样的算法会有比较好的performance应该对于假设反复验证。说白了就是做实验。
然后我们一般用什么算法呢,看看mahout给的算法吧,花样繁多,什么item based,user based,slop-one,SVD等等,常用的都有了,那我们要用什么算法呢。
先简单说下user based的算法在mahout中的一些实现:
第一步应该先算出所有人的相似度矩阵W,再去对于item进行遍历,事实上mahout也是这样做的。
相似度矩阵也许可以保留下来,这样可以用来做谱聚类来验证。
UserSimilarity 封装了用户之间的相似性
UserSimilarity similarity = new PearsonCorrelationSimilarity (model);
UserNeighborhood封装了最相似的用户组
UserNeighborhood neighborhood = new NearestNUserNeighborhood (2, similarity, model);
总而言之,用DataModel来生成data model,用UserSimilarity生成User-user之间的相似度矩阵,用户的邻居的定义用UserNeighborhood定义,推荐引擎使用Recommender实现。
对于推荐的评判是使用evaluator来进行评判
double score = evaluator.evaluate(recommenderBuilder, null, model, 0.95, 0.05);
用95%的数据构建模型,用5%的数据进行test
Fixed-size neighborhoods
对于到底用多少人作为用户周围的一圈,我们事实上没有一个确定的值,就像做生物实验一样需要不断在特定的数据集里跑出来。
Threshold-based neighborhood
当然,我们也可以定义个threshold去找出最相似的用户群。
Threshold定义为-1到1(相似度矩阵返回的相似度就是在这个范围)
new ThresholdUserNeighborhood(0.7, similarity, model)
开工:
上面给了一些reading lists,并不是说要读完所有的才能开工,只是说,先看完个目录,哪里不懂查哪里。在下面介绍的做推荐系统的流程中,我只是想给大家介绍个普通的推荐系统该怎么做,所以很多地方都有偷懒,还请大家见谅。而且由于我不是做的在线的推荐系统,而是属于隔天推荐的那种离线的,所以叙述工程的时候就是只叙述离线的推荐。
数据准备:
一般来说,做推荐系统的数据一般分两种,一种从在线的读取,比如用户产生一个行为,推荐系统就反应下(传说豆瓣fm就是这么做的?),还有一种就是从数据库里读。
我个人一般是这样做的:跟做反作弊的人打个招呼,让他们在记用户行为数据的时候顺便存到各个线上服务器上,再写个php脚本,从各个服务器上把我需要的日志抓过来,然后当日要的最新的数据就来了。
但是这种地方其实存储的数据是加了一些判断的,也就是说是分类记录的(因为很多记录是别人刷的,比如丢一个链接到qq群里让别人帮忙投票什么的),这里不细说,到后面fighting spam的地方再讨论。
数据过滤:
当我们得到了每天产生的数据后,说实在这些数据实在是太多了,我们当然用不到这么多,就要写个过滤模块,把一些我们用不到的数据过滤掉。
我一般是这样做的:写个python的脚本,把过滤器放到一个单独的模块,要用的过滤器就到责任链里面注册下。这样别人和自己维护起来也方便点,顺便一说,过滤的东西一般来说有这样几种:一种是一个item只有一个user打过分的,而且以前没有人打分的,这样的数据放到推荐的模型里去跑虽然mahout会自动无视它,但其实按照power law来说是有不少的,内存能省就省吧;还有一种是有些黑名单的,有item和user各自的黑名单,这些也是事先要去掉的。
数据存储:
这个就是大家仁者见仁,智者见智的时候了,因为一般来说,是你选用的算法和算法具体的实现方式以及基础架构决定了你的存储方式,就不多说了。
我一般是这样做的:一般做成增量处理的方式,然后每天一计算,一周一回滚。由于算法实现的特殊性,每40个item user对存储在一起,有点类似于bitmap吧。
推荐系统算法部分:
这部分以前写过类似的小记录和心得笔记之类的东西,就直接贴了_(:з」∠)_
这里的推荐系统的核心算法主要用mahout实现。
各种算法对于推荐都有着自己的特定的假设,对于什么时候什么样的算法会有比较好的performance应该对于假设反复验证。说白了就是做实验。
然后我们一般用什么算法呢,看看mahout给的算法吧,花样繁多,什么item based,user based,slop-one,SVD等等,常用的都有了,那我们要用什么算法呢。
先简单说下user based的算法在mahout中的一些实现:
第一步应该先算出所有人的相似度矩阵W,再去对于item进行遍历,事实上mahout也是这样做的。
相似度矩阵也许可以保留下来,这样可以用来做谱聚类来验证。
UserSimilarity 封装了用户之间的相似性
UserSimilarity similarity = new PearsonCorrelationSimilarity (model);
UserNeighborhood封装了最相似的用户组
UserNeighborhood neighborhood = new NearestNUserNeighborhood (2, similarity, model);
总而言之,用DataModel来生成data model,用UserSimilarity生成User-user之间的相似度矩阵,用户的邻居的定义用UserNeighborhood定义,推荐引擎使用Recommender实现。
对于推荐的评判是使用evaluator来进行评判
double score = evaluator.evaluate(recommenderBuilder, null, model, 0.95, 0.05);
用95%的数据构建模型,用5%的数据进行test
Fixed-size neighborhoods
对于到底用多少人作为用户周围的一圈,我们事实上没有一个确定的值,就像做生物实验一样需要不断在特定的数据集里跑出来。
Threshold-based neighborhood
当然,我们也可以定义个threshold去找出最相似的用户群。
Threshold定义为-1到1(相似度矩阵返回的相似度就是在这个范围)
new ThresholdUserNeighborhood(0.7, similarity, model)
相关文章推荐
- 缓冲字符流 BufferedReader类与BufferedWriter类
- Linux战地日记—压缩解压命令
- Android全局捕获崩溃异常记录日志保存至本地并定时删除
- 数据库中使用正则表达式小结
- QT5设计VTK UI窗口
- Unity3D手机游戏开发-金玺曾读书摘要(2015-4-27 19:01、2016-4-11 10:39)
- Error parsing HTTP request header
- Inverse和cascade是Hibernate映射中最难掌握的两个属性
- Android中RelativeLayout各个属性
- Android新增一个emmc 上层的实现
- uitableview beginupdates 和endupdates 的使用
- avi视频 及其压缩
- Threads And Locks
- ajax异步上传图片三种方案
- C#之结构、枚举和运算符
- 我TMD创业失败了:6个月从豪情壮志到分崩离析
- highcharts画阶梯图线(Step)阶跃信号之类
- iOS帮助地址
- 关于python的字符串逆序输出
- 2015年第三季度总结