您是否曾经利用 Siri、Alexa 或者 Cortana 以对话方式设置闹钟、呼叫朋友甚至是安排会议日程?相信大多数朋友和我一样,感觉虽然这些方案在日常生活与工作中能够起到一定作用,但仍然很难与之谈论一般性、特别是哲学层面的话题。
通过自然语言与机器交互属于通用型人工智能方案的基本要求之一。这一 AI 研究领域被称为对话系统、口语对话系统或者是聊天机器人。在这类场景下,机器需要能够结合对话背景为用户提供翔实的答案,而且在理想情况下应实现与人类无异的沟通效果。
但在实践当中,最后一项要求往往很难达成。不过幸运的是,只要机器人能够切实提供帮助并且具备一定幽默感,人类用户就完全能够接受这样的对话方式。目前的对话系统主要分为两大类:面向目标型以及通用对话型。前者负责通过自然语言帮助人类用户解决日常问题,而后者则负责与人类交流以应对更为广泛的话题。
首先,我会以递归神经网络与单词嵌入作为起点,这意味着大家必须了解二者的概念与工作原理,进而跟上文章的讨论思路。如果大家对它们还不太熟悉,我在文末附上了相关教程,各位请各取所需、不用客气~
生成式模型与选择式模型
通用型对话模型主要分为两大类——生成式模型与选择式(或者叫排名式)模型。另外,目前也存在不少混合式模型。但最为常见的解决思路在于,这些模型会根据对话语境构想几条回应语句,并预测与情境相符的潜在答案。通过下图,大家可以明确了解此类系统的工作原理。
在本篇文章中,当我提及“网络消费单词序列”或者“将单词传递至 RNN”时,我所指的是将单词嵌入传递至网络——而非对单词 ID 进行传递。
对话数据表达的标注
在深入探讨之前,我们首先需要聊聊对话数据集的表现形式。以下提到的全部模型皆进行配对训练。其中的情景表现为回复之前的数个句子。该语句被视为从词汇中所获得的一条标记序列。
为了便于理解,下面来看表格内容。我们从两位对话者的交流内容中提取出三份样本:
这里需要注意每句末的“eos”标记。这一特殊标记能够帮助神经网络理解各句子的界限,从而更为准确地更新内部状态。
某些模型可能利用其它来自数据的元数据信息,例如对话者身份、性别以及情绪等。现在,我们开始讨论生成式模型。
生成式模型
在这里我们从最简单的对话模型起步,相关信息请参阅《神经对话模型》论文。
为了进行对话建模,该篇论文部署了一套序列到序列(简称 seq2seq)框架,其在神经机器翻译领域快速兴起并拥有相当出色的对话问题解决效果。这套架构包含两套配备有不同参数集的 RNN。我们将左侧的 RNN(对应 A-B-C 标记)称为“编码器”,而右侧的(对应 -W-X-Y-Z 标记)则被称为“解码器”。
编码器如何工作?
其中的编码器 RNN 一次构想一条情境标记序列,并对其隐藏状态进行更新。在完成对整体情境序列的处理之后,其会生成一项最终隐藏状态——此状态将包含情境意识并被用于生成答案。
解码器如何工作?
解码器的目标在于从编码器处获取情境表达并借此生成答案。为了实现这一目标,编码器 RNN 当中需要维持一个处于词汇之上的 softmax 分类层。在每一时间步长当中,该层会获取解码器的隐藏状态,并立足其词汇表中的所有单词输出一条概率分布结果。
以下为回复内容的生成方式:
解码器当中生成的回复,不过目前表达为公式而非单词形式。在这里,w_t 为时间步长 t 上的采样单词 ; theta 为解码器参数,phi 为密集层参数,g 代表密集层,p-hat 则为时间步长 t 条件下的词汇概率分布。
我们在生成回复时使用 argmax,其将在利用同一情景之下始终给出同样的答案。
以上描述的流程只是模型的推理部分,除此之外还有模型的训练部分,且后者的实现方式略有不同——在每个解码步骤当中,我们需要使用正确单词 y_t 而非生成的单词(w_t)作为输入内容。换句话来说,在训练过程中,解码器会消费正确的回复序列,但移除其中的最后一个标记并添加 标记。
解码器推理阶段示意图。上一时间步长的输出结果作为当前时间步长的输入内容。我们的目标是在每个时间步长中最大程度提升下一正确单词的概率。更简单地讲,我们要求该网络通过提供正确的前缀以预测序列中的下一单词。训练过程以最大可能性方式进行,而这会带来经典的交叉熵损失:
在这里,y_t 为时间步长 t 中的正确回复单词。
生成式模型的修改
现在我们对序列到序列框架已经建立起基本认知。那么,我们该如何为此类模型添加更多生成能力?这里通常使用以下方法:
生成式模型的问题
下面,我将整理出各类高人气实现方案的相关链接,大家可以利用其训练自己的对话模型。不过需要强调的是,大家在使用生成式模型时有可能遇到几种常见问题。
泛型响应
通过最大可能性方式训练出的生成式模型往往倾向于作出最为泛用的回复预测内容,例如“好的”、“不”、“是的”以及“我不知道”等等。大家可以参阅以下资料了解如何解决这些问题:
回复不一致 / 如何整合元数据
使用 seq2seq 模型时的另一大问题,在于其往往会在意义相同但表达不同的情境下给出不一致的回复内容:
目前最引人关注的处理方式在于“基于角色的神经对话模型”。作者为每段发言赋予对话者身份,并借此生成答案——其中不仅考虑到编码器状态,同时亦引入对话者嵌入因素。而对话者嵌入会在初始阶段即与模型本身一同进行学习。
通过这种方式,大家即可利用手头拥有的不同元数据对模型进行扩充。举例来说,如果您知晓对话的时态,则可借此推理时间并使用正确的时态生成回复内容。另外,您亦可在拥有相关训练数据集的情况下,有效调整回复方的个性或者回复属性。
具体实践
在文章开头,我曾提到过要为大家提供与 seq2seq 模型实现方案相关的各类框架选项,下面马上开始。
TensorFlow
Keras
论文与指南
选择式模型深度剖析
说完了生成式模型,接下来我们开始讨论选择式神经对话模型的工作原理。不同于估算概率 p,选择式模型需要学习另一项类似函数——sim,其中的回复内容为来自一套预定义潜在答案池的元素之一。总体来讲,该网络会将情景与一条候选答案作为输入内容,而后返回二者之间适用性的置信度结果。
选择式(或称为排名式,或 dssm)网络由两项“塔式”因素组成:其一为情景,其二为回复。每项塔式因素都可能拥有您所需要的架构。塔式因素提取输入内容并将其嵌入至语义向量空间内。接下来,其计算情景与回复向量间的相似性,即使用余弦相似度公式
C^T*R/(||C||*||R||)。在推理阶段,我们可以计算给定情景与全部可能答案之间的相似度,并从中选择相似度最高的答案。为了训练选择式模型,我们使用三元损失函数。三元损失函数通过三项因素定义,即情景、回复_正确、回复_错误,即:
选择式模型中的三元损失函数。其与 SVM 当中的最大边界损失非常类似。那么 reply_wrong 是什么?其亦被称为“负”样本(reply_correct 相应被称为‘正’样本),且在最简单的情况下,其为答案池中的随机回复。因此,通过尽可能降低这一损失值,我们将能够对非正确绝对值进行排名的方式获得相似度函数。不过需要注意的是,在推理阶段,我们只需要比较所有回复的评分结果并选择评分最高的选项。大家可以点击此处通过微软项目页面深入了解 DSSM 的更多相关信息。选择式模型的开源实现方案不像生成式模型那么丰富,但大家仍然可以点击此处参阅在 TensorFlow 上实现选择式模型教程。
选择式模型中的采样模式
大家可能会问,我们为何要从数据集中提取随机样本?为什么不使用更为复杂的采样模式呢?问得好。如果进一步观察,大家就会意识到三元组的数量为 O(n3),因此最重要的是选择负属性,因为我们无法对全部数据集内容进行处理。
生成式对选择式:优势与劣势
说到这里,我们已经了解了生成式模型与选择式模型的工作原理。不过哪种类型更适合您的实际需求?以下表格也许能够帮助大家作出正确的选择。
最困难的部分在于评估
最重要的问题之一,在于如何评估神经对话模型。目前我们可以使用多种自动化指标以通过机器学习技术进行聊天机器人评估:
不过最近的部分研究工作表明,上述指标与人类在特定情景下对回复内容的适当性判断并无关联。
举例来说,假设您面对的问题为“Statsbot 是否在阐述我们处理数据的方式?”而数据集内存在“当然是。”这条回复。但您的模型却在这样的情景下给出了其它回复内容,例如“绝对是的。”以上提到的各项指标都会给这样的答案打出很低的评分,但我们可以看到,这条答案跟数据集中的选项一样正确无误。