沐神的成名作谁能不爱?这是沐神2014年发表在OSDI的文章,一篇有关大规模分布式机器学习参数服务器的内容。大数据系统有很多,比如通用领域的批处理系统MapReduce,spark,流处理系统storm,spark Streaming,当然也有特定领域的系统像图处理系统Giraph,基于Spark的机器学习系统MLlib。本文的大数据系统是一个用于分布式机器学习问题的参数服务器框架,开源后已经被亚马逊,Facebook,百度等多家顶级互联网公司应用。
本文提出了一个用于分布式机器学习问题的参数服务器框架。数据和任务都分布在工作节点上,而服务器节点维护全局的共享参数,表示为密集或稀疏的向量和矩阵。该框架管理节点之间的异步数据通信,支持灵活的一致性模型,具有弹性可扩展和持续容错特性。
实验部分为了证明框架的扩展性,展示了PB级别的真实数据的实验结果,其中包含数十亿示例和参数,涉及从稀疏逻辑回归到潜在狄利克雷分配和分布式草图等问题。
分布式优化和推理正在成为解决大规模机器学习问题的先决条件,现有的问题为:
训练数据的实际数量在1TB到1PB之间变化,这允许人们设计 1 0 9 10^9 109到 1 0 12 10^{12} 1012参数规模的强大复杂的模型。这些模型通常由所有节点共享,在执行计算时经常访问共享参数。共享带来三个挑战:
上图是某数据中心作业情况,其中任务失败是由于没有容错机制而导致被抢占或丢失机器。因此容错是工业界部署的必要条件(与研究不同)。
本文是参数服务器的第三代开源实现,着重于分布式推理的系统方面。它为开发人员提供了两个优势:
参数服务器提供了五个关键特性:
本文所提出系统的新颖之处在于通过选择正确的系统技术,将它们应用于机器学习算法并修改算法以使系统更加友好实现协同作用。特别地,我们可以放松一些其他方面的硬件约束,因为相关机器学习算法对扰动有很强的的容忍度。这样就得到了一个可以扩展到工业规模的通用ML系统。
在当时机器学习领域通用的系统如spark,只能处理比较小规模的数据场景,但是本文的参数服务器作为通用的分布式系统,能够在工业界处理最大规模数据。
在进行分布式数据分析时涉及读取和更新不同工作节点共享参数问题。参数服务器框架为工作节点之间的模型参数和统计信息之间的聚合同步提供了一种有效的机制。每个参数服务器仅维护一部分参数,并且每个工作节点在运行时通常只需要这些参数的子集。在构建高性能参数服务器系统时出现了两个关键挑战:
上图展示了在不同系统上执行最大监督和无监督学习实验的规模。很明显,本文的系统能够在数量级更大的处理器上覆盖数量级更大的数据。
上表概述了几种机器学习系统的主要特性。本文的参数服务器在一致性上提供更多的灵活性,并且是唯一提供持续容错机制的系统。原生的数据类型也对数据分析友好。
这里想谈谈上图的容错,可以看到参数服务器是持续的容错,而Graphlab等提供的是检查点等容错,持续容错的优势是容错恢复快,并且不像检查点那样,要占用很多的空间存储检查点信息,同时回退也会造成重复计算。
亚马逊、百度、Facebook、谷歌、微软和雅虎已经实现了相关系统。第一代参数服务器缺乏灵活性并且性能不好,它将高速缓存memcached键值分布式存储重新应用在同步机制。YahooLDA通过实现用户可定义的更新原语和更具原则性的负载分配算法实现专用服务器从而改进此设计。第二代参数服务器Distbelief是特定任务系统。Petuum迈出了通用平台的第一步。它使用有界延迟模型改进了YahooLDA,同时对工作线程模型进一步限制。
将参数服务器和通用的机器学习分布式系统进行比较是有意义的。同步和迭代通信会随着节点的增多带来更多的挑战。基于Hadoop的Mahout和Spark的MLIib均采用迭代MapReduce框架。MLI的一个关键点在于迭代之间保持状态,这是参数服务器的核心目标。
分布式GraphLab使用图形抽象来异步调度通信。它缺乏基于Map-reduce框架的弹性可扩展性,依赖于粗粒度快照进行恢复,这两者都阻碍了可扩展性。它对于某些算法的实用性受到缺乏作为有效的一流原语的全局变量同步的限制。本文的参数服务器的一个核心目标是获得GraphLab异步的优势,同时不受框架限制。
Piccolo使用与参数服务器相关的策略来共享和聚集节点之间的状态。工作节点在本地预先聚集状态并将更新传输到保持聚合状态的服务器。它实现了本文系统很大一部分,但是缺少专门的优化:消息压缩,复制和通过依赖图表示的变量一致性模型。
机器学习系统通常由三部分组成:特征提取,目标函数和学习。其中特征提取处理原始训练数据,获得特征向量。
许多机器学习算法的目标可以通过“目标函数”来表达,这个函数可以捕捉学习模型的属性。学习算法通常最小化目标函数来获得最终模型。通过多次迭代改进模型接近解决方案。当接近最优解或者模型收敛时停止迭代。此外,训练数据可能非常大,每个数据都可能表示为非常高维的特征向量。迭代处理如此大规模的数据需要巨大的计算和带宽资源,并且,每天可能会有更新数据添加到系统中,这需要算法实时运行。如何高效执行是本文的主要关注点。下面介绍两种广泛使用的机器学习技术用来演示参数服务器的功效。
风险大体上是预测误差的一种度量,是预测值与真实值之间的误差。训练由n个数据组成, x i x_i xi是第 i i i个样本,通常是长度为 d d d的向量。每个训练样本 x i x_i xi与一个标签 y i y_i yi相关联。风险最小化可以学习一个预测未来示例 x x x的标签的模型。
在任何学习算法中,训练数据量与模型大小之间存在重要关系。一个更复杂的模型通常会提高准确性,但是只能在一定程度上提高,因为数据集数量不够的话会导致模型过拟合。另一方面,一个太小的模型无法捕获对做出正确决策至关重要的数据的相关属性。
正则化风险最小化是寻找平衡模型复杂性和训练误差的一种方法。它通过最小化两个项的和来实现:表示训练数据上的预测误差的损失 L ( x , y , w ) L(x,y,w) L(x,y,w)和惩罚模型复杂性的正则化器 Ω [ w ] \Omega[w] Ω[w]。一个好的模型是低错误和低复杂度的模型。所以努力最小化:
F ( w ) = ∑ i = 1 n l ( x i , y i , w ) + Ω ( w ) F(w)=\sum^n_{i=1}l(x_i,y_i,w)+\Omega(w) F(w)=i=1∑nl(xi,yi,w)+Ω(w)
在实验部分,本文使用高性能分布式学习算法来评估参数服务器。为了简单起见,这里先描述一个更简单的模型叫分布式次梯度下降。
如上图和算法1所示,训练数据按块分发到所有节点上,这些节点共同学习出参数向量 w w w,该算法迭代运行。在每次迭代中,每个节点独立地使用自己的训练数据来确定应该对 w w w进行哪些更新以接近最优值。由于每个节点的更新只反映它自己的训练数据,所以系统需要一种机制来允许这些更新进行融合。它通过将这些更新表示为次梯度(参数向量 w w w应移动方向)并在将所有次梯度应用于 w w w之前聚合到一起。
算法1中开销最大的步骤是计算次梯度去更新 w w w。这个任务被分配给所有的节点,每个节点执行迭代任务。作为其中一部分,节点计算 w T x i k w^Tx_{i_k} wTxik,对于高维的 w w w可能不可行。幸运的是,当且仅当它的一些训练数据引用该条目时,节点才需要知道 w w w的坐标。例如在广告点击预测中,如果只有极少数广告包含OSDI 2014短语,那么大多数节点不会对 w w w中的相应条目产生任何更新,因此不需要此条目。尽管 w w w的总大小可能超过单个机器的容量,特定节点所需要的工作条目可以简单缓存在本地。上图显示,对于100个节点,每个节点只要需要总参数的7.8%,当有10000个节点时,降低到0.15%。
这里在看完沐哥的视频后,才有了更深的理解,为什么参数服务器需要多个服务器节点存储参数,而工作节点只需要一个就行呢?以及坐标是什么意思?因为对于单个工作节点,它只需要拿到一部分参数就可以在已有的数据集上进行训练了,它所拥有的只是一部分数据,只会更新一部分参数,所以上面所描述的坐标,就是指所需的那一部分参数在参数服务器中所在的位置。
无监督学习算法没有训练标签,它的思想是试图捕获数据集的基础结构,例如给定文档集合,推测每个文档包含的主题。在推荐系统内容个性化等实际环境中,这些问题的规模是巨大的,这使得跨大型集群并行化算法变得至关重要。
由于上述问题的规模和数据量,这些算法在引入第一代参数服务器才具有商业价值。主题模型的一个挑战在于参数描述当前估计文档应该是如何产生的必须要共享。一个热门的主题建模方法是潜在狄利克雷分布(LDA)。虽然统计模型是完全不同的,但所得到的学习算法与算法1很相似。关键的区别在于更新步骤不是一个梯度计算,而是模型对文档解释程度的估计。
计算需要访问每个文档的辅助元数据,该元数据在每次访问文档时都会更新。由于文档的数量很大,每当处理文档时,通常都会从磁盘读取元数据并将其写回磁盘。辅助数据是分配给文档的主题集,学习的参数 w w w由单词出现的相对频率组成。
与监督学习一样,每个节点只需要存储处理文档中出现的单词的参数,因此可以处理比单个节点可处理的更大的模型。
参数服务器节点分组为一个服务器组和多个工作组,如上图所示。
对于服务器组:
对于工作组:
参数服务器支持独立的参数命令空间,这允许工作组将其共享的参数集与其他组分离。当然不同工作组也可以共享命名空间,可以用多个工作组并行处理深度学习应用。
参数服务器旨在简化分布式机器学习应用程序。
节点之间共享的模型可以表示为一组键值对。例如在损失最小化问题中,配对的是特征ID和权重,在LDA中,配对的是单词ID和主题ID以及计数。
本文的参数服务器通过识这些键值项的潜在含义改进了这种方法:机器学习算法通常将这些模型视为线性代数对象,比如在风险最小化中的参数 w w w,通过将这些对象视为稀疏线性代数对象,参数服务器可以提供与键值对抽象的相同功能,同时加入重要优化操作,如向量加法、乘法,计算2范数等其他精细操作。
为了支持这些优化,假设key值是有序的。可以将参数视为键值对同时赋予它们向量和矩阵语义。有助于使用机器学习中的线性代数,这减少了实现优化算法的编程工作量。此外,这种接口设计利用CPU高效的多线程自调整线性代数库(BLAS、LAPACK等)实现高效的代码。
与一般的键值对不同,这里的key是int64或int128,value是一串浮点数,可以理解成向量,可以用一些数值运算库直接处理。
节点之间采用push和pull传输数据。算法1中每个节点将其整个局部梯度推送到服务器中,然后将更新的权重拉取回来。算法3中更高级的算法采用相同的模式,只是每次通信一定范围的keys。
参数服务器通过支持基于范围的推和拉来优化这些更新,以方便程序员,同时提高计算和网络带宽效率。如果 R \mathcal{R} R是一个key范围, w . p u s h ( R , d e s t ) {\rm w.push}(\mathcal{R},{\rm dest}) w.push(R,dest)表示从 R \mathcal{R} R范围内key表示的所有 w w w的现有条目发送给目标,目标可以是特定节点,也可以是服务器组等节点组。 w . p u l l ( R , d e s t ) {\rm w.pull}(\mathcal{R},{\rm dest}) w.pull(R,dest)执行相反的操作。
这个接口可以扩展通信任何共享相同key的本地数据结构。比如在推送本地梯度可以用 w . p u s h ( R , g , d e s t ) {\rm w.push}(\mathcal{R},{\rm g},{\rm dest}) w.push(R,g,dest)来减少内存同时享受其他的优化。
服务器节点可以执行用户自定义函数,这是因为服务器节点有共享参数更完整和更新的信息。算法1中,服务器节点评估次正则项 Ω \Omega Ω的次梯度以便更新 w w w。在5.3的草图中,几乎所有的操作都发生在服务器端。
独立任务通过并行使用 CPU、磁盘和网络带宽来提高系统效率。但是,这可能会导致节点之间的数据不一致。比如上图迭代11用的是旧的迭代10,会获得与迭代10中相同的梯度。这种不一致会降低算法1的迭代速度。不过一些算法对这种不一致不太敏感。比如在算法3中,每次只更新 w w w的一部分,这样只会导致一部分不一致。
系统效率和算法收敛速度之间的权衡通常取决于多种因素,包括:算法对数据一致性的敏感度、训练数据特征相关性以及硬件组件容量差异。
参数服务器为算法设计者提供了定义一致性模型的灵活性。这里展示了三种根据任务依赖性实现的不同模型。有向无环图如下所示:
依赖关系图可以是动态的,调度器可以根据运行进度调整延迟,以平衡系统效率和底层优化算法的收敛。
参数服务器支持用户自定义过滤器选择同步单个键值对,从而对任务中数据的一致性进行细粒度控制。优化算法本身需要分析出哪些参数对同步信息最有用。在5.1节会详细讨论KKT过滤器。
服务器采用一致性哈希存储键值对参数。为了容错,条目采用链复制进行复制,与之前的键值对系统不同,参数服务器针对基于范围的通信和基于范围的向量时钟进行了压缩优化。
考虑到潜在复杂的任务依赖关系图和快速恢复的需要,每个键值对都与一个向量时钟关联,该向量时钟记录每个单独节点在该键值对上的时间。虽然向量时钟很便捷,但是其简单实现需要 O ( n m ) O(nm) O(nm)空间去处理 n n n个节点和 m m m个参数。这在内存和带宽上是不可行的。
由于参数服务器基于范围的通信模式,许多参数具有相同的时间戳。如果一个节点在一个范围内推送参数,那么与节点相关联的时间戳很可能相同。这些时间戳可以被压缩为一个单一范围的向量时钟。
初始状态对于每个节点 i i i只有一个范围的向量时钟,覆盖整个参数key空间。每个范围集可以拆分出最多3个新的向量时钟。设 k k k是算法传递唯一范围的总数,那么最多有 O ( m k ) O(mk) O(mk)个向量时钟, m m m是节点的个数。这显著减少了范围向量时钟所需的空间。
比如在语言模型中,模型有几十或者几百层,在做vector clock计时,只需要计算每个节点在每一层用的是哪个时间的值,这样存储量就大大减少。
节点可以将消息发送给单个节点或者节点组。消息格式如下:
[ v c ( R ) , ( k 1 , v 1 ) , . . . , ( k p , v p ) ] k j ∈ R a n d j ∈ { 1 , . . . , p } [{\rm vc}\mathcal{(R)},(k_1,v_1),...,(k_p,v_p)] k_j \in \mathcal{R} {\rm and} j \in \{ 1,...,p\} [vc(R),(k1,v1),...,(kp,vp)]kj∈Randj∈{1,...,p}
这是参数服务器基本的通信格式,同时适用于共享参数和任务。
消息可以携带范围 R \mathcal{R} R内所有可用key的子集,缺失的key被分配相同的时间戳而不改变它们的值。
keys和服务器节点ID都被嵌入到哈希环中,每个服务器节点管理从其插入点开始到逆时针方向下一个节点的插入点的key范围,称为主节点。物理服务器通常通过多个虚拟服务器在环中表示,以改善负载平衡和恢复。
每个服务器节点存储着相对于自己拥有的k个逆时针方向的邻居keys范围的副本。我们把保存副本的节点称为对应键范围的从节点。上图左边展示了一个k=2的例子,服务器1复制了服务器2和服务器3拥有的键范围。
工作节点与主节点通信,主节点上任何修改都会同步复制到从节点上。上图显示了工作节点1将x推送到服务器1的情况,只有确认数据修改复制到从节点上才完成推送任务。
原始的复制会让网络带宽增加k倍。参数服务器允许聚合后复制。如上图右边所示。虽然聚合增加了任务回复的延迟,但是可以通过宽松的一致性条件来避免。
为了实现容错和动态扩展,必须支持节点的添加和删除。当加入一个服务器时,步骤如下:
在收到节点更改消息时,节点N首先检查是否也维护key范围 R \mathcal{R} R(现在归新节点维护)。如果不再维护就把相关联的所有键值对和向量时钟删除。接下来对于尚未收到回复的消息,如果键值范围与 R \mathcal{R} R相交,消息将拆分并重新发送。
服务器节点的离开类似于加入,同样是对节点key范围的管理。服务器管理器通过心跳信号检测节点故障。未来可与Yarn或Mesos进行集成。
添加工作节点W与添加服务器节类似但更简单,步骤如下:
当工作节点开始离开,任务调度器可能开始更换。系统给算法设计者提供控制恢复的选项,有两点原因:
因此算法设计者可能更愿意继续而不做更换。
实验部分基于稀疏逻辑回归和DLA评估参数服务器。
稀疏逻辑回归是最流行的大规模风险最小化算法之一。它将损失函数与 l 1 l_1 l1正则化结合。使用的数据集包括636TB数据(压缩后为141TB),在1000台机器上运行参数服务器,每个机器有16个物理啮合,192GB的内存。800台机器充当工作节点,200台服务器充当参数服务器。
算法:采用算法3,它在四个方面不同于之前的简单变体:
在这篇文章发表前,没有开源系统可以将稀疏逻辑回归扩展到本文描述的规模。
参数服务器将与系统A和B对比,A和B代码超过10k行,而参数服务器只需要300行就可以实现与系统B相同的功能。参数服务器成功地将大部分系统复杂性从算法实现转移到可重用的通用组件中。
上图表明系统B优于A,因为实现了更好的算法。参数服务器优于系统B,因为参数服务器降低了网络流量以及应用了宽松一致性的模型。
根据第三四节的描述,这里参数服务器优势主要体现在值缓存和压缩零,以及宽松一致性带来了一定的异步特性,提高了工作节点的利用率。
上图进一步显示宽松一致性模型大大提高了工作节点的利用率。系统A有32%的空闲时间,系统B有53%的空闲时间,而参数服务器只有2%。可以看到参数服务器在计算开销要略多于系统B,主要因为参数服务器异步更新需要更多轮次迭代才能达到相同的目标,当然B在预处理部分也做了一定的优化。
接下来评估每个系统的网络流量减少情况。可以看出允许发送方和接收方缓存key可以节省近50%流量。此外应用KKT过滤器时,数据压缩是非常高效的。这是因为:
可以看出超过93%的特征被KKT过滤器过滤。
最后分析有界一致性模型。上图显示在不同的延迟下,工作节点实现相同收敛标准所需时间。可以看到:
略
略
后两节没有解读有两点原因,首先实验一已经很好论证了参数服务器性能的优越性,同时评估了网络流量减少程度和有界一致性模型最佳性能,后面两个模型最多也是得到相同的结论。第二,沐哥也在视频中提及,后面的实验有些复杂,并且和本系统关联没那么紧密的,只是想证明这个系统的通用性,除了机器学习,还能做更多其他工作。
本文描述了一个参数服务器框架解决分布式机器学习问题。这个框架有以下优势:
http://www.istc-cc.cmu.edu/publications/papers/2014/parameter_server_osdi14.pdf
https://blog.csdn.net/u011254180/article/details/80200696
https://blog.csdn.net/zj_18706809267/article/details/125044839
https://zhuanlan.zhihu.com/p/508056568
https://www.bilibili.com/video/BV1YA4y197G8/
特别推荐李沐老师本文亲自讲解这篇文章的视频,干货满满,许多文章中不理解的地方一点即通!
参数服务器作为面向大规模场景分布式机器学习系统,具有简单易用,执行高效,支持弹性可扩展和容错性等特征,并且在真实数据上实验效果好。看完这篇文章后我也有自己的一点思考,首先是它的动态一致性,将异步的思想带入到机器学习中,很好的利用了机器学习迭代的特性,那就是当前迭代如果用的是旧数据,那么再迭代一次就好,不会造成模型结果出错。第二就是它的应用场景,在实验部分就能看出它用了几乎半个互联网大公司的服务器集群去完成实验,这在真实情况下是不现实的。但是随着现在的大规模预训练语言模型的出现,模型的参数达到了 1 0 11 10^{11} 1011左右的规模,那么也就只有参数服务器这样类型的系统才能够支持这样的大规模计算,可见这个9年前的系统还是很有前瞻性的。
另外,本篇文章我也有做相关的汇报和PPT,感兴趣的朋友可以私信我~