机器学习与微博:TensorFlow在微博的大规模应用与实践
作者|何沧平
编辑|Vincent
AI前线出品| ID:ai-front
借 AI 前线提供的交流机会,我给各位汇报一下 TensorFlow 在微博的使用情况和在分布式计算上的一点经验,错误疏漏不足之处,敬请批评指教。
TensorFlow 在微博的应用场景
今天的分享内容由虚到实,由概括到具体。
微博的日活和月活数量都在增长,移动端比例很高,占 91%。2017 年 4 月份的财报显示,营收同比增涨 67%,一个重要原因就是移动端抢到了用户的碎片时间。
微博里随处可见推荐信息:推荐的新闻、推荐的视频、推荐的新账号。最重要还有推荐的广告。
用户登录以后,立刻就要计算推荐什么内容。拿推荐广告来说,备选的广告数以万计,需要排序给出最可能被点击的几条广告。
如果切中用户的购买需要,广告就不再是打扰。
垃圾严重影响用户体验,色情、暴力、反动、低俗,宁可错杀不可漏网,十分严格。
人工智能反垃圾的目标是提高准确度、降低成本。
图像质量也是用户体验的基本要求。
用户可以容忍不感兴趣的图片,但很难容杂乱的图像。
例如左边的美女图,看起来赏心悦目,手机上刷过,即使不停下细看,也不会反感。
右边的图片,里面也是美女,但加上文字之后,立刻变得杂乱,版式与酒店里的小卡片相仿。很可能被认定为骗子。
明星是微博制胜的法宝。明星是公众人物,话题多、热度高、影响力大。明星粉丝狂热,消费力强。
为粉丝推荐她他喜欢的明星的行程、事件、各种评价,粉丝爱看。甚至明星代言的广告,粉丝可能都会喜欢。停留在微博的时间越长,有意无意浏览的广告就越多。正确识别明星就很重要了,如果不巧推荐了用户讨厌的明星,可能就没了刷微博的心情。
明星脸识别是微博的特色,有海量的明星图片,也有巨大的识别需求。
明星脸识别有特别的困难:常用人脸识别研究所用的照片表情、造型较少,不同人之间的差别较大。而明星表情丰富,造型多变,无论男女都化妆!不少人妆容近似,有些整容脸连人脑都傻傻分不清,计算机就更难分清了。
上部的图片可能归属两个及以上类别,因此称为“兼类”。
图片、视频分类的最终目的都是为了关联广告。喜欢旅游的用户就给她他推荐旅游景点、线路、酒店、机票、户外装备等。
如果广告能够切中用户本来就要买的物品,就不必费尽心机说服用户购买不必要的商品,只需要将购买场所由一个地点(网站、实体店)转移到另一个地点,将购买时间由将来转移到现在,将商品品牌由 A 切换为 B。这样广告效果自然会好很多,点击率高,用户还不反感。
例如,印度电影《三个白痴》中几次提到太空笔,我当时就特别想买一支,在京东上搜了半个小时。如果能够提前识别到这个广告点,并在播放过程中推荐购买链接,很可能立即就下单了。
但是,图像分类难,视频精细分类更难,又不得不分。短视频(5 分钟以内)方兴未艾,变现模式还不成熟,处于烧钱阶段。相对于文本、图片,短视频的带宽成本更高,消耗的用户时间更多。如果关联广告的转化率不高,入不敷出,无法长久。
TensorFlow 在微博的应用技术 & 案例
务虚内容结束,下面是具体点的技术。
微博机器学习平台承担了离线训练和在线预测任务。微博实时产生的文本、图片、视频显示后转入后台,用于提取特征、离线训练。
越来越多的业务使用深度学习方法,TensorFlow/Caffe 框架被集成进来。
离线训练主要使用 GPU 机群。由于业务增长过快,计算机群有一部分来自阿里云。
这一页完全是个人理解。
对规模巨大的训练任务,TensorFlow 提供了分布式的模式。
TensorFlow 分布式计算与 HPC 的 MPI(Message Passing Interface) 分布计算区别很大。用过 MPI 的人都知道,MPI 进程相互平等,保证没有瓶颈进程。MPI-IO 也设计得每个主机都能均匀分担 IO 压力。MPI 进程上的计算任务也要求均匀划分,保证各个进程的计算进度保持一致。MPI 进程之间也只交换数据块的边界,尽量减少网络流量,压缩通信时间。
TensorFlow 的分布式计算设计得简单粗暴。
若干参数服务器 (parameter server) 和若干劳工 (worker) 组成一个机群 (cluster),劳工承担运算任务,将每步运算得到的参数(权重和 bias)提交给参数服务器,参数服务器将来自所有 worker 的参数合并起来,得到全局参数,然后将全局参数发送给劳工。劳工在全局参数的基础上继续下一步运算。
TensorFlow 采用主从模式,参数服务器是瓶颈。每步都要传递所有的参数,网络流量太大,假设每个劳工上参数占用内存 1GB,机群包含 1 个参数服务器和 10 个劳工,那么每个迭代步将产生 20GB 的网络流量,按照 10GbE 网络计算,通信时间至少需 16 秒。而实际上,每个 batch 数据的运算时间可能还不足 1 秒,模型参数占用的内存可能远大于 1GB。从理论分析来看,TensorFlow 分布式运算的效率不如 MPI。
有人说深度学习只是高性能计算的一个特殊应用,我认为不是这样。
如图中表格所列,TensorFlow 机群就与 HPC 机群有重大区别。
HPC 机群的 3 大特点:高性能计算芯片(高端 CPU、GPU)、高速网络、并行存储。TensorFlow 机群只需要其中的 1 个:高端 GPU。
劳工在一批数据上训练得到W 和b(合称为P),称为一步训练。
如上图所示,所有的劳工(Device A/B/C)在完成一步训练后,暂停训练,将自己得到的P 发送到参数服务器(Parameter Device)。参数服务器一直等待,直到来自所有的劳工的参数变化量P 都接收成功。参数服务器将所有的P 相加取平均,然后用这个均值更新旧参数(更新公式请参见随机梯度算法),得到新参数 P,接着将 P 发送给所有的劳工。劳工在接收到新参数 P 以后,才进行下一步的训练。
与用 1 台服务器训练相比,用 N 台劳工同时训练 + 同步更新参数等价于将 batch 的规模扩大了 N 倍。具体来说,如果用 1 台服务器时,每步训练采用 100 张数字图片(batch=100), 那么用 4 个劳工得到的参数变化量(即P)同步更新,就相当于每步训练采用 400 张数字图片(batch=400)。从而,参数变化得更平稳,收敛更快。
同步更新也有缺点:整体速度取决于最慢的那个劳工。如果劳工之间的软硬件配置差别较大,有明显的速度差异,同步更新计算速度较慢。
为了避免劳工有快有慢造成的等待,TensorFlow 提供了异步更新策略。
如图下部所示,当有一个劳工训练得到一个参数变化量P 时,不妨假设是图中的 Device A,该劳工立即将P 发送给参数服务器。参数服务器接收到来自劳工 Device A 的P 后,不等待其它的劳工,立即用P 更新全局参数,得到全局参数 P,紧接着将 P 发送给劳工 Device A。劳工 Device A 接收到全局参数 P 后,立即开始下一步训练。
由异步更新参数的过程可知,它等价于只用 1 台服务器训练:都是每次用一小批(batch)图像训练更新参数,只是各批数据的上场顺序不能事先确定,上场顺序由劳工的随机运行状态确定。
刚开始运算时,劳工 0(左边) 先算了 10100 步(对应 localstep), 此后劳工 1(右边)才开始运算。这说明,在异步运算模式下,劳工之间确实不相互等待。劳工 0 和劳工 1 都运算了全局第 10100 步 (global_step_value),说明运算的剖分并不十分准确。
2 个劳工都执行了第 13142、13144、13146、13148 步,但都没有执行 13143、13145、13147 这 3 步。这说明 Tensorflow 异步更新的任务指派会随机出错,并不是绝对不重不漏。所幸随机梯度法对更新顺序没有要求,少量的错误对最终计算结果影响不大。
同步更新模式不能真正地同步执行,将程序杀死的时候,2 个劳工执行完的步数相差很多。劳工 0 本地执行了 11023 步之后,全局步数竟然只有 7072,肯定出错了。
网络上也有人报告了这个错误:
github.com/tensorflow/…,
TensorFlow 开发者已经确认这是一个漏洞,但尚未修复。
公式预警……
以 MNIST 手写数字识别为例,上部分公式迭代一步就使用所有 n 个样本。
下部公式将所有样本分割成若干批次(batch)。
TensorFlow 的异步更新,就是不同的劳工使用不同的小批训练样本来更新权重和 bias,不能事先确定每个劳工的更新顺序。具体举例:假设有 2 个劳工执行训练任务,劳工 0 负责更新奇数批次样本 b1/b3/b5…b499,劳工 1 负责更新偶批样本 b2/b4,…,b500。
由于各种随机因素,样本的使用顺序可能是 b1àb3àb5àb2àb7àb4à…因为样本的批次划分本身就是随机的,这样乱序更新仍然是随机的,对最终结果没有什么影响。
TensorFlow 同步更新时,对所有劳工得到的梯度求平均,然后更新权重和截距。仍然假设有 2 个劳工,它们分别训练第 1 批和第 2 批样本得到梯度w1 和b1 截距分别为w2 和b2,同步之后的梯度如图中所示。
从而,同步更新等价于一次使用 2m 个训练样本,正则化系数和 batch 大小都扩大为原来的 2 倍而已。如果劳工数量很多(例如 20 个),那么同步更新就等价于一次使用 2000 个训练样本,与划分 batch 的初衷不符。因此,建议不要使用同步更新。
注意公式里红色的(2m)
下面是一个具体优化案例:
CTR(Click-Through-Rate,点击通过率)是营收的关键。
对候选广告按点击可能性排序,然后插入到用户信息流之中。
deepCTR 不完全是特征工程,输入层与隐层的连接关系也是不全连接。
千亿样本数据近百 TB,为提高效率,采用多人推荐过的 TensorFlow 队列。
个人理解,队列的设计初衷很好(如图中表格所示),但实际性能很差,GPU 利用率只有 5%。查找原因发现,程序卡在线程同步操作上,而这个线程同步就来自于 TensorFlow 队列。于是尝试用别的方式读取训练样本文件。
左图横轴采用对数坐标。
队列读以 CSV 带宽只有极限带宽的 1/467,队列读取 tfrecord 格式文件带宽提升至 1.24MB/s,提高至 3.2 倍。由于 tfrecord 格式文件较小,读完一个文件的耗时降低至 15%(272.6/1789.9)。
用 pandas 读取文件带宽达到极限带宽的 35%。最终舍弃 TensorFlow 队列,选用 pandas 读 CSV 文件。
当 CSV 文件小于 1/3 内存时,直接用 pandas 一次性读入内存。不用 tf 队列,数据混洗就要程序员自己完成,所幸不麻烦。
对大于内存 1/3 的文件,直接拆分成多个小文件。需要程序员自行保证均匀使用各个小文件。
最后给各位汇报一个小游戏。
用 MNIST 训练得到的 CNN 网络来识别汉字,“霸”字被识别为 1。这点很容易理解,得到的 CNN 网络只有 10 个类别,不得不在 0~9 个数字中选一个。
因为“霸”字与任何数字都不像,识别为任何数字的“概率”应该都不太大吧,例如都小于 0.2(随便说的数值)。可是实际情况却是这样:0~9 分类对应的概率差别很大,最大接近 0.8,最小接近 0,卷积网络识别汉字的时候不会犹豫不决,错得十分坚定。
从这个小实验里可以发现几个问题:
图像的特征究竟是什么?如果有,如何用这些特征来区分不认识的图像(比如这个例子里的汉字)?
如何控制一个网络的泛化能力?这个例子中的泛化能力看起来太强了,以致于把汉字都识别成数字了。目前看来,CNN 的泛化能力几乎是听天由命。
softmax 后的值真的代表概率吗?看起来它们仅仅是和为 1 正数。概率本质的随机性体现在哪里呢?
这些问题,我还没有想明白,这里提出来,请各位朋友批评指教。
问答环节
问题 1:队列读取性能差是否是由于设置 cache 的样本数问题?回答:cache 基本没有影响。batch_size 会有影响,最关键还是线程锁的问题。
问题 2:(反垃圾)这一步的准确率怎么算的?是模型准确率吗?
回答:这个涉及到业务,不便透露。可以私下交流。
问题 3:千亿级别 feature 没有模型并行吗?感觉模型单机放不了,不能数据并行。
回答:数据并行,因此研究分布式运算。
问题 4:1 亿条评论的话,你怎么判断分类器是否分正确了?还是说这里的准确率只是在测试集上的准确率?
回答:业务上具体做法不便透露。这里提醒一下,微博有举报、屏蔽功能。
问题 5:微博的 TensorFlow 环境配置,资源管理和分布式计算是用的第三方平台吗?还是自己封装的
回答:资源管理和分布式计算尝试过几种方案,开源软件 + 自行定制。多种机群,安全级别和管理方式不完全一样,因此资源管理方式(网络、存储、权限)也不一样。
问题 6:会考虑评价 GPU 的利用率吗?比如用 deepbench 测?有什么 GPU 提升利用率的经验分享?
回答:GPU 利用率是成本核算的重要指标,很重视。查看 GPU 利用率比较简单:命令行 nvidia-smi,英伟达还有专门的库,提供轻量级的 C、JAVA 等接口。
提高 GPU 利用率经验:如果显存能装得下,尽量使用 1 个模型训练;设定显存使用量(例如 0.5),将 2 个及以上作业放在同一个 GPU 上。IO 性能差的话,会导致数据供应不上,从而 GPU 利用低。PPT 中 deepCTR 优化案例就是这个情况。batch 太小、权重矩阵过小,都会导致不能充分利用 GPU 的大量核心(通常有 4000-5000 个),利用率低。
问题 7:如果在庞大的 csv 上训练, 用 tf 队列和用 spark df 制作生成器的效果有比对过么?
回答:目前没有对比过 tf 队列和 spark df。
作者介绍
何沧平,微博研发中心算法工程师,目前负责建设深度学习平台。对高性能计算(HPC)较熟悉,著有《OpenACC 并行编程实战》一书。如有相关技术问题可以私下与讲师讨论,讲师微信:272702575
-全文完-
AI前线提供最新最全AI领域技术资讯、一线业界实践案例、搜罗整理业界技术分享干货、最新AI论文解读。欢迎关注我们的微信公众号:AI前线
接下来会陆续更新一系列与 TensorFlow 理论与实践案例相关的文章,这是第一篇,敬请期待。
- 免责声明
- 本文所包含的观点仅代表作者个人看法,不代表新火种的观点。在新火种上获取的所有信息均不应被视为投资建议。新火种对本文可能提及或链接的任何项目不表示认可。 交易和投资涉及高风险,读者在采取与本文内容相关的任何行动之前,请务必进行充分的尽职调查。最终的决策应该基于您自己的独立判断。新火种不对因依赖本文观点而产生的任何金钱损失负任何责任。