本文要点
- 现在,很多客户支持平台都配备了人工智能,大大节省了人力,提高了用户体验。
- 历史会话数据会随着时间的推移而增加。将这些数据放到Apache Hadoop集群中是一个可扩展的数据管理和共享解决方案。
- Analytics Zoo是一个面向Apache Spark上分布式TensorFlow、Keras和BigDL的统一分析+ AI平台,由英特尔开源。
- Analytics Zoo为从集群中读取和预处理文本数据提供了丰富的支持。用户可以轻松地使用内置模型以分布式方式执行自然语言处理任务。
- 本文将逐步演示如何使用Analytics Zoo构建端到端的QA排名应用程序。该解决方案已被Microsoft Azure成功地用于服务其客户。
本系列文章讨论了微软Azure中国团队在Azure上使用Intel Analytics Zoo构建人工智能客户支持平台的实践。
在上一篇文章中,我们详细介绍了构建文本分类模块以更有效地处理客户请求的成功经验。在接下来的文章中,我们将继续介绍我们的客户服务平台中的另一个重要AI模块——QA排名,它用于对QA模块中的大量候选项进行排序,并选出最佳答案。
下图展示了客户支持平台的总体架构,并以橙色突出显示了问答(QA)组件。上一篇文章介绍了更多关于客户支持平台背景和架构的信息。
我们有很多Azure中国客户不断寻求帮助来解决他们遇到的技术问题(用中文描述),他们经常希望得到及时的支持。因此,我们打算设计一个QA模块,目的是为客户的问题提供尽可能多的准确答案(也是用中文),同时尽可能地减少人的干预。在我们最初的实现中,我们根据预先定义的对话流以及基于信息检索的文档搜索、索引和权重为用户提供答案。
遗憾的是,当我们开始处理这个问题时,QA模块返回的结果不是很令人满意。如果客户的问题属于预定义的对话流,那么提供的答案可能很有用。然而,在大多数情况下,预定义的对话流不能捕获客户提出的问题,所提供的答案也不是用户所期望的。
为了改善结果以获得更好的用户体验,我们决定尝试使用AI技术来帮助完成这项任务。利用NLP技术和深度学习相结合的方法是一个自然的选择。随着数据的累积,它们可以增量训练和演进。我们决定添加一个深度学习QA排名模块,从搜索引擎提供的候选答案中选择最佳答案。
针对我们的场景,我们采用了Analytics Zoo提供的内置文本匹配模型,并将其集成到我们的服务平台中。通过新添加的QA排名模块,根据基准测试结果和客户反馈,我们已经看到了显著的性能改进。在本文剩下的部分中,我们将与你分享在Intel Analytics Zoo中添加QA排名模块的一般步骤和实践经验。
为什么选择Analytics Zoo?
Analytics Zoo是一个开源的统一分析+人工智能平台,由英特尔开发,用于Apache Spark上的分布式TensorFlow、Keras和BigDL。该平台提供了非常丰富的功能支持,包括高级管道API、预定义模型、公共数据集上的预训练模型、参考用例等。我们之前使用Analytics Zoo成功集成了文本分类器模块,因此我们认为,Analytics Zoo是我们以及其他Azure大数据用户在Azure上构建端到端深度学习应用的一个很好的选择。有关Analytics Zoo的更详细介绍,可以参考本文。
什么是问答(QA)排名?
问答(QA)是一种常见的自然语言处理任务,它试图用自然语言自动回答人类提出的问题。在我们的场景中,我们的客户支持平台有一个FAQ文本和文档文章的集合,可以作为回答语料库使用,它试图从这些语料库中为用户的每个问题找到最佳的相关答案。这样的问题可以看作是一个文本匹配问题,我们可以创建一个模型来预测一个问题和候选列表中每个候选答案的相关度,然后对候选答案进行排序,并将得分最高的答案返回给客户。
与文本分类类似,文本匹配模型的训练也包括数据收集、训练和验证数据集的准备、数据清理和预处理,然后是模型训练、验证和调优。Analytics Zoo为我们提供了一个内置的文本匹配模型和Python及Scala语言的参考示例。有关文本匹配API和功能的更详细文档,参见此处。
数据收集和预处理
我们维护了一个整洁有序的候选答案和文章(均为中文)集合,每一项都有一个不同的ID。我们有一个从不同来源收集的用户问题的集合(也是中文),每个问题也分配了不同的ID。然后,我们让人标记出每个问题的最佳匹配答案。我们使用这些数据来训练用于QA排名的文本匹配模型。
问答语料库示例如下:
备注:实际内容为中文。原文作者把它们翻译成了英语。
对于数据加载,首先我们使用Analytics Zoo中的TextSet API把CSV格式的问答语料库加载到一个基于TextSet的、文本的弹性分布式数据集(RDD)中,用于如下分布式预处理:
1. from zoo.common.nncontext import init_nncontext
2. from zoo.feature.text import TextSet
3.
4. sc = init_nncontext()
5. q_set = TextSet.read_csv("question_corpus.csv", sc, partition_num)
6. a_set = TextSet.read_csv("answer_corpus.csv", sc, partition_num)
接下来,我们需要准备关系文件,表明问题答案对之间的相关性。一对标记为1(正)或0(负)的问答表示答案是否与问题匹配。由于原始的标签数据只有正标签,我们通过对每个问题的所有非匹配答案随机抽样,生成一个负样本集合。
我们为训练、验证和测试分别构建了手动和半自动的关系文件。每个关系记录包含一个问题ID、一个答案ID和一个标签(0/1)。关系示例如下所示:
CSV格式的关系也可以使用以下API轻松读取为RDD:
1. from zoo.feature.common import Relations
2.
3. train_relations = Relations.read("relation_train.csv", sc, partition_num)
4. validate_relations = Relations.read("relation_validate.csv", sc, partition_num)
下面的预处理步骤与我们在文本分类器模块中所做的非常相似。每个输入都需要经过符号化、从单词到索引的转换和序列对齐。有关详细信息,你可以参考前一篇文章中相应的部分。
Analytics Zoo中的TextSet提供了内置的操作,帮助我们非常方便地构建预处理管道。Analytics Zoo提供的原始实现只能处理英语。由于我们的数据是中文的,所以我们进行了修改,并利用jieba及自定义的标记将中文句子分成单词。代码的预处理部分是这样的 :
1. transformed_q_set = a_set.tokenize().word2idx().shape_sequence(q_len)
2. transformed_a_set = q_set.tokenize().word2idx(existing_map=q_set.get_word_index()) \
3. .shape_sequence(a_len)
4. word_index = transformed_a_set.get_word_index()
在内部,上述过程首先对问题语料库进行预处理。然后对答案语料库进行类似的预处理,不过是将新单词添加到从问题语料库获得的单词索引图中,使两个语料库共享相同的单词索引。上面的操作基于RDD,因此可以很容易地扩展并以分布式方式在大型问答数据集上执行。
模型定义和构造
对于文本匹配模型,我们使用Analytics Zoo中内置的K-NRM模型,该模型利用内核池技术来有效地获取排名。下面是K-NRM模型的架构:
输入查询和文档将首先经过一个共享嵌入层,该层通常使用预先训练的词嵌入向量作为其初始权重。随后的点层生成翻译矩阵,其中每个条目表示查询和文档中每个单词之间的相似性。RBF内核用于提取多级软匹配特征,然后是一个“学习排名(learning-to-rank)”层,它将这些软TF特征组合成最终的排名得分。有关详细信息,可以参考“带有内核池的端到端神经即时排名”一文。
K-NRM模型可以使用以下开箱即用的API进行构建:
1. knrm = KNRM(text1_length, text2_length, embedding_file, word_index=None,
2. train_embed=True, kernel_num=21, sigma=0.1, exact_sigma=0.001,
3. target_mode="ranking")
该模型的输入是问题索引序列以及答案索引,输出是它们之间的相关性分值。用户需要分别指定问题和答案的长度q_len和a_len。注意,对于词嵌入,该模型支持用于英语单词预训练的GloVe。同样,由于我们处理的是中文,所以我们选择并修改FastText作为中文词嵌入。参数word_index只是上面介绍的答案语料库TextSet生成的单词及其ID的映射。
是否对嵌入层进行训练是可配置的,实验结果表明,根据内核池的结果对词嵌入向量进行微调,可以获得更好的性能。你还可以指定使用多少内核和内核宽度。实际上,默认参数对于我们的数据集来说已经足够好了。
这实际上是一个多用途模型,它的target_mode可以是“ranking”或“classification”。你可以查看这个文档了解更多细节。
模型训练、评估和优化
现在,我们有了开始训练所需的所有要素。训练和验证关系、经过预处理的问答语料库TextSet,这些是我们训练文本匹配模型所必须的。
该模型可以按照上面介绍的两种target_mode值以两种方式进行训练。一种是将每个关系记录单独训练,作为一个二元分类问题,输出将是问题与答案相关的概率。另一种方法是联合训练一对记录,每对记录由同一问题的正关系(标签为1的关系)和负关系(标签为0的关系)组成,并优化两者之间的间隔。我们已经尝试了两种方法,并发现后者的表现更好。
Pairwise训练是以相同问题的一对关系作为输入。每对关系包含一个标签为1的关系和一个标签为0的关系。因此,在这种情况下,我们在K-NRM模型外封装了一个TimeDistributed封装器:
1. from zoo.pipeline.api.keras.models import Sequential
2. from zoo.pipeline.api.keras.layers import TimeDistributed
3.
4. model = Sequential().add(TimeDistributed(knrm, input_shape=(2, q_len + a_len)))
Analytics Zoo还提供了一个API,可以直接生成给定关系和预处理语料库的所有关系对,这些关系对的结果可以直接输入到模型中。
1. train_set = TextSet.from_relation_pairs(train_relations, q_set, a_set)
然后,我们使用便捷的Keras-Style API来编译和训练K-NRM模型。有一个损失函数RankHinge是专门为Pairwise训练提供的。损失函数hinge用于最大间隔分类,RankHinge是其方差,其目的是使正样本与负样本之间的间隔最大化。
1. model.compile(optimizer=SGD(learning_rate), loss="rank_hinge")
2. model.fit(train_set, batch_size, nb_epoch)
可调参数包括周期数、批大小、学习率等。用户还可以在训练期间获取快照,然后从快照中恢复训练。
排名模型的评价与训练有一点不同。基本上,对于每一个验证问题,我们都会准备一个正确的答案和一些错误的答案。我们想根据输出分数按降序排列所有候选答案。标签为1的得分越高越好。NDCG或MAP是评估排序任务的常用指标。Listwise评估的示例代码如下:
1. validate_set = TextSet.from_relation_lists(validate_relations, q_set, a_set)
2.
3. knrm.evaluate_ndcg(validate_set, k=3)
4. knrm.evaluate_map(validate_set)
你可以从日志控制台找到计算结果。NDCG和MAP都会给出0到1之间的值。如果指标接近1,那么最相关的答案应该排在第一位。你还可以在训练期间保存即时结果,并使用Tensorboard可视化损失曲线。如果度量指标相对较低,或者模型没有如预期的那样收敛,这表明模型性能不够好,我们必须对模型进行调优。这通常是一个反复检查数据质量、选择合适的训练超参数或调整模型参数的过程,直到得到满意的结果,然后训练好的模型就可以投入生产。
模型服务及发布
这部分与我们在前一篇文章中详细说明的文本分类器模块中所做的工作非常相似。我们在我们的服务中使用了类似POJO的Java推理API(更多细节参见这里)。由于QA排名中每个问答的预处理与文本分类器基本相同,所以这两个模块共享这部分的代码,这样便于维护。Analytics Zoo还提供了Web服务示例(包括文本分类和推荐)供我们参考。
随着我们不断收集用户反馈,我们会有越来越多的关系,我们会定期重新训练和发布更新后的排名模型。
小结
本文到这里就结束了。总结一下,本文演示了我们使用Intel Analytics Zoo在Azure大数据平台上成功构建QA排名模块的过程。你可以遵循我们上面的步骤,并参考Analytics Zoo提供的指南和示例,将其添加到你自己的应用程序或服务中!在本系列的后续文章中,我们将继续介绍在构建客户支持平台方面的更多实践经验。
要了解更多信息,请访问Github上Analytics Zoo的项目主页,你也可以下载并尝试在Azure市场上预安装Analytics Zoo和BigDL镜像。
作者简介
Chen Xu,微软高级软件工程师。他负责Mooncake Support Chatbot AI组件的设计和开发。
Yuqing Wei ,微软软件工程师,专注于大数据平台及相关技术。她致力于Mooncake Support Chatbot AI的开发。
Shengsheng (Shane) Huang ,英特尔高级软件架构师,Apache Spark提交者和PMC成员。她有10多年的大数据经验,目前在Apache Spark上的分布式深度学习基础设施和应用程序开发方面担任领导角色。
Kai Huang是英特尔公司的一名软件工程师。他的工作主要是在Apache Spark上开发深度学习框架,帮助客户在大数据平台上制定端到端的深度学习解决方案。
查看英文原文:Using Intel Analytics Zoo to Inject AI Into Customer Service Platform (Part II)