Press "Enter" to skip to content

结合Spark与TF,Uber客服系统引入深度学习

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

年初我们在Uber引入了 客户满意服务单辅助系统(Customer Obsession Ticket Assistant,COTA) ,利用机器学习和自然语言处理()技术给客户服务人员推荐服务单类别和回复模板。在我们的客户服务平台集成COTA后,在保持甚至提高客户满意度的前提下,英文服务单的响应时间缩短了10%.
对Uber而言,这只是一个开始。为了提高COTA表现,我们安排了离线试验。试验显示,深度学习可以将类别模型的top-1预测精确度从49%提高65%,将回复模型的top-1预测精确度从47%提高到55%(更多细节请参考我们的KDD论文,arXiv:1807.01337)。考虑到这些任务的复杂度,这真的是很不错的成绩。
由于试验的结果很鼓舞人心,我们决定将我们的深度学习模型部署到Uber内部的机器学习平台Michelangelo。为此,我们创建了一个基于Spark的深度学习工作流,以基于Michelangelo的现有基础设施产品化第二代COTA( v2)。由于模型的表现会随着时间推移而下降,我们同样创建了模型管理工作流,自动重新训练、撤下模型,使模型始终保持最新。
集成到Michelangelo之后,在线测试验证了之前的试验结果,相比COTA v1系统,COTA v2深度学习系统在模型表现、服务单处理事件、客户满意度等关键测度上,有了显著提升。

初代COTA:挑战和机遇

COTA v1主要有两个地方需要提高:

  1. 对负面样本的处理方式过于复杂,使训练模型变得困难。再加上依赖特定的数据表,再训练需要大费周章。
  2. 扩展性不够,将来的NLP模型难以使用。

为何深度学习?
COTA v1的成功促使我们进一步投入技术栈,探索其他服务解决方案。在全球超过600个城市提供服务,支持多种语言和超过5种沟通渠道,Uber的客服涉及Uber旗下各种服务。这样的范围和规模给我们面临的挑战增加了极大的复杂度。因此,归类和解决服务单的方式数以千计。此外,Uber的成长需要我们以前所未有的节奏迭代。如果没有考虑到业务增长,今天奏效的解决方案可能几个月后就失效了。
深度学习给包括机器翻译、语音识别、计算机视觉、自然语言理解在内的众多的领域带来了变革,并在特定任务上取得了和人类相当乃至超过人类的表现。因此,深度学习看起来是开发COTA v2自然的选择。事实上,通过离线测试,我们发现,相比COTA v1,深度学习模型可以提供精准得多的服务单响应预测。

迁移至基于深度学习的COTA v2

简单来说,COTA v1基于传统的NLP方法进行主题建模,并使用了结合文本特征、类别特征、数值特征的机器学习技术,如下图上半部分所示:

上:COTA v1;下:COTA v2

COTA v1创建了处理输入的服务单消息的NLP工作流,以提取文本特征。并通过另外的特征工程生成余弦相似度。一切特征就绪后,将所有特征传入一个二元逐点排序算法,预测服务单类别和回复模板。
上图的下半部分刻画了COTA v2所用的深度学习架构。文本特征经过典型的NLP预处理(例如文本清洗和tokenization,示意图上没有显示),服务单中的每个单词通过一个嵌入层(示意图上没有显示)编码为密集表示,并进一步通过卷积层编码整个文本语料库。类别特征通过嵌入层编码,以捕捉不同类别的接近程度。数值特征通过批归一化稳定训练过程。我们的离线试验表明COTA v2深度学习系统较COTA v1有显著提升(提高了8-16个百分比),无论是单独预测类型和回复,还是一次性联合预测类型和回复,皆是如此。

上图显示了深度学习模型学习到的嵌入的t-SNE图形。例如,上图左半部分可视化了一些Uber特定的关键词,我们发现,“载具”(vehicle)和“汽车”(car)在t-SNE图形上非常接近。和支付相关的单词,例如“充值”(charge)、“信用”(credit)、“费用”(fare),在t-SNE图像上也聚类在一起。
上图右半部分可视化了学习到的服务单类型嵌入,其中每个数据点对应一个类型。类型有三种颜色:“搭车人”、“司机”、“其他”(餐饮、旅馆等)。在t-SNE图形上,“搭车人”和“司机”的聚类很明显。这些可视化直观地确认了模型正在学习合理的表示,同时暗示模型足以捕捉单词间的相关性和语义联系,以及服务单类型之间的关系。
部署COTA v2的挑战和解决方案
由于深度学习模型在离线测试上成果喜人,我们决定将其部署到生产系统。然而,同时集成NLP转换和深度学习训练带来了不小的复杂度,再加上我们将使用大量训练数据,部署COTA v2深度学习模型很有挑战性。
理想情况下,我们想要利用Spark分布式地进行NLP转换。Spark计算通常基于CPU集群。另一方面,深度学习训练在基于GPU的基础设施上运行起来更高效。为了应对这一双重性,我们需要找到一个同时使用Spark转换和GPU训练的方法,同时创建一个训练深度学习模型并提供服务的统一工作流。
另一项挑战是我们需要决定如何在Uber业务的动态本质下保持模型的新鲜度。因此,工作流需要频繁地重新训练、重新部署模型。
为了解决第一项挑战,我们创建了一个深度学习Spark工作流(DLSP),同时使用Spark进行NLP转换,使用GPU进行深度学习训练。至于第二项挑战,我们集成了一个内部工作规划工具,在DLSP的基础上创建了一个模型生命周期管理工作流(MLMP),让我们可以按所需频率规划和运行每项工作。这两个工作流让我们得以在Uber的生产系统上训练和部署深度学习模型,同时重新训练和更新模型以保持峰值表现。
在接下来的两部分中,我们将详细讨论这两个工作流。

COTA v2的深度学习Spark工作流

分两个阶段定义工作流,一个阶段进行Spark预处理,一个阶段进行深度学习,看起来是分配工作负荷的最佳方式。我们扩展了Spark工作流的概念,得以使用现有的基础设施支持批量预测和实时预测服务。
训练
模型训练分为两个阶段,如下图上部所示:

  1. 基于Spark进行预处理: 我们利用Uber的大规模Spark集群进行数据预处理,同时拟合训练和服务所需的转换。在预训练时对数据所做的一切转换均保存为Spark转换器,接着用于创建Spark工作流提供服务。在Spark集群上进行分布式预处理比在单GPU节点上预处理数据要快得多。我们在Spark集群上计算拟合转换(需要持续数据的转换,比如StringIndexer)和非拟合转换(比如从字符串中清洗HTML标签)。
  2. 基于TensorFlow进行深度学习训练: 一旦完成了第一步的预处理,我们便利用预处理过的数据基于TensorFlow训练深度学习模型。然后合并这一阶段训练好的模型和上一阶段生成的Spark工作流,得到最终的Spark工作流。最终工作流整合了预处理转换器和TensorFlow模型,以便运行预测。我们实现了一个特殊类型的转换器,称为TFTransformer,以结合Spark工作流和TensorFlow模型。因为所有的Spark工作流都是基于Java实现的,所以TFTransformer也使用了Java。

服务
上图的下半部分展示了如何基于深度学习Spark工作流在批量预测和实时预测服务使用训练好的模型。我们扩展了Michelangelo以支持通用Spark工作流,并利用现有的部署和服务基础设施提供深度学习模型服务。用于提供服务的工作流运行在JVM上。我们观察到提供服务时的延迟为p95 < 10ms(译者注:95%的情况下延迟低于10毫秒),这展示了使用现有的JVM服务基础设施带来的低延迟优势。通过扩展Spark工作流封装深度学习模型,我们能够融CPU驱动和GPU驱动两家之长:1) 基于CPU的Spark转换分布式计算和Spark工作流低延迟服务;2) 基于GPU加速深度学习模型训练。

模型生命周期管理工作流:模型保鲜

为了避免COTA v2模型的表现随时间推移而下降,我们在DLSP的基础上创建了一个模型生命周期管理工作流(MLMP)。具体来说,我们利用Uber内部工作规划工具Piper创建了一个端到端工作流,以固定频率重新训练、重新部署模型。

如上图所示,模型生命周期管理工作流共有6项工作,使用Michelangelo现有的API重新训练模型。这6项工作构成了一个有向无环图(DAG),箭头表示依赖关系:

  1. 数据ETL: 包括数据提取,基本转换,加载工作以准备数据。通常从若干不同的数据源拉去数据,转换数据至恰当的格式,并放入Hive数据库。
  2. Spark转换: 这一步骤转换原始数据(文本、类别、数值,等等)为张量格式,提供给TensorFlow图作为输入,以训练模型。底层的转换通过Michelangelo利用了Spark引擎分布式进行。转换器保存到模型存储。
  3. 数据传输: CPU计算机集群进行Spark转换。深度学习训练需要GPU加速进程。因此,我们将第二步的输出数据传输至GPU机器。
  4. 深度学习训练: 数据一旦传输至GPU集群,就会触发一项工作,开启基于定制的Docker容器的GPU会话,并开始深度学习训练过程。训练结束后,将TensorFlow模型文件保存至模型存储。
  5. 模型合并: 合并第2步的Spark转换器和第4步的TensorFlow模型,形成最终模型。
  6. 模型部署: 部署最终模型后,生成 model_id 以便引用新部署的模型。外部微服务可以使用服务框架Thrift引用 model_id 。

在线测试:COTA v1 vs. COTA v2

为了验证我们在离线试验中观测到的COTA v2深度学习模型的表现,我们在滚动式更新系统前进行一次在线测试。
测试策略
为了避免早先存在的采样偏差,我们在A/B测试前先组织了一次A/A测试,如下图所示:

在A/A测试和A/B测试期间,服务单以50/50的比例随机分配至对照组和实验组。在A/A测试期间,对照组和实验组的预测均由COTA v1模型做出。而在A/B测试期间,实验组使用COTA v2深度学习模型。
结果
A/A测试跑了一周,A/B测试跑了大概一个月。下图展示了我们追踪的两个关键测度:模型精确度(这里我们以服务单类型为例)和每个服务单的平均处理时间。如下图上部所示,在A/A测试期间,模型表现没有差异,而开启A/B测试后,实验组的模型大大提升了。这些结果确认了COTA v2深度学习系统比COTA v1体改了更精确的解。
如下图下部所示,在A/B测试期间,实验组的平均服务单处理时间要低得多。另外,从上图上部我们还能观测到一个现象,模型的表现随着时间推移而下降,突显了模型管理工作流MLMP的必要性。(为了保证一致性,在试验期间没有重新训练模型。)
我们的在线测试再次证明给定足够的训练数据,COTA v2深度学习模型的表现明显超过经典的COTA v1机器学习模型。

统计分析表明,A/A测试期间对照组和实验组的平均处理时间没有显著差异,而A/B测试期间存在显著差异。服务单处理时间有6.6%的相对缩短。另外,服务单建议的精确度也提高了。此外,我们也测量了顾客满意度评分,发现使用COTA v2后满意度略有提升。
COTA v2不仅提升了客户支持的体验,而且通过提高服务单解决过程的效率每年为公司节省数百万美元。

下一步

鉴于COTA v2中的深度学习模型的强力表现,我们计划在未来使用服务单类型预测决定给定服务单分配给哪个客服,因为专门处理特定类型问题的客服通常能更快地积累经验。这一更新将增加在初次路由中识别解决客户服务单的合适客服的概率,提升整个服务单支持系统的效率。
我们还打算考察能让我们更快地回复仅仅请求信息的服务单的特性。例如,提问“我如何更新Uber账户头像”的服务单。这类服务单,只需直接分享静态信息(在这一情形下是指引)就可以解决。在所有服务单中,这可能只占一小部分,但这些服务单可以在无需客服监督的情况下由COTA v2自动处理。提高这些静态回应的效率可以帮助客户节省时间,也能让客服集中精力处理更具挑战性的服务单,以提供更好的客户服务。

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注