如何使基于梯度下降的机器学习并行化

来源:互联网 发布:mac更换输入法快捷键 编辑:程序博客网 时间:2024/05/16 08:12

本文,讨论batch-gradient和stochastic gradient descent的并行化。

首先来看batch-gradient。batch-gradient的每次更新都要在整个训练集上计算获得。比如,logistic regression的更新公式为:

(1)
图片来自coursera上的《Machine Learning》截屏

因此若训练集很大(m很大),这种做法是十分耗时的。那何做到并行化呢?Andrew ng 在《Machine Learning》中便提到了机器学习的并行化:如果机器学习算法能表示成training set上函数的sum的形式(即上面公式),那么一个好的并行化选择是使用Map-reduce。一个Map-reduce job分两个阶段进行:map阶段和reduce阶段。因此可以将原本的sum公式(1)分解成几个小的sum公式,each由不同map task分别计算,最后由reduce task把map得到的结果进一步加和。


好,看来batch-gradient的并行化不是个很大的问题。但batch-gradient本身有缺陷:若机器学习算法(比如矩阵分解问题)面临的是一个非convex的算法,那么使用batch-gradient会使算法收敛很慢[2],并且很可能陷入局部最优解(local optimum)。因此,实际中使用的是SGD(Stochastic Gradient Descent)——随机梯度下降。SGD的主要思想是:不同于以往利用整个training set更新一次参数,SGD随机从training set 中挑选出一个样本进行更新,直到算法收敛。 [1]指出KDD Cup 2011(track 1)的前三名都使用了SGD。SGD有算法converge 快,不容易陷入局部最优解的优点。


但是SGD内在本身是序列化的,因而不容易并行化。但不是不能,基本思想是:若为选定的一个评分r_ij,算法对应要更新的用户feature向量p_i和物品feature向量q_j,也就确定了。因此,评分矩阵中,所有即不同行又不同列的评分都可以同时更新。台湾国立大学的团队提出了一种快速的基于内存共享的并行SGD算——FPSGD。根据评测,它超出了现有被认为最好的shared-memory SGD并行算法CCD++。[13]指出,以往的SGD并行化算法面临两个问题:①缓存命中率低和②等待问题。首先,缓存命中率低是由算法内在的随机选取引起的。而等待问题是由数据的imbalance引起的。比如评分预测问题中,有的用户评分多,有的用户评分少,因此整个评分矩阵是imbalanced的。若使用DSGD(详见[1]),则所有节点要等待最慢的那个节点处理完(“最慢”可能是因为它被分配的block是最密集的)。


针对问题②,可以在执行DSGD之前random shuffle整个评分矩阵。但作者不满意这样方法,它指出不同线程的执行时间还会有差异。于是作者提出给空闲线程分配任务的方法:将整个矩阵分成(s+1)×(s+1)块,让s个线程同时执行。这样一个线程处理完一个block之后,必定有其他的block是free的(free是指不与其他线程处理的block共享用户或物品feature向量)。算法则为其分配更新次数最少的free block——为了使所有block的更新次数都差不多。论文显示,这样的方法使DoI在a few iteration之接近zero。(见论文)。


针对问题①,作者提出了partial random method:即更新块的选择是随机,而块内的更新是有序的。同时为了增加随机性,算法将评分矩阵分成了比(s+1)×(s+1)更多的块。


最后值得指出的是,作者将改算法实现并开源了,enjoy!


参考文献:

[1] A Fast Parallel SGD for Matrix Factorization in Shared Memory Systems

[2] Efficient Top-N Recommendation for Very Large Scale Binary Rated Datasets

1 0
原创粉丝点击