王益,分布式机器学习的践行者,他的足迹值得后来者学习。
膜拜策略:
- LinkedIn高级分析师王益:大数据时代的理想主义和现实主义(图灵访谈)【心路历程】
- 分布式机器学习的故事-王益【历史由来】
腾讯孔雀系统
一、基本状况
2014年业内现状
并且很多研究员也并不擅长设计适合于自己研发的算法的并行计算架构
业内实际问题
同时也和腾讯的同事们一起为国际数据挖掘大赛出题,比如KDD Cup 2012和ICME Grand Challenge 2014。
业内大牛
互联网行业里有一些学界业界交融好榜样,比如卡内基梅隆大学的Alexander Smola教授。
他在Yahoo!有丰富的业界经验。在成为Principle Scientist之后,去卡内基梅隆任教,传授业界积累的大数据挖掘知识。同时在Google做访问研究,保持研究水平的领先。我相信将来会有更多研究人员像这样两条胳膊都撸起袖子。
伟大经历
Google 让我见识和实践了世界一流的大数据技术,
Tencent 给了我了解互联网业务的机会。
二、并行机器学习系统 - 孔雀
孔雀是一个主题模型的并行训练系统。主题模型是一种机器学习方法,它从文本中归纳“语义”,每个“语义”是一组表达同样意思的词。这个归纳过程通常比较耗费机器和时间;但是一旦归纳结束,得到了主题模型,那么机器就可以在几毫秒之内理解任何一段文本(搜索词、广告、商品描述或者网页内容)表达的语义,从而在语义空间里比较用户意图(搜索词)和广告、商品、网页的相关性。而相关性是现代搜索引擎、推荐系统、广告系统的核心要素之一。主体模型除了用在文本数据上,也可以用在用户行为数据上——此时它就是一个先进的协同过滤推荐系统。
Ref: 分布式机器学习的故事(侧记):论文发表了
"感谢阵容" 极为豪华!
Ref: 让机器搞懂100万种隐含语义,腾讯Peacock大规模主题模型首次全揭秘
此处只是本文的阅读理解,详读还需要未来花时间好好瞧瞧。
/* implement */
三、Google的Rephil系统
2006年开始,Google的Rephil系统就可以从好几个数量级大的文本数据中归纳几十万语义,从而奠定了Google AdSense广告系统的相关性的基石,最终帮助AdSense成为Google收入的半壁江山。
其作者(博士Uri Lerner和工程师Mike Yar)在2002年在湾区举办的几次小规模交流中简要介绍过。
Ref: 分布式机器学习的故事:Rephil和MapReduce
因为概率模型做了太多的 ”指数族分布假设“。
Rephil系统实现的模型是一个神经元网络模型(neural network)。它的设计的主要考虑,就是要能尽量好的描述长尾分布的文本数据和其中蕴含的语义。Rephil模型的具体技术细节因为没有在论文中发表过,所以不便在这里透露。但是Rephil模型描述长尾数据的能力,是下文将要介绍的Peacock系统的原动力,虽然两者在模型上完全不同。
Rephil系统是基于Google MapReduce构建的。如上节所述,MapReduce在用来实现迭代算法的时候,效率是比较低的。这也是Peacock要设计全新框架的原动力——使其比MapReduce高效,但同时像MapReduce一样支持fault recovery。
以下三篇需要再整理:
(1)[Bayes] Concept Search and LSI
(2)[Bayes] Concept Search and PLSA
(3)[Bayes] Concept Search and LDA
四、韭菜所学
长尾需求
可是互联网的精髓在于服务用户的“长尾”需求。
战狼养生
在座的百度的余凯老师表示理解,总结说:“今日中国是极端的理想主义和极端的现实主义的结合”。我甚感共鸣,其实古往今来莫非如此。
他这样在数学、计算机、金融、投资、管理等多个方面努力学习、融会贯通,功底是和扎实的。而为了做到这些,他每天的体能训练也很扎实。并且为了保持精神状态,每天洗冷水澡。
编程理解
其中对我影响最大的是Lisp,是我的同学王垠教我的,让我接触了一点计算的数学本质。
在微软图形学组实习时学了GPU的汇编语言,后来用GPU写并行机器学习算法的时候用过Cg。
我工作中用的语言主要是C++。
从写Peacock开始用Go。
Go语言的开发效率比C++和Java都高很多,让我能在七天假期里尝试新模型和新的并行化方法。
简单的分布式数据处理用bash+ssh+awk代替MapReduce。
职业规划
原来Hulu.com的engineering VP张小沛。她对择业的建议很简练:“最重要的是知道自己要的是什么”。
分布式机器学习的故事
简言之,互联网使得人类第一次有机会收集全人类的行为数据。从而为机器学习这一持续了数十年的研究方向提供了全新的机会——分布式机器学习——从互联网数据中归纳这个人类的知识,从而让机器比任何一个个人都要“聪明”。
一、大数据和分布式机器学习特点
我见过的有价值的大规模机器学习系统,基本都有三个特点:
1. 可扩展。可扩展的意思是“投入更多的机器,能处理更大的数据”。且Fault recovery是可扩展的基础。
2. 数学模型要根据架构和数据做修改。这里有两个原因:
(a)因为大数据基本都是长尾分布的,而papers里的模型基本都假设数据是指数分布的。
(想想用SVD做 component analysis其实假设了Gaussian distributed,latent Dirichlet allocation假设了multimonial distribution。)
真正能处理大数据的数学模型,都需要能更好的描述长尾数据。否则,模型训练就是忽视长尾,而只关注从“大头”数据部分挖掘 “主流”patterns了。
(b)很多机器学习算法(比如MCMC)都不适合并行化。所以往往需要根据模型的特点做一些算法的调整。
有时候会是 approximation。比如AD-LDA算法是一种并行Gibbs sampling算法,但是只针对LDA模型有效,对其他大部分模型都不收敛,甚至对LDA的很多改进模型也不收敛。
3. 引入更多机器的首要目的不是提升性能,而是能处理更大的数据。
(a)用更多的机器,处理同样大小的数据,期待speedup提高——这是传统并行计算要解决的问题 ——是multicore、SMP、MPP、GPU还是Beowolf cluster上得分布式计算不重要。
(b)在大数据情况下,困难点在问题规模大,数据量大。此时,引入更多机器,是期待能处理更大数据,总时间消耗可以不变甚至慢一点。分布式计算把数据和计算都分不到多台机器上,在存储、I/O、通信和计算上都要消除瓶颈。
上述三个特点,会在实践中要求:“一个有价值的算法值得也应该有自己独特的框架”。
二、并行范式
框架实现
概念在 开始说故事之前,先正名几个概念:Message Passing和MapReduce是两个有名的并行程序编程范式(paradigm),也就是说,并行程序应该怎么写都有规范了——只需要在预先提供的 框架(framework)程序里插入一些代码,就能得到自己的并行程序。
-
- Message Passing(消息传递)范式的一个框架叫做MPI,其实现叫作:MPICH2
- MapReduce范式的框架也叫MapReduce,其实现叫作:Apache Hadoop
- BSP范式,其实现叫作:Google Pregel
资源管理和分配
MPI这个框架很灵活,对程序结构几乎没有太多约束,以至于大家有时把MPI称为一组接口(interface)——MPI的I就是interface的意思。
这 里,MPICH2和Hadoop都是很大的系统——除了实现框架(允许程序员方便的编程),还实现了资源管理和分配,以及资源调度的功能。
-
- 在 Google的系统里是分布式操作系统负责的,而Google MapReduce和Pregel都是在分布式操作系统基础上开发的,框架本身的代码量少很多,并且逻辑清晰易于维护。
- 当然Hadoop已经意识到这个问题,现在有了YARN操作系统。(YARN是一个仿照UC Berkeley AMPLab的Mesos做的系统。关于这个“模仿”,又有另一个故事。)
三、pLSA和MPI——大数据的首要目标是“大”而不是“快”
故事缘由
我2007年毕业后加入 Google做研究。我们有一个同事叫张栋,他的工作涉及pLSA模型的并行化。这个课题很有价值,因为generalized matrix decomposition实际上是collaborative filtering(协同过滤)的generalization,是用户行为分析和文本语义理解的共同基础。几年后的今天,我们都知道这是搜索、推荐和广告这三大互联网平台产品的基础。
当时的思路是用MPI来做并行化,张栋和宿华合作,开发一套基于MPI的并行pLSA系统。MPI是1980年代流行的并行框架,进入到很多大学的课程里,熟悉它的人很多。MPI这个 框架提供了很多基本操作:除了点对点的Send, Recv,还有广播Bdcast,甚至还有计算加通信操作,比如AllReduce。
试图并行化
MPI很灵活,描述能力很强。因为MPI对代码结构几乎没有什么限制——任何进程之间可以在任何时候通信——所以很多人不称之为框架,而是称之为“接口”。
但是Google的并行计算环境上没有MPI。当时一位叫白宏杰的工程师将MPICH2移植到了Google的分布式操作系统上。具体的说,是重新实现MPI里的Send, Recv等函数,调用分布式操作系统里基于HTTP RPC的通信API。
MPI 的AllReduce操作在很多机器学习系统的开发里都很有用。因为很多并行机器学习系统都是各个进程分别训练模型,然后在合适的时候(比如一个迭代结束 的时候)大家对一下各自的结论,达成共识,然后继续迭代。这个“对一下结论,达成共识”的过程,往往可以通过AllReduce来完成。
如 果我们关注一下MPI的研究,可以发现曾经有很多论文都在讨论如何高效实现AllReduce操作。比如我2008年的博文里提到一种当时让我们都觉得很 聪明的一种算法。这些长年累月的优化,让MPICH2这样的系统的执行效率(runtime efficiency)非常出色。
基于MPI框架开发的pLSA模型虽然效率高,并且可以处理相当大的数据,但是还是不能处理Google当年级别的数据。
自动错误恢复功能 de 必要性
原因如上节『概念』中所述—— MPICH2没有自动错误恢复功能,而且MPI这个框架定义中提供的编程灵活性,让我们很难改进框架,使其具备错误恢复的能力。
具 体的说,MPI允许进程之间在任何时刻互相通信。如果一个进程挂了,我们确实可以请分布式操作系统重启之。但是如果要让这个“新生”获取它“前世”的状 态,我们就需要让它从初始状态开始执行,接收到其前世曾经收到的所有消息。这就要求所有给“前世”发过消息的进程都被重启。而这些进程都需要接收到他们的 “前世”接收到过的所有消息。这种数据依赖的结果就是:所有进程都得重启,那么这个job就得重头做。
一个job哪怕只需要10分钟时间,但是这期间一个进程都不挂的概率很小。只要一个进程挂了,就得重启所有进程,那么这个job就永远也结束不了了。
虽 然我们很难让MPI框架做到fault recovery,我们可否让基于MPI的pLSA系统支持fault recovery呢?原则上是可以的——最简易的做法是checkpointing——时不常的把有所进程接收到过的所有消息写入一个分布式文件系统(比 如GFS)。或者更直接一点:进程状态和job状态写入GFS。Checkpointing是下文要说到的Pregel框架实现fault recovery的基础。
MPI的尴尬
但是如果一个系统自己实现 fault recovery,那还需要MPI做什么呢?做通信?——现代后台系统都用基于HTTP的RPC机制通信了,比如和Google的Stubby、 Facebook的Thrift、腾讯的Poppy还有Go语言自带的rpc package。做进程管理?——在开源界没有分布式操作系统的那些年里有价值;可是今天(2013年),Google的Borg、AMPLab的 Mesos和Yahoo!的YARN都比MPICH2做得更好,考虑更全面,效能更高。
四、LDA和MapReduce——可扩展的基础是数据并行
因为MPI在可扩展性上的限制, 我们可以大致理解为什么Google的并行计算架构上没有实现经典的MPI。同时,我们自然的考虑Google里当时最有名的并行计算框架MapReduce。
MapReduce 的风格和MPI截然相反。MapReduce对程序的结构有严格的约束——计算过程必须能在两个函数中描述:map和reduce;
输入和输出数据都必须 是一个一个的records;
任务之间不能通信,整个计算过程中唯一的通信机会是map phase和reduce phase之间的shuffuling phase,这是在框架控制下的,而不是应用代码控制的。
pLSA支持EM可并行
pLSA 模型的作者Thomas Hoffmann提出的机器学习算法是EM。EM是各种机器学习inference算法中少数适合用MapReduce框架描述的——map phase用来推测(inference)隐含变量的分布(distributions of hidden variables),也就是实现E-step;reduce phase利用上述结果来更新模型,也即是M-step。
LDA支持"多份”并行
但 是2008年的时候,pLSA已经被新兴的LDA掩盖了。LDA是pLSA的generalization:一方面LDA的hyperparameter 设为特定值的时候,就specialize成pLSA了。从工程应用价值的角度看,这个数学方法的generalization,允许我们用一个训练好的 模型解释任何一段文本中的语义。而pLSA只能理解训练文本中的语义。(虽然也有ad hoc的方法让pLSA理解新文本的语义,但是大都效率低,并且并不符合pLSA的数学定义。)这就让继续研究pLSA价值不明显了。
另 一方面,LDA不能用EM学习了,而需要用更generalized inference算法。学界验证效果最佳的是Gibbs sampling。作为一种Markov Chain Monte Carlo(MCMC)算法,顾名思义,Gibbs sampling是一个顺序过程,按照定义不能被并行化。
但 是2007年的时候,UC Irvine的David Newman团队发现,对于LDA这个特定的模型,Gibbs sampling可以被并行化。
具体的说,把训练数据拆分成多份,用每一份独立的训练模型。每隔几个Gibbs sampling迭代,这几个局部模型之间做一次同步,得到一个全局模型,并且用这个全局模型替换各个局部模型。
这个研究发表在NIPS上,题目 是:Distributed Inference for Latent Dirichlet Allocation。
上述做法,在2012年Jeff Dean关于distributed deep leearning的论文中,被称为data parallelism(数据并行)。如果一个算法可以做数据并行,很可能就是可扩展(scalable)的了。
David Newman团队的发现允许我们用多个map tasks并行的做Gibbs sampling,然后在reduce phase中作模型的同步。这样,一个训练过程可以表述成一串MapReduce jobs。我用了一周时间在Google MapReduce框架上实现和验证了这个方法。
后来在同事Matthew Stanton的帮助下,优化代码,提升效率。
BSP范式 Pregel的由来
但是,因为每次启动一个MapReduce job,系统都需要重新安排进程(re-schedule);并且每个job都需要访问GFS,效率不高。
在当年的Google MapReduce系统中,1/3的时间花在这些杂碎问题上了。后来实习生司宪策在Hadoop上也实现了这个方法。我印象里Hadoop环境下,杂碎事 务消耗的时间比例更大。
随后白红杰在我们的代码基础上修改了数据结构,使其更适合MPI的AllReduce操作。这样就得到了一个高效率的LDA实现。我们把用MapReduce和MPI实现的LDA的Gibbs sampling算法发表在这篇论文里了。
当 我们踌躇于MPI的扩展性不理想而MapReduce的效率不理想时,Google MapReduce团队的几个人分出去,开发了一个新的并行框架Pregel。
当时Pregel项目的tech lead访问中国。这个叫Grzegorz Malewicz的波兰人说服了我尝试在Pregel框架下验证LDA。
分布式机器学习系列讲座
八小时无尿点讲座,666~
一、与单机ML之区别
ML重在数学知识。
Distributed ML重在软件工程。
二、四大Framework
Frameworks: MPI, mapReduce, Pregel (类似 Spark), GBR
MapReduce弱点,这也是为什么有了后来的spark
-
- MapReduce Lite (c++ version)
- 在哪里启动进程,分布式操作系统去做,但mapReduce自己去“多余”的实现了。
三、分布式主题模型
Peacock使用golang实现。
扒数据:内容数据,行为数据。
四、长尾效应
广告“长尾”推荐。
1% 随机点击率,非常小;重视长尾,提高点击概率。
五、分布式操作系统
分布式机器学习的平台基础,也是机制实现的前提条件。
“大”比“快”更重要。
Kubernetes 是Google一个开源的 Docker 容器编排系统,它可以调度计算集群的节点,动态管理上面的作业,保证它们按用户期望的状态运行。通过使用「labels」和「pods」的概念,Kubernetes 将应用按逻辑单元进行分组,方便管理和服务发现。
六、Fault Recovery
进程会挂掉,很可能是因为优先级低,被高优先级的杀掉了,属于正常行为。
大数据用Java,好么?
七、Pitfalls
- De-noise data 描述长尾的方法:非参贝叶斯方法,包括 Dirichlet process, 皮特曼尤尔过程 (Pitman-Yor Processes)
- Parallelize models in papers and textbooks
- Use existing frameworks.
- MPI
- Mix frameworks with cluster operating systems
- Less talking about production
- Use standard measures
- Java or Python,最大的两个坑。吹一波 Golang。
八、大杀器与业务优化
Analysis 由人力覆盖大头,长尾还是比较困难。
九、Full-stack.
End.