上一期,我们介绍了让一台机器人开口讲话,需要下面3个步骤:
1. 准备对话数据
2. 搭建seq2seq模型
3. 训练模型,并预测聊天效果
并且,使用“字典”和“语料”,我们已经完成了第1步准备的工作。
感兴趣的同学,可以戳这里:《 keras教程:手把手教你做聊天机器人(上) 》
这一期,我们来构建机器人最核心的部分:seq2seq模型
下面,我们就开始啦~~
如果我问你:“今天的心情如何?”
你会如何回答我?
“好”? “不好”? “还不错”? ……
不管哪种答案,在回应之前,你的脑海里,都会不经意间闪现这样几个片段:
听到问题 - 理解问题 - 组织语言 - 回答问题
让我们来具体看一看:
首先,你的听觉系统会捕捉到我的问题。
接下来,你的大脑开始快速运算,试图理解问题。
然后,开始组织语言,寻找合适的措辞,以便能准确表达自己的感受。
最后,你选择了一个最为满意的答案,回答了我刚刚的提问。
大脑就是这样,一步一步引导我们说出答案。
同样的,让一台计算机“学会聊天”,也需要经历4步。
只不过,我们使用更为专业的词汇来描述:
输入问句 - 编码 - 解码 - 输出答句
如下图:
此处,“输入问题 - 编码 - 解码 - 输出答句”就构成了一套完整的seq2seq模型。
如果抛开晦涩的专业术语,可以简单地理解为:
“编码”—— 计算机在尝试“读懂”你;
“解码”—— 计算机在努力“表达”它自己。
下面,我们将逐一剖析各个环节。
假设仍以该对话为例:
● 第1环节 —— 输入问句
仿照我们人类的对话过程:
如果,我想让你回答我的问题,首先,我得先让你听到我的讲话。
那么,如何让计算机也“听到”我们的提问呢?
如果以“ 绿色圆圈
”代表汉字,在seq2seq中,问句可以被直观地描绘为:
是不是很简单?
进一步地,如果我们用3个数字来代表一个汉字,
例如:
那么,输入问句的形态将为:
需要注意的是,如果你对“由数字构成的汉字”并不了解,建议回顾上节课的内容:《 keras教程:手把手教你做聊天机器人(上) 》,里面有一个非常重要的概念——词向量,需要你掌握。
此处,只需要记住上图的形态,就可以了。
● 第2环节 —— 编码
在我们回答同伴的问题之前,一定会先搞明白对方说了什么。
同样的,计算机在输出答句之前,也会先“搞清楚”人类到底问了什么。
“编码”过程,实际上就是算法探求问句含义的过程:
图中:
绿色圆圈
代表输入的文字;
橘色圆圈
代表输出的问句含义;
灰色方块
代表一套RNN或LSTM算法。
这里又涉及到另外一个概念——RNN。
之前,我们用了3篇文章,详细阐述了RNN的适用范围、运行原理,以及它的变体-LSTM的运行机制。
未学习的同学,可以翻阅RNN系列教程:
《股票预测,自动翻译,你想要的它都能做——RNN算法探索之旅(1)》
《股票预测,自动翻译,你想要的它都能做——RNN算法探索之旅(2)》
《股票预测,自动翻译,你想要的它都能做——RNN算法探索之旅(3)》
在这里,你仅需要记住编码的结构,见下图。这个结构,在后面编写代码时,会用得上。
● 第3环节 —— 解码
当我们理解了同伴提出的问题后,大脑就开始高速运转……
我们可能会不断地组织语言,寻找着最佳措辞,以便能更准确地表达自己内心的感受。
模型的“解码”过程,也是计算机学习“表达”自己的过程。
在这个过程中,算法会根据问句的含义,来推测较为妥帖的回答:
将“编码”和“解码”衔接到一起:
可以看到,算法在努力寻找答句中的最佳措辞:
“哪个汉字,能作为答句中的第1个汉字?
哪个汉字,能作为答句中的第2个汉字?
……”
一旦该工作完成,我们就能得到来自计算机的回应:
读到这里,希望你对模型的结构,已经有了大体的了解。
在keras中,使用4行代码就可以搞定上图:
● 第1行:model = Sequential()
相当于搭建一个空容器:
我们会向容器添加“网络层”。
如果暂不考虑“输入问句”和“输出答句”,之前我们构建的模型,一共含有3层(如蓝色箭头所示):
第1层和第3层,均采用的是 RNN(或LSTM)算法:
第2层的“橘色圆圈
”,含有问句的含义,因为要传递给下一层使用,所以,在此处我们将其进行复制(如图中橘色箭头所示):
将3层网络写成代码,即为:
补充完整每一层代码:
● 第1层
这里涉及一个概念——“词向量维数”。
在开篇我们提到,每个汉字由若干个数字组成:
以第1个汉字“心”为例,它由数字[ 0.063, 0.028, -0.121 ]构成。
因而,它的形态可以被精确地表述为:
这里的小圆圈个数,即为“词向量维数”。
代码中有这样一句: input_shape=(句子中的汉字个数, 词向量维数)
在我们的例子中:
汉字的个数 = 4
词向量维数 = 3
因而, input_shape = (4, 3)
实际上,除了汉字外,模型第1、2、3层的内部,均由若干个圆圈(即“神经元”)构成,如下图:
(假设灰色方框中的神经元个数,与词向量维数相等,也为3)
将第1层代码补充完整,即为:
温馨提示:
在代码中,return_sequences 表示“输出的结果是否为序列”。
举个例子:
如果你正在讲话,刚说一半,我就猜出你后面要讲的每一个字:
此时,“对/面/甲/方/的/狂/野”就是一个“序列”。
因为,此时我更关心“你要讲出的每一个字,以及字与字之间的顺序关系”。
相反,如果你正在讲话,等你把话说完,我从中捕捉出大致的意思:
那么,此时的句义--“鸡汤”,类似于一个“标签”,它是作为一个整体而非序列来存在的。
回到我们的例子中,
如果return_sequences = True,那么,模型的形态是这样的:
而如果return_sequences = False,那么,模型的形态就是这样的:
针对编码层,我们更关心问句的含义,而不是输出的具体文字,故 return_sequences的取值为False。
● 第2层网络
RepeatVector表示“对问句的含义,进行复制”:
要复制多少份?
通常情况下,我们会限制一句话的最大长度。比如,一句话不超过15个汉字。这里的15,就是句子的最大长度。
我们需要复制的“份数”,刚好等于这个“句子的最大长度”。
在我们的例子中,假定答句长度为3,那么,在第2层就需要复制3份,即 RepeatVector(3)。
温馨提示:
句子的长度,由个人来设定。
● 第3层网络:
第3层与第1层的主要区别在于:return_sequences的取值。
因为,我们要获取答句中的每一个文字,故此处return_sequences的取值为True:
将全部过程整合起来,即为:
至此,seq2seq模型的核心部分,我们就搭建完成了。
剩下的工作仅仅是常规的编译和训练模型,完整代码可以在后台(微信公众号:AI传送门)回复“聊天机器人代码”来获得。
最后,有一点需要特别说明:
本文的模型及案例,已经做了简化处理。
标准的seq2seq模型,形态如下:
可以看到,比文中所描绘的模型结构要更为复杂。作为入门,了解到文中所呈现的结构就可以了。但后期要做深入学习,就需要了解到该模型了。感兴趣的同学,可以在后台(微信公众号:AI传送门)留言给我们,我会根据大家的需求,酌情展开此部分内容。
最后,祝愿每一个人,都能拥有一台属于自己的聊天机器人,分享你的喜悦,解你的忧愁。