- 前言:
员工Bot是e成科技一款服务于企业内部员工的机器人助理产品。其中,自动解答员工频繁会问到的业务知识类问题是员工Bot的核心应用场景,借助员工Bot可以显著的减少HR日常重复性工作。
本文主要讨论自然语言处理算法在员工Bot场景下的应用,其核心是短文本(问题)的相似度匹配。这是一个自然语言处理领域成熟的方向,有很多经典方法,但随着近些年来深度学习的进展,效果更好的新方法也在不断涌现。作为一名NLP领域的算法工程师,一方面需要追踪最新NLP领域的最新研究进展固然重要,同时也必须结合实际情况,探寻和落地可行的方案。
- 方案选择:
在员工Bot场景中,产品经理基于业务场景收集人力资源场景的FAQ知识库,包含人力资源领域员工经常提出的问题和对应的解答。算法需要根据用户的提问匹配到知识库里面最合适的那一个答案,并判断是否进行回答。在这个场景中,知识库是垂直领域的,它的大小取决于这个业务场景需要支持的范围有多大,一般来说问题对(问题-答案)的数量都在几百到几千不等。从技术上说,上述问题可以抽象成一个文本与文本的相似度匹配问题,下面我们给出基本的技术方案:
召回方案
考虑到模型的负载和延时情况,用户的问题的内容并不会和语料库中的所有问题进行匹配,而是提前将语料库中的问题进行索引,并先进行粗粒度的相似召回,然后再用精细化的匹配模型去计算最相似的那个问题。粗粒度的索引常见的方案有:(1)基于词的倒排索引(Inverted Index);(2)基于稠密向量的向量召回。两种方法都能实现粗粒度的召回,但是倒排索引需要构建有效的索引词表,因此需要根据应用场景调整词表。而基于向量召回的方法,只要确定构建稠密向量的方法,就可以用Faiss[1]或者annoy[2]等工具索引起来,在牺牲少量精度的情况下,高效地完成问题的召回。本文最后采用的方案:基于文本中词的IDF(Inverse Document Frequency)值,获得加权句向量(Sentence Embedding),然后用annoy工具,将数据库中的问题集索引起来,实现粗粒度的相似问题召回。
传统的文本匹配方法
我们分别调研了传统的文本匹配方法和深度学习方法,比较了两种方法的优点和不足。传统的BM25/Jaccard/Cosine Similarity 等基于词匹配的模型都具有表示方法简洁、运算方便的特点,解决了词汇层面的匹配问题。另一方面,基于词匹配的模型也有一定的局限,如一词多义、同义词关联以及语序问题。举例来说,同样是想知道公司的位置,“公司位置”和“办公地点在哪儿”这两个问题的意思完全一致,但是字面上没有任何的重叠,用传统文本匹配方法来计算,他们的相似度都是0。文本匹配模型需要解决这种在词袋层上虽然没有overlap,但是语义层面是相似的文本匹配问题。
深度学习文本匹配的方法分类
深度学习的蓬勃发展为我们提供了新的思路,基于神经网络训练出来的词向量(Word Embedding)来进行文本匹配的计算获得了大家的一致认可,就像在问答系统里大家默认将 query与question进行匹配一样,在深度学习模型中加入预训练的词向量是“默认”的选项。
基于深度学习的的文本匹配方法主要分为两类,一类是Representation-based模型,这类方法先分别学习出query和question的句向量表示,然后用两个向量做余弦相似度计算或者连接多层感知机(MLP)得到最后的匹配分,重点是学习query和question对应的句向量表示;另外一类是Interaction-based 模型,这类先构建匹配矩阵(Matching Matrix),然后利用匹配矩阵学习一个匹配函数,最后连接多层感知机输出匹配分,重点是匹配函数的学习。
图一:问题相似度匹配模型总结
- 技术演进:
深度学习匹配模型
经过最初的第一轮调研后,我们确定采用深度学习方案。而在模型的选择上,我们一开始选择了在各大赛事中评价很好的representation-based 的孪生网络(Siamese Network)模型(也叫“双塔”模型)。具体的结构实现我们参考的是Paul Neculoiu等人在2016年发表的工作(Learning Text Similarity with Siamese Recurrent Networks[3]),模型的结构如下所示:
图二: “双塔”模型结构
基本方案流程是:构建query和question的文本pair,通过embedding layer生成词向量矩阵,这两个词向量矩阵分别通过神经网络计算得到句向量。有了句向量之后,在匹配层进行相似度计算,实际中最常用的就是cosine函数,或者连接一个多层感知机(MLP)网络,输出最终的匹配分。
完成模型的搭建和训练之后,通过测试集的测试,我们发现模型的效果完全没有达到预期,模型基本上是无法工作的状态。分析主要原因在于有标注数据过少,导致模型过拟合严重,效果无法达到预期。在短期内无法得到足够标注资源的情况下,我们不得不求助于不依赖大规模标注样本的传统文本匹配方法。
传统文本匹配模型
构建传统的文本匹配模型,需要人工的设计才能保证一个不错的效果。因为构建的模型就是直接用来做预测的,因此特征以及特征的参数选择会决定最初模型的可用程度。除了文本的原始特征(TF/IDF等)之外,还有传统的Jaccard/BM25 (BM:Best Matching)信息匹配特征[4],以及WMD(Word Mover ‘s Distance)/余弦相似度(Cosine Similarity)来构建组合文本匹配方法;
其中 BM25/Jaccard/WMD 是一系列基于文本之间词表重合度的评分函数,只是不同函数之间侧重点和参数不同。CosineSimilairy 是最为常用的余弦相似度。ai 是不同的评分函数的参数,因为参数较少可以直接通过手动调试的方式获得最佳可用的值。
文本匹配模型优化
针对前面讲到的传统匹配方法存在的问题,我们也进行了改进工作。比如,通过对大量的平行语料进行统计分析,构建同义词表和多义词表。然后基于同义/多义词表,改进分词的效果,同时对训练集进行扩展或者对训练集进行同义词替换(同义词用统一的标识符表示)的方式,显著的改进了匹配算法的效果。
优化后的传统信息匹配模型,在匹配效果上远远超过了深度学习模型,基本能够达到业务方的要求。同时模型计算性能也大大提升,模型也更具有可解释性。这给之前非常迷信最新深度学习算法的我们也很好地上了一课,新方法并不是总比旧方法好,关键在于结合场景选择合适的方法。
但随着业务的发展,我们也发现随着语料的增加,同义词、相关词及人工规则也要随之增加也调整,使得整体的逻辑变得复杂,增加了很多工作量。在传统的匹配方法优化到了瓶颈之后,我们希望重新使用深度学习学习模型。
深度学习模型进一步探索
图二和图三显示了深度学习匹配模型中Representation-based框架和Interaction-based框架。从图中可以看出模型的差异主要在于是否直接得到句向量及匹配层的实现方式。Representation-based的主要目的是尽可能的将输入层的 query 和 question 学习到充分表示的句向量,然后进行匹配计算。但这需要大量语料的支持,这在特定的垂直领域并不容易获得。而Interaction-based模型,首先构建query和question在词粒度的匹配矩阵(或张量),然后将这个匹配矩阵(或张量)输入到预测函数中得到最终的相似度。相比于Representation-based模型,Interaction-based模型的预测函数只需要输入抽象的匹配矩阵,与语料的领域无关。
因为我们选择采用无监督的方式构造交互矩阵,并利用其他领域语料训练预测函数。这样既可以获得充足的训练语料,又可以避免不同领域之间的鸿沟,本质上属于一种改进的迁移学习方法。具体在Interaction-based模型中我们采用了K-NRM[5],主要出于计算效率和模型效果的考虑。该方法对于 query中的每个term计算它在question中的匹配信号,计算整体的匹配强度的分布即离散化分桶,统计在每一个桶上的次数,这样就可以得到一个关于query中每个term和question匹配分的一个直方图,即一个向量。再通过全连接层学习到最终的匹配分。K-NRM模型结构如图三所示。
图三 K-NRM模型结构
经过实际测试获得了令我们惊喜的结果,在不做任何调优的情况下,模型在测试集上分类任务的准确率就达到了65%。模型的实际表现验证了我们开始的猜测,为后续优化提供了空间,同时也为更加复杂的组合模型提供了探索基础。
传统模型和深度学习模型的融合
除模型算法的调研以及本身的优化改进之外,同时我们将传统的匹配模型的特征融合和深度学习中间隐层网络进行拼接,实现了传统文本匹配方法和深度学习模型的融合(如图四所示),进一步提升了模型效果。我们将组合模型在上面同样的开源中文训练集上进行训练,在同样的测试集中,准确率直接提高到了81%。而这样的结果,不仅说明融合模型的有效性,也验证了我们的探索方向。
图四 改进后的K-NRM模型结构
- 总结
回顾整个项目过程,我们经历了深度学习方法到传统文本匹配方法,到深度学习算法,最终到深度学习算法与传统文本匹配方法结合的过程。在这个过程中,我们对业务及不同算法的理解也上了一个台阶。针对文本任务的特点结合实际应用场景,除了从深度学习模型更好地设计选型之外,也可以将一些传统的文本匹配技术更好地和模型融合,更高效地获取更好的效果。
- 参考
[1] A library for efficient similarity search and clustering of dense vectors
[2] Annoy (Approximate Nearest Neighbors Oh Yeah) is a C++ library with Python bindings to search for points in space that are close to a given query point.
[3] Learning Text Similarity with Siamese Recurrent Networks
[4] 算法导论 第三版 Thomas H.Cormen , Charles E.Leiserson,Ronald L.Rivest, Clifford Stein