目录
专栏 | 阿里妈妈基于TensorFlow做了哪些深度优化?TensorFlowRS架构解析
相比图像、语音、视频等领域,搜索、广告、推荐等场景有着独特的场景特点: 样本规模和特征空间通常非常巨大,千亿样本、百亿特征并不罕见,同时存在大量的稀疏特征作为Embedding输入。
阿里妈妈的优化:
TF作为一个分布式训练系统有两个主要的问题:
TensorFlowRS的解决方案:
在对TF做过细致的profiling之后,我们发现TF原生的PS由于设计和实现方面的多种原因(grpc,lock,graph-engine),很难达良好的水平扩展能力。于是我们决定丢掉TF-PS的包袱,重新实现一个高性能的参数服务器:PS-Plus。此外我们提供了完整的TF on PS-Plus方案,可以支持用户在Native-PS和PS-Plus之间自由切换,并且完全兼容TensorFlow的Graph语义和所有API。用户可以在深度网络代码一行不改的情况下,将参数分布和运行在PS-Plus上,享受高性能的参数交换和良好的水平扩展能力。
TensorFlowRS引入了worker state,在checkpoint中存储了worker的状态信息,worker重启后,会从接着上次的进度继续训练。此外TensorFlowRS通过zk生成cluster配置,支持了动态组网的Failover。新的Failover机制可以保证任意角色挂掉的情况下,系统都能在分钟级完成Failover,并且不多算和漏算数据。
所谓的exactly-once,参考:https://www.jianshu.com/p/5d889a67dcd3:
在分布式系统中,构成系统的任何节点都是被定义为可以彼此独立失败的。比如在 Kafka中,broker可能会crash,在producer推送数据至topic的过程中也可能会遇到网络问题。根据producer处理此类故障所采取的提交策略类型,我们可以获得不同的语义:
参数分配策略(variable placement),决定了如何将一个参数切分并放置到不同的server上。placement策略的好坏在高并发的情况下对PS的整体性能有着重大的影响。传统ParameterServer的placement方案是由系统预先实现几种常见的placement算法(比如平均切分+roundrobin),或者由用户在创建参数的时候手工划分,往往没有综合考虑全局的参数规模、Server的负载等。
PS-Plus实现了基于模拟退火算法的启发式参数分配策略,后续也在考虑实现基于运行时负载,动态rebalance的placement策略(是不是可以试试基于rl的呢,手动滑稽。。。)。PS-Plus的placement设计有如下优点:
目前主流的深度学习框架都是以连续的内存来存储训练参数,通过偏移量(ID值)来寻址到具体的权重。为了避免内存的浪费,需要对特征做从0开始的连续ID化编码,这一过程我们称之为特征ID化。特征ID化是一个非常复杂的过程,尤其是当样本和特征数量非常庞大的时候,特征ID化会占用大量的时间和机器资源,给样本构建带来了很大的复杂度。
PS-Plus内部实现了一个定制化的hashmap,针对参数交换场景做了专门的优化,在支持特征动态增删的同时提供了超高的性能。通过hashmap,PS-Plus直接实现了对非ID特征的支持,极大的简化了样本构建的复杂度。
对于Parameter Server架构,延迟是影响整体性能的重要原因。尤其是在模型复杂度不高的情况下,模型计算部分往往在10~100ms量级,那么总体通信的延迟就成为一个关键因素。
在传统的pipeline线程模型
我们认为polling + run to completion是一个正确的选择,并且设计了我们的整体通信层架构。
在新的通信层中,我们使用了Seastar作为底层的框架。对于Server、Worker上的connection,都严格保证connection绑定到固定的线程,同时线程与CPU核心绑定。Request、response直接采用run to completion的方式在当前线程处理。整体架构如下图所示:
在Seastar的基础上,做了很多功能、性能的改进和优化
注:更多关于SeaStar可以参考:https://daiwk.github.io/posts/platform-seastar.html
关于run to completion:https://en.wikipedia.org/wiki/Run_to_completion_scheduling
在Dense以及WDE(Wide-Deep-Embedding)两种经典模型的性能指标:
水平扩展能力比较:
TensorFlowRS通过对接PS-Plus,给出了一套完整的端到端的在线学习解决方案,赋予了TF支持千亿规模非ID化特征在线训练的能力。
在在线学习的场景下做特征实时ID化是比较复杂的,需要一个超高性能的全局的ID生成器,这给样本生成带来了很大的复杂度。TensorFlowRS利用PS-Plus直接实现了对非ID特征的支持,极大的简化了实时样本构建的复杂度。
在在线训练的场景下,训练任务会以service的形式长期运行,在训练过程中,不断会有新特征加入到模型中,为了保证训练可以长期进行而不会因为新特征的不断加入导致OOM,PS-Plus在支持特征动态添加的同时,还提供了默认的特征删除策略,可以将低频或者低权重的特征删除掉,用户还可以通过UDF定制符合自身业务需求的删除策略
在线学习模型更新的常见方式有全量和增量两种。在模型参数较多的情况下,全量更新的方式会对在线系统的带宽带来巨大的压力,而降低更新频率又会使模型的实效性降低。PS-Plus支持以任意频率将模型增量部分实时写出到消息队列,在大幅减少网络IO的同时实现了真正意义上的模型实时更新。
在在线学习的场景下,我们希望在训练的过程中就可以尽快的发现模型本身的异常,而不是等模型更新到线上之后。因此我们需要有一些方法来评估模型在训练过程中的 AUC等指标。TF里默认的streaming auc的实现在历史数据累积了一定量的时候,无法及时反应当前模型的状态,反馈有很大的滞后性。因此我们引入了新的AUC计算机制:AUC Decay。AUC Decay本质上是一种特殊的Moving Average,通过基于时间的减益方式,弱化历史样本和模型在当前AUC计算中的比重,以达到更快反应模型变化的目的。
大数据模型引入了分布式并行训练,同步并行训练受长尾worker的制约,并发数容易受限。异步并行是快速训练的主流。异步并行训练打破了普通SGD训练的串行性,计算的梯度与更新的模型不是严格一致,引入了梯度delay的问题。
在基于ParameterServer的训练框架里,系统分为两个角色:worker和ps。
异步并发训练打破了普通SGD训练的串行性,引入了梯度delay的问题。
如图,\(worker_m\)
拿到了模型\(w_t\)
,计算得到梯度\(g_t\)
,但传给ps时,已经有r个worker向ps提交了梯度更新,所以,这个时候应用到的是模型\(w_{t+r}\)
。虽然梯度更新的大方向可能偏差不大,但与模型\(w_{t+r}\)
期望的梯度\(g_{t+r}\)
相比,\(g_t\)
是存在细微偏差的。
微软在ICML2017提出过DC-ASGD optimizer【 Asynchronous Stochastic Gradient Descent with Delay Compensation】,使用泰勒展开来近似梯度补偿。我们测试在50并发以内收益良好。可是在上百并发训练里,泰勒展开超过了近似收敛半径,导致的误差增大,效果下降。
各框架实现dc-asgd的issue:
it was lacking an _apply_dense() implementation, there were typos that caused failures when used, etc.The commit is obviously in the history for somebody to re-use and fix, if they wanted, but they'd need to write more tests and probably refactor it to make it something that the team could accept to TensorFlow.
mxnet.optimizer.DCASGD
改进:引入\(\Delta w\)
【maybe就是下面第一篇里讲到的隐式动量?,,再看看】与g的相关因子来衡量梯度delay的严重程度,从而用来boost主流的sgd-based optimizer。在每一维度上:
\(\Delta w\)
与-g是正相关,说明大部分worker都在往同方向更新,模型w在这个方向上已经走的挺远了,继续前进需要谨慎。这个时候,保持g的方向不变,但减少g的绝对值。\(\Delta w\)
与-g是负相关,说明大部分worker都在往反方向更新,此时g是一个比较强烈的转折信号,揭示了模型w的更新方向要发生变化,我们需要重视这个信号,所以我们保持g的方向不变,但增大了g的绝对值。引入相关因子是基于以下原因:
For convolutional neural networks, we experimentally validate that the degree of asynchrony directly correlates with the momentum, confirming our main result. An important implication is that tuning the momentum parameter is important when considering different levels of asynchrony.
所以\(\Delta w\)
与g的相关性具备普适性,可以和主流的sgd-based optimizer结合,适应不同场景的不同优化器并发训练需求。
用相关性因子boost了SGD、Momentum、AdaGrad三种算法,
并行度 | Boosted-sgd auc | Boosted-moment auc | Boosted-adagrad auc |
---|---|---|---|
100 | +0.012% | +0.01% | +0.012% |
200 | +0.028% | +0.045% | +0.051% |
400 | +0.043% | +0.064% | +0.058% |
并行度 | Boosted-sgd accuracy | Boosted-moment accuracy | Boosted-adagrad accuracy |
---|---|---|---|
30 | +0.43% | +0.2% | +0.25% |
60 | +0.56% | +0.25% | +0.46% |
TFRS中集成了多种高阶训练模式,例如Graph Embedding,Memory Network,Cross Media Training等。
Graph Embedding,图是一种表征能力极强的数据结构,但是无法直接作为神经网络的输入。TFRS支持样本以图的形式进行输入,并支持多种随机游走算法动态生成正负样本。目前Graph Embedding已经应用在了淘宝搜索直通车的向量化召回等多个项目里,通过在User-Query-Item三种节点的异构有向图中随机游走,生成深度神经网络能够处理的稀疏特征。最终学习出User,Query和Item三者的高维向量化的表示,用于线上广告的向量化召回。
值得一提的是,除了Graph Embedding,我们同样支持对图的结构进行学习,例如在训练过程中反馈调整图中的边的权重等。
Memory Network记忆网络最早由Facebook在2015年提出,用于QA系统中。在本模型出现之前,机器学习的模型都缺乏可以读取和写入外部知识的组件。对很多任务来说,这是一个很强的限制。比如,给定一系列事实或故事,然后要求回答关于该主题的问题,虽然原则上这可以用RNN等模型进行处理,然而它们的记忆(隐藏状态和权重编码)通常太小,并且不能精确地记住过去的事实。在阿里妈妈搜索广告场景下,我们使用记忆网络对用户行为进行建模。
相比一般的在样本组织阶段进行记忆体生成的方式,TFRS通过在训练过程中引入动态记忆存储模块,支持长短期记忆,大幅提高了序列化类行为数据的训练效率。
参考https://daiwk.github.io/posts/dl-ntm-memory-networks.html
DeepInsight是一个深度学习可视化质量评估系统,支持训练阶段模型内部数据的全面透出与可视化分析,用以解决模型评估、分析、调试等一系列问题,提高深度模型的可解释性。
下面我们通过一个过拟合的例子来说明DeepInsight在模型质量分析和问题定位方面发挥的作用:
上图是通过DeepInsight生成的特征权重分布,从图中我们可以看到右侧过拟合模型的边权重大小分布很不均匀,出现了大量权重极大的边,且集中在一条带状区域内,其为某一组特征输入所连接的所有边,这表明模型过度拟合了该组特征的信息。在使用正则项和dropout之后,过拟合的问题仍然没解决,因此我们最终定位到问题出现在该组特征的输入上。