1. 我们为什么需要推荐系统?“推荐”可是个当红话题。Netflix愿意用百万美金召求最佳的电影推荐算法,Facebook也为了登陆时的推荐服务开发了上百个项目,遑论现在市场上各式各样的应用都需要个性化服务。“从互联网中提取信息犹如用消防栓饮水”(Mitchell Kapor)。如今的信息量早已过载,要依据如此嘈杂的信息做出正确决定显然是艰难的。这也是为什么推荐系统日渐流行,尤其在像Netflix, Amazon, Echo,和Facebook这类需要个性化服务的产品。 在大数据时代,实时推荐可能是新的趋势,因为:
实时推荐使得用户和服务商都能得到及时的信息反馈
这将大大加速产品和公司的升级
这也使得实时分析成为可能
2. “Yelper”是什么?根据2016年的”Yelp Challenge”数据来看,“Yelper”能够做到:
按照城市划分商业数据来进行更周到的推荐服务
用Spark的MLlib实现协同过滤
用D3和其他图像工具实现以用户为主导的可视化商业分析
用Scala中Spark GraphX做用户-商业关系图分析
用Spark Streaming和Apache Kafka模拟实时的用户请求处理
给用户推荐高评服务时的谷歌地图展示
Yelper实现的背后展示了一个事实: 
知道机器学习背后的工作原理已经不能满足现在的需求了,数据科学家们需要对即将到来的新挑战做好准备:在大数据时代对大规模的流数据的挖掘分析。Yelper的GitHub主页:https://github.com/sundeepblue/yelper_recommendation_systemPPT展示3. 搭建Yelper的主要模块Yelper主要由5部分构成,如下图所示。这张图展示了Yepler从接受请求到处理的大致流程。

3.1 数据预处理Yelper的数据主要基于Yelp Challenge 2016 Dataset, 其中包括了:
2.7M的评论和来自687K个用户关于86K商户的649K条建议
566K个商业服务特征,例如营业时间,停车信息,周边环境等
共包括有4.2M种关系(edge)的关于687K用户的社交网络。
对86K商户信息的不断汇总更新
和公司及其服务相关的200,000张图片
Yelper系统主要依赖于687K用户和86K商户的数据。而对它们的预处理主要包括两步(Python 代码):
将顾客和商业服务的ASCII编码字符串格式的ID信息转为整数索引
把商业服务的数据按9个城市划分(按城市划分数据结构示例):us-charlotte,www.yghrcp88.cn  us-lasvegas, us-madison, us-phoenix, us-pittsburgh, us-urbana-champaign, canada-montreal, germany-karlsruhe, uk-edinburgh
在Yelper系统中,M为百万单位,所有的商业ID在[0,1M]范围中,而由于顾客数量远多于这个数,顾客ID在[10M,+∞]范围内。这样的话以10M为单位我们可以将顾客信息和商业信息联系起来。总的来说,将字符串换为整数索引有这些好处:
便于使用Spark GraphX,因为它要求所有的节点和边都具有整数ID
用D3 Javascript可视化时能更方便地编写和查错
在以CSV或者JSON文件导出时文件大小会大大减小,使得加载和操作都更快捷
可以根据数字大小范围就能确认是顾客ID还是商业ID
而将商业数据以城市划分也大有好处:
可以根据城市特色建立不同的推荐模型
划分后,每个城市的数据量都比原数据小了很多,可以更快地进行模型训练
按城市来调整模型和参数更加灵活
可以根据现有城市模型向新城市推广,毕竟这个世界上有成千上万的城市
而就像每个人都是不同的,每个城市也都各具特色,用一个模型概括所有城市显然是不科学的
3.2低秩矩阵分解 (Low-Rank matrix factorization)我们希望做出高相关的推荐,而现有的推荐系统主要使用2种算法:
以协同过滤为基础的关联推荐算法,例如low-rank matrix factorization,SVD等
以内容为基础的推荐(content-based recommendation)
这两种方法各具优劣,我们先简明扼要地说一下第一种算法。如果有时间的话,将第二种算法整合进系统也不难。我们用Spark MLlib来训练ALS-based协同过滤模型(Python 代码戳这里)。以下是大致的步骤:
用Spark加载数据文件F,F记录了不同城市的用户-商业服务-星级评分的元祖数据。(Las Vegas的样本元祖数据)
将F里的数据分为三组:60%为训练集,20%为测试集,20%为验证集。
设置矩阵的秩作为备选参数值(rank values),比如4,8,12,用交叉验证方法调参找出最佳的参数,调参标准是最小化RMSE(Residual Mean Squared Error)值
用选取的参数建模
将模型输出到对应城市的目录下(Las Vegas训练模型样本)
最后一步输出,最好将模型固化到硬盘或云盘里,这样便于后来的压缩、传输和缓存。3.3 动态网络的可视化Yelper尤其对于分析用户-商业服务的相互作用,从而对城市得以有更深的思考感兴趣。为什么?因为我们认为:
总的来说,一个城市拥有更多的商业机会,这个城市发展的潜能就更大;
而更多的用户(居民,游客,人口等)可以刺激城市开发更多的商业服务来满足用户的需求
如下是建立城市为单位的用户-商业服务关系网络步骤:
用Spark GraphX提取图中的connected components(Scala 代码戳这里)
用Python生成动态的用户-商业服务关系网络图(Python代码戳这里)以生成Javascript JS文件(js 示例代码戳这里),用js文件做D3可视化(HTML代码戳这里)
下图是Madison(US)城市的示例。图中每个节点代表用户(绿色)或商业服务(蓝色)。如果一个用户对一个服务进行过评分,就会对应生成一条从用户(u)出发到商业服务(b)的边(edge)连接这两个节点,即边u–>b。Madison有超过10K条边,遗憾的是D3.js处理不了这么大的图,所以我们随机选取了一小部分在Chrome里展示。从这个关系网络里我们能发现什么?至少我们可以得到用户和商业服务的拓扑关系。图中边(红色)的密度从某种意义上反映了一个城市里用户对其所有的商业服务的评级。如果每个城市都能生成一个这样的关系网络,我们会发现每个城市的图都是不同的。这样单从这个关系图里就能进一步提取城市更深的信息,例如图形的in/out degree,聚合程度,page rank分析,min cut,社区发现等。

3.4 利用谷歌地图API的前端服务Yelper有一个服务器让用户可以收到推荐。这个服务器需要用到:
Spark
Flask
cherrypy
Python paste
Yelper的前端具有以下特点:
用户可以搜索任何他们感兴趣的关键字(不仅仅是餐馆)(Python 代码戳这里)
推荐的服务能够在谷歌地图中展示出来(Javascript 地图代码戳这里)
用户可以修改城市名和希望得到的推荐数目
RESTful API可以让用户在URL上修改城市/前K项推荐/关键字
下图是用户与Yelper的互动展示。ID为“10081786”的用户提出了Charlowww.senta7.net tte城市里关键字为“restaurants”,“book store”,”library”和“ice cream”的推荐请求,Yelper返回了“topK”条推荐结果,并且用谷歌地图API展示了地点信息。

3.5 模拟处理实时请求假设有成千甚至成百万的用户想要得到不同城市的推荐,处理这么多请求是很具挑战性的,因为:
Yelper需要能稳定地处理大量来自不同客户端的用户请求(手机,iPad,笔记本等)
用户的请求必须得到及时的反馈
对于这么大量的推荐请求,Yelper不能丢失任何一条,否则将影响用户的满意度和忠实度
这样我们就需要一个处理这些请求的网络计算队伍
而同时我们需要解决用户对不同服务的要求
这也只是冰山一角,实际需要处理的问题更多,所以我们需要一个强大的推荐架构。这篇文章就不再做更细的讨论,一个简单的办法是把这些来源不同的请求看作一个不间断的信息流(non-stopping stream),用Apache Kafka将这些请求转到Kafka上,然后用Spark Streaming以fault-tolerant和scalable方式进行流处理。这样做的好处有:
处理流程对于任何突发情况都具有容错性
可以pipe不同类型的信息
信息可以模块化(Modulization)
方便处理
下图展示了我们模拟的实时大量推荐请求处理(Python 代码戳这里)。terminal左边的窗口是用Spark Streaming以频率为1.5秒处理的用户请求。注意信息以时间戳的形式显示,例如“Time: 2016-09-25 14:37:22.500000”。每个推荐结果前都有Yelper的logo。在terminal的右边,我们用Python script生成随机时间间隔的用户请求。这些请求被piped到Apache Kafka上,这样Spark Streaming就能处理这些请求了。  

机器学习系列(17)_Yelper推荐系统的更多相关文章

  1. Weka中数据挖掘与机器学习系列之Exploer界面(七)

    不多说,直接上干货! Weka的Explorer(探索者)界面,是Weka的主要图形化用户界面,其全部功能都可通过菜单选择或表单填写进行访问.本博客将详细介绍Weka探索者界面的图形化用户界面.预处理 ...

  2. Java 集合系列 17 TreeSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  3. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证)

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证) ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框 ...

  4. Weka中数据挖掘与机器学习系列之Weka系统安装(四)

    能来看我这篇博客的朋友,想必大家都知道,Weka采用Java编写的,因此,具有Java“一次编译,到处运行”的特性.支持的操作系统有Windows x86.Windows x64.Mac OS X.L ...

  5. Spark2.0机器学习系列之11: 聚类(幂迭代聚类, power iteration clustering, PIC)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:             (1)K-means             (2)Latent Dirichlet all ...

  6. Spark2.0机器学习系列之10: 聚类(高斯混合模型 GMM)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  7. Spark2.0机器学习系列之9: 聚类(k-means,Bisecting k-means,Streaming k-means)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  8. Weka中数据挖掘与机器学习系列之Weka Package Manager安装所需WEKA的附加算法包出错问题解决方案总结(八)

    不多说,直接上干货! Weka中数据挖掘与机器学习系列之Weka系统安装(四) Weka中数据挖掘与机器学习系列之Weka3.7和3.9不同版本共存(七) 情况1 对于在Weka里,通过Weka  P ...

  9. Weka中数据挖掘与机器学习系列之Weka3.7和3.9不同版本共存(七)

    不多说,直接上干货! 为什么,我要写此博客,原因是(以下,我是weka3.7.8) 以下是,weka3.7.8的安装版本. Weka中数据挖掘与机器学习系列之Weka系统安装(四) 基于此,我安装最新 ...

随机推荐

  1. Nginx 做负载均衡的几种轮询策略

    网上看见nginx的upstream目前支持的5种方式的分配,摘录备忘. 1.轮询(默认)每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除.upstream back ...

  2. Java多线程——Executors和线程池

    线程池的概念与Executors类的应用 1.创建固定大小的线程池 package java_thread; import java.util.concurrent.ExecutorService; ...

  3. How to easily concatenate text based on criteria in Excel? 如何将Excel中的文本按条件合并

    To combine text with the unique ID numbers, you can extract the unique values first and then create ...

  4. android关机充电

    1.关机充电其实是进入adb shell很快的方式! 2.手机关机时候插入USB,手机将进入关机充电模式,那么这个模式究竟是怎么进行的,这里分析如下! (1)uboot:这里代码大概浏览了一下:u-b ...

  5. linux下64位汇编的系统调用系列

    http://blog.csdn.net/mydo/article/category/3084893

  6. android开发布局优化之ViewStub

    使用ViewStub可以延迟加载一个布局文件,提高显示速率.刚开始接触到,记录下来. 关于viewstub的使用,我们可以在不同的布局中使用,比如可以根据设备的大小动态决定显示哪个界面. viewst ...

  7. java Thread.join()

    thread1.join()方法阻塞调用此方法的线程,直到线程thread1完成,此线程再继续. 通常用于在main()主线程内,等待其它线程完成再结束main()主线程 @Test /** * ou ...

  8. android 6.0获取 WRITE_SETTINGS 权限

    android 6.0上只写在AndroidManifest中是不行的,还必须手动打开才行 private void setBrightnessMode(Context context, int mo ...

  9. Plain old data structure(POD)

    Plain old data structure, 缩写为POD, 是C++语言的标准中定义的一类数据结构,POD适用于需要明确的数据底层操作的系统中.POD通常被用在系统的边界处,即指不同系统之间只 ...

  10. Maven浅析-2 什么是Maven

    1.简单点讲:Maven就是一个项目构建工具.它可以生成一个artifact(component),还可以帮我们管理项目依赖(如附加的组件Filters等). 2.从整体讲:Maven也可以看作一个项 ...