为了解决大规模机器学习问题,工业界和学习界都做了很多努力。最开始是运用MPI,这个相对来说比较古老的并行接口来做大规模机器学习。MPI肯定本身还是比较灵活的,但是因为本身不是为大数据、以数据为中心的计算来设计的,所以在处理做大规模机器学习的时候还是有不少问题,首先开发不够友好,学习曲线比较高。容错性也比较差,如果跑一个大规模机器学习任务,跑了很久突然出问题了就不好处理。
Hadoop兴起后,很多人也尝试用Hadoop来实现机器学习算法。但是很快大家认识到在Hadoop上的MapReduce有很大的问题,一是BSP模式,所以同步代价很大。同时要做Shuffle,网络瓶颈也比较大。因为单个节点上的内存限制,也不能把规模放得特别大。为了解决MapReduce,后面又提出了AllReduce,通过树形通信来减少通信开销,这个机制在Spark里面就实现了。当然还有一波人认为MapReduce太粗了,所以就提出了Graph-Base的模型,这套模型的表达能力比较强、比较灵活,也可以处理比较大的模型。我个人认为,这个模型稍微复杂了一点,对于开发者来说学习曲线相对高了一点,而且也不是对所有算法有比较好的效率。
最近几年谈到大规模机器学习的框架,经常被提起的是Parameter Sever,它是为了解决超大规模、超大维度吸收数据的机器学习的问题。因为它很简单,就分成了Parameter Sever和worker两组的节点。Parameter Sever可以把模型分布式在各个节点上,每个Work去进行算法的局部训练,然后同步地去跟Parameter Sever来更新模型或者获取最新的模型。这种模式,如果是稠密数据,比如有亿维度数据是密的,肯定是不可行的。为什么呢?因为中间的通信会变得非常庞大。幸运的是超大规模机器学习的问题一般是稀疏的,所以目前Parameter Sever解决大规模机器学习最关注的一个方向。
市面上开源的大规模机器学习的框架并不是特别多或特别成熟。比如基于Hadoop Map Reduce Mahout,有很大的问题,效率很低。我曾经跑过一个算法,在几百台机器上花了50分钟,数据是100+G,找了大内存机器去跑,自己写了一个算法5分钟就跑完了。实际上,基于Hadoop来做机器学习的效率非常低。后来Spark出现了,各种机制、调度比Hadoop更加优化一点。所以MLLib里面算法的效率是大大高于基于Hadoop的算法的效率。Graph-Basc有一个项目是Graphlab,后来基于Graphlab成立了一个公司叫Dato, 前几个月刚改名Turi,刚刚被苹果收购了。Parameter Sever开源的有ps-Lite,这个项目我们也做过一些调研,发现它总体来说是比较轻量级的框架,但是对于实际应用上来说,可能还不够完善。另外一个是Petuum,在机器学习界很多人应该也知道它,我们现在也在跟他们在谈一些合作,看看怎么把Petuum真正带到实际应用中来。
我们现在要反思一下,我们看到前面的大规模机器学习解决的路径是什么?基本上是在考虑如何能够更好地并行,提高并行的效率。然后通过增加机器,计算能力和内存资源来解决计算的瓶颈。 但是大规模机器学习的计算瓶颈是算法本身造成的问题,一个是计算量跟数据量的超线性增长带来的,一个是多次迭代带来的。如果我们的算法能够解决这两个问题,在进行大规模机器学习的时候,对系统的压力会减轻很多。我们的理想算法是什么样子的?是线性算法,而且最好是迭代一次就能够收敛并且取得很好的效果。
在这一块,我们也做了很多的研究工作。之前我在IBM做机器学习研究的时候,看到了一个很有意思的算法,就是范伟博士在2003年提出来的随机决策树的算法。这个算法跟一般的决策树或随机决策树有很大的不同,每一颗树的构建过程是完全随机的,随机构建空树以后,把数据灌进去,然后统计每个节点的分布。预测的时候,每个树给出一个正常的预测过程,给出一个预测的概率,然后把多颗树的结果做平均就可以了。我在2010年对算法的复杂度做过一些分析,应该说这是一个线性的算法,计算了跟数据量增长呈线性关系。