@hanxiaoyang
2017-12-14T12:49:16.000000Z
字数 4967
阅读 2716
个人博客
原文地址:yelper recommendation system
原文翻译与校对:@酒酒 && @寒小阳
时间:2016年10月。
出处:http://blog.csdn.net/han_xiaoyang/article/details/52778321
声明:版权所有,转载请联系作者并注明出
“推荐”可是个当红话题。Netflix愿意用百万美金召求最佳的电影推荐算法,Facebook也为了登陆时的推荐服务开发了上百个项目,遑论现在市场上各式各样的应用都需要个性化服务。
“从互联网中提取信息犹如用消防栓饮水”(Mitchell Kapor)。如今的信息量早已过载,要依据如此嘈杂的信息做出正确决定显然是艰难的。这也是为什么推荐系统日渐流行,尤其在像Netflix, Amazon, Echo,和Facebook这类需要个性化服务的产品。 在大数据时代,实时推荐可能是新的趋势,因为:
根据2016年的"Yelp Challenge"数据来看,“Yelper”能够做到:
Yelper实现的背后展示了一个事实:
知道机器学习背后的工作原理已经不能满足现在的需求了,数据科学家们需要对即将到来的新挑战做好准备:在大数据时代对大规模的流数据的挖掘分析。
Yelper的GitHub主页:https://github.com/sundeepblue/yelper_recommendation_system
Yelper主要由5部分构成,如下图所示。这张图展示了Yepler从接受请求到处理的大致流程。
Yelper的数据主要基于Yelp Challenge 2016 Dataset, 其中包括了:
Yelper系统主要依赖于687K用户和86K商户的数据。而对它们的预处理主要包括两步(Python 代码):
在Yelper系统中,M为百万单位,所有的商业ID在[0,1M]范围中,而由于顾客数量远多于这个数,顾客ID在[10M,+∞]范围内。这样的话以10M为单位我们可以将顾客信息和商业信息联系起来。总的来说,将字符串换为整数索引有这些好处:
而将商业数据以城市划分也大有好处:
我们希望做出高相关的推荐,而现有的推荐系统主要使用2种算法:
这两种方法各具优劣,我们先简明扼要地说一下第一种算法。如果有时间的话,将第二种算法整合进系统也不难。
我们用Spark MLlib来训练ALS-based协同过滤模型(Python 代码戳这里)。以下是大致的步骤:
最后一步输出,最好将模型固化到硬盘或云盘里,这样便于后来的压缩、传输和缓存。
Yelper尤其对于分析用户-商业服务的相互作用,从而对城市得以有更深的思考感兴趣。为什么?因为我们认为:
如下是建立城市为单位的用户-商业服务关系网络步骤:
下图是Madison(US)城市的示例。图中每个节点代表用户(绿色)或商业服务(蓝色)。如果一个用户对一个服务进行过评分,就会对应生成一条从用户(u)出发到商业服务(b)的边(edge)连接这两个节点,即边u-->b。Madison有超过10K条边,遗憾的是D3.js处理不了这么大的图,所以我们随机选取了一小部分在Chrome里展示。
从这个关系网络里我们能发现什么?至少我们可以得到用户和商业服务的拓扑关系。图中边(红色)的密度从某种意义上反映了一个城市里用户对其所有的商业服务的评级。如果每个城市都能生成一个这样的关系网络,我们会发现每个城市的图都是不同的。这样单从这个关系图里就能进一步提取城市更深的信息,例如图形的in/out degree,聚合程度,page rank分析,min cut,社区发现等。
Yelper有一个服务器让用户可以收到推荐。这个服务器需要用到:
Yelper的前端具有以下特点:
下图是用户与Yelper的互动展示。ID为“10081786”的用户提出了Charlotte城市里关键字为“restaurants”,“book store”,"library"和“ice cream”的推荐请求,Yelper返回了“topK”条推荐结果,并且用谷歌地图API展示了地点信息。
假设有成千甚至成百万的用户想要得到不同城市的推荐,处理这么多请求是很具挑战性的,因为:
这也只是冰山一角,实际需要处理的问题更多,所以我们需要一个强大的推荐架构。这篇文章就不再做更细的讨论,一个简单的办法是把这些来源不同的请求看作一个不间断的信息流(non-stopping stream),用Apache Kafka将这些请求转到Kafka上,然后用Spark Streaming以fault-tolerant和scalable方式进行流处理。这样做的好处有:
下图展示了我们模拟的实时大量推荐请求处理(Python 代码戳这里)。terminal左边的窗口是用Spark Streaming以频率为1.5秒处理的用户请求。注意信息以时间戳的形式显示,例如“Time: 2016-09-25 14:37:22.500000”。每个推荐结果前都有Yelper的logo。
在terminal的右边,我们用python script生成随机时间间隔的用户请求。这些请求被piped到Apache Kafka上,这样Spark Streaming就能处理这些请求了。
建立静态用户-商业服务关系网络可以用Python里的graph-tool包(Python 代码戳这里)(网络示例图片)。我们现在来看一看这个关系网络到底什么样子。像之前描述的,如果一个用户对一个服务做了评级,关系图里就会有一条边连接着用户和商业服务两个节点。
但是可视化这些连接并不容易。按理说图中的节点和边越多这个图就更准确。可是从可视化的角度说,这么多边和节点看起来犹如一团乱麻。所以我们用了两个简单的小技巧:在一个城市的所有边中,我们要么随机选择1%(或2%)的边,要么只选择前1%(或2%)的边。
尽管我们只用了2%,也能从这2%数据生成的网络图中挖掘到大量信息。下面来看看3个美国城市的图:Charlotte, Las Vegas, 和Pittsburgh。
我们随机选了1%的边,共3312条。大概是如下的样式:
同样随机选择了1%的边,共11547条。大概是如下的样式:
如果我们随机抽取%2(23095条)的边呢?就变成下面这个样子了:
如果选择前23095条边的话,图会是这个样子:
对匹兹堡随机抽取2%的边(2230条)。
类似分析动态网络图,利用图计算模型和分析我们也能从静态图中得到很多有用的信息。比如说,众所周知,拉斯维加斯的经济要好于匹兹堡。从图上看,拉斯维加斯的图也是明显地有更多节点,进来每个节点的边也更多。
以下是一些可以更多思考的方向: