这一年来的工作

今天正好是我的birthday :),也好对这一年来做的工作来一个总结。
我把研究生最美好的一年时光给了End2End,但却还是没有得到太多回报。直到现在我依然不看好端到端对话系统这个方向,因为这个方向现在问题实在太多了,很多问题也许本身跟对话系统无关,但却很大程度上影响了端到端对话系统的发展,同时这些问题也暴露出了现有的机器学习模型框架或者算法的一些弊病。
下面主要按以下大纲进行总结

过去工作总结

  • Baseline-1
  • HRED+Reinforcement Learning
  • Variational Encoder-Decoder
  • Baseline-2
  • Results

对任务的分析和一些看法

=================================我是分界线=======================================

Baseline-1

Figure 1: Baseline-1 模型架构

figure1所示就是baseline-1的模型架构图,底层是一个基于LSTM/GRU的编码器,顶层也是一个基于LSTM/GRU的解码器,解码器每个时刻都另外会有一个attention向量作为输入。

HRED+Reinforcement Learning

15年的时候有两篇论文:”A Hierarchical Recurrent Encoder-Decoder for Generative Context-Aware Query Suggestion”和”Building End-To-End Dialogue Systems Using Generative Hierarchical Neural Network Models”,提出了一种层次化编解码模型(HRED),这种层次化编解码模型(HRED)相比于之前的编解码模型(Encoder-Decoder)来说,最大的优势就是它能够对上下文建模,从而实现多轮对话。

Figure 2: 层次化编解码模型图

如上图figure 2所示,这种层次化编解码模型比普通的编解码模型多了一层context layer,通过context layer就能实现对上下文信息的编码,从而实现多轮对话,在解码的时候,context layer的输出会作为解码器的输入,解码器根据上下文信息编码向量解码出相应的response。这种做法的一个好处就是它能够丰富编码信息,使得编码信息不仅仅包含当前输入句子的语义信息,还包含了历史输入句子的语义信息,这种丰富的上下文编码信息对解码器来说更能准确地解码出相应的response。基于层次化编解码模型的优越性,我们采用它作为引入强化学习(Reinforcement Learning)的策略网络(Policy Network)

强化学习(Reinforcement Learning)是一种基于经验和试错(trial and error)的学习方法,它通过跟环境(environment)交互,学习得到一个在每个状态(state)下由策略(policy)所选择的动作(action)是能够得到累积回报(cumulative return)最多的最优策略(optimal policy)。它通常可以用马尔科夫决策过程(MDP)来建模。一般的马尔科夫决策过程(MDP)由一个五元组<S, A, r, γ, T>组成,其中S代表所有状态集合(states set)A代表所有动作集合(actions set), r代表奖励函数(reward function),通常由环境(environment)根据当前stateaction决定,γ代表折扣因子大小,是一个介于01的实数,用来表示将来的动作回报对当前时刻获得的累积回报(cumulative return)影响有多大,T代表状态转移概率矩阵,矩阵中P(s_{t+1}=s'|s_t=s,a_t=a),表示在当前状态s_t=s下,执行动作a_t=a,跳到下一个状态s_{t+1}=s’的概率是多少。

我们通过把每个时刻解码器(Decoder)的选词动作当做策略网络(policy net)需要去学习的策略。具体地,我们选用了强化学习里面的Reinforce算法。Reinforce算法首先会采样得到一个完整的预测单词序列,然后我们根据采样得到的预测单词序列由奖励函数(reward function)计算出奖励(reward)是多少,从而计算出这个预测单词序列里每一时刻能够得到的累积回报(cumulative return)是多少,然后再根据这些累积回报(cumulative return)去更新我们的策略网络(policy net)

上面的公式(1)就是采用Reinforce算法设计得损失函数(loss function),其中Θ是策略网络(policy net)的参数,Q(s_t, a_t)代表在状态s_t下执行动作a_t能够获得的累积回报(cumulative return),计算公式如公式(2)所示。最后我们希望通过最小化损失函数L(Θ)来训练得到一个好的策略网络(policy net)

但是我们很快就发现了这个模型存在的一些问题。首先,它的动作搜索空间(actions search space)特别大,跟决策序列的长度成指数级增长关系,由于动作集合(actions set)是整个词表大小:24789,所以如果决策序列的长度是T的话,那整个动作搜索空间大小就是24789^T,这几乎是个天文数字,同时由于很难采样得到一个合理的预测单词序列,所以奖励信号也是稀疏的(reward signals are sparse),这样就导致策略网络(policy net)很难去学到一个好的策略(policy);其次,没有一个很合适的环境(environment)去针对策略网络(policy net)选择的动作序列(actions sequence)给出一个合理的回应(response),在这里主要是奖励信号(reward signals),如何去构建或模拟一个合适的环境(environment)也很困难,一个主要原因是目前还没有一个通用的和合理的评价标准(metric)去评估回应(response)的合理与否。这两个问题在很大程度上影响了模型的性能。同时,在训练的过程中,我们发现层次化编解码(HRED)模型很容易出现梯度消失(gradient vanishing)的现象。有人把两句话拼接后输入给编码器(encoder),再把编码之后的向量输入给解码器(decoder)进行解码,最后发现这样做的效果和用层次化编解码(HRED)模型效果差不多,可能还要好一些,并且不容易出现梯度消失(gradient vanishing)的现象。虽然层次化编解码模型本身存在一些问题,但并不能否认它相比于普通的编解码模型(Encoder-Decoder)还是有优势。由于循环神经网络(RNN),包括后面改进过的LSTMGRU,在实践中都不能很好地对长句子序列进行编码,句子序列越长,丢失的信息也越多,所以如果在这种情况下想要去引入上下文信息(context information)的话,层次化编解码(HRED)模型就比普通的编解码模型(Encoder-Decoder)更加合适和高效。

Variational Encoder-Decoder

在想到用变分方法(variational method)之前,我们更多的是从模型身上去思考如何设计和实现一个端到端对话系统,而不是从对话过程本身上面去思考。后来我们把注意力转移到了对话过程本身,发现人跟人之间的对话都有一个“主题”(topic),并且整个对话过程始终围绕着这个“主题”进行,中间可能会有“主题”的转换,但这是另一个问题了。因此,我们想到可以引入一个隐变量(latent variable),让这个隐变量去学习表示我们所说的“主题”(topic)

整个推导过程天衣无缝,我们引入了隐变量Z,使得Z表示对话过程中的“主题”(topic),从上面的公式推导可以看出,最后我们需要优化两项,一项是传统的交叉熵损失函数(cross entropy loss function),另一项是KL散度损失(KL divergence loss)KL散度(Kullback–Leibler divergence)是一种衡量两个分布的逼近程度的一个度量标准(metric),但不是一种距离度量标准,因为它是非对称的。上面的损失函数(loss function)与之前普通的编解码模型(Encoder-Decoder)损失函数相比,多了KL散度损失,它的作用是使得先验概率分布P(Z|X)能够尽量逼近后验概率分布q(Z|Y),这样,从直观上我们就能解释隐变量Z的物理意义:Z是第一句话X和第二句回应Y(response)之间共有的一些东西,也就是我们之前提到的“主题”。

Figure 3Variational Encoder-Decoder模型图

figure 3所示,我们用到了两个神经网络:先验神经网络(prior network)和后验神经网络(post network)去分别拟合先验概率分布P(Z|encode(U1))和后验概率分布q(Z|encode(U2))。训练的时候会使得先验神经网络(prior network)去逼近后验神经网络(post network),即使得KL散度(Kullback–Leibler divergence)减小;同时每次会从后验神经网络中去采样得到隐变量Z,再把Z和编码器(encoder)编码得到的信息向量一起输入给解码器(decoder)

在训练的过程中,我们发现虽然模型架构(model architecture)和损失函数(loss function)本身没有什么问题,但模型却很难训练,主要难点在于没法很好地控制KL散度(Kullback–Leibler divergence)的大小,后来我们修改了原来的损失函数,用一个影响因子去控制训练的过程中模型更倾向于学习一个小的交叉熵损失值(cross entropy loss)还是去学习一个小的KL散度值(KL divergence value),修改后的损失函数为:

L(Θ)=(1-α)*CE_LOSS+α*KL_LOSS

整个训练过程我们会去动态调整影响因子α的大小,在训练的初始阶段,通过把α设小一点,使得模型主要去训练学习得到一个小的交叉熵损失值CE_LOSS,在训练的后面阶段,会逐渐增加α的大小,使得KL散度值减小。这样来动态调整影响因子α的理由是,在训练的初始阶段,我们更加希望模型能够去学习得到一个好的编码器(encoder),解码器(decoder)和隐变量Z表示,在训练的后面阶段,当模型已经学到一个不错的隐变量Z的表示之后,开始增加影响因子α的大小,从而使得先验概率分布P(Z|U1)不断去逼近后验概率分布q(Z|U2)。后来的实验结果,也证明了这种动态调整影响因子α大小的训练方法的有效性。

虽然通过设置一个影响因子α,以及动态去调整影响因子α的大小,在一定程度上确实提升了模型的性能,但是模型的性能依然很差。为了找出这其中的原因,我们更进一步分析了其中的原因。主要做的工作就是,通过把隐变量Z可视化之后,分析模型学习得到的隐变量Z是否合理。具体地,我们通过把训练过程中的先验神经网络(prior network)学习得到的隐变量表示Z和后验神经网络(post network)学习得到的隐变量表示Z保存到本地,然后通过一些可视化技术将Z打印出来。

Figure 4:先验隐变量Z和后验隐变量Z的可视化效果

figure 4所示,先验神经网络(prior network)学习得到的隐变量Z和后验神经网络(post network)学习得到的隐变量Z大部分都聚集在一块儿,并且大部分先验隐变量Z和后验隐变量Z都没有成对出现(说明它们的分布并没有非常逼近)。从可视化的结果来看,模型并没有学习得到一个好的隐变量Z的表示。

Baseline-2

为了更好地解释和对比变分方法(variational method)的有效性,我们特意设计了另一个Baseline,姑且把它称作Baseline-2,它跟上面的Variational Encoder-Decoder模型相比,只少了后验神经网络,体现在损失函数(loss function)上面就是少了一项KL散度(Kullback–Leibler divergence),虽然它也有先验神经网络(prior network),但是在这里只是单纯地把先验神经网络看做是一层普通的神经网络,没有其他含义。

Figure 5: Baseline-2模型图

Baseline-2具体的模型结构图如figure 5所示。

Results

下面是上面提到的三个模型:Baseline-1Baseline-2Variational Encoder-Decoder在基于twitter语料(corpus)上面的训练结果。主要评价标准(metric)BLEU值,它是一种常用的机器翻译任务(machine translation task)里的评测方法。

Model

BLEU value

Baseline-1

0.249

Baseline-2

0.251

Variational Encoder-Decoder

0.260

Table 1: 各种模型评测结果

========================================================================================

对任务的一些分析和看法

这部分主要是个人对端到端对话系统的理解,以及对现有问题的一些分析,并且会给出一些可能的解决方法。

其实并不看好端到端对话系统这个方向,因为这个方向现在问题实在太多了,很多问题也许本身跟对话系统无关,但却很大程度上影响了端到端对话系统的发展,同时这些问题也暴露出了现有的机器学习模型框架或者算法的一些弊病。

首先对上面提到的模型遇到的问题作一个总结:

HRED模型存在的问题

训练和调试困难,容易出现梯度消失现象,但是如果想直接对两句话进行拼接,输入给编码器(encoder),从而达到引入上下文信息(context information)的目的,则会存在序列长度过长导致编码信息遗失的问题。

RL在End2End框架下遇到的问题

强化学习(Reinforcement Learning)本身是一种经验和试错的算法(trial and error algorithm),特别适合在没有大量标注语料以及有一个很强的交互环境(environment)的情况下使用,但是如果在有大量标注语料的情况下使用强化学习就有点得不偿失了,因为强化学习能够工作(work)的原因就是,它需要大量跟环境(environment)交互的轨迹(trajectory),通过这些轨迹来学习到一种策略(policy),使得在某个状态(state)下由策略执行某个动作(action)后能够得到的累积回报(cumulative return)最多。而对于对话任务而言,虽然没有大量高质量的语料(corpus),但是针对目前收集到的数据量而言,更适合把它看成是一个监督学习任务(supervised learning task),更重要的是,对于对话系统而言,构建一个强大的可交互环境(environment)太难了,甚至对于评测对话本身也没有一个真正有效和通用的标准(metric)

同时,在端到端的对话系统下强化学习还面临着计算复杂度,动作搜索空间太大等问题。

 变分方法(variational method)存在的问题

变分方法在思想上没有任何问题,但是我觉得是受到深度学习(deep learning)的影响,由于深度学习模型经常很难训练,而且往往中间的隐层变量几乎没有可解释性,从而导致它不能发挥出自己的性能。

另外,上面的模型都会有倾向预测高频词的现象发生,具体拿Variational Encoder-Decoder模型来讲:

Figure 6: 单词在日志以及训练语料里的词频统计信息

figure 6可以看出,模型预测的单词词频基本上跟它在训练语料里出现的词频成正比。也就是说,模型的解码器(decoder)比较倾向于预测一些高频词汇,而这也是大部分深度学习模型所遇到的一个问题。

通过上面的描述,如果不算上强化学习在端到端对话系统里面遇到的问题的话,基本上其他所有的问题都跟深度学习(deep learning)有关。具体的,它有以下几个问题:

  • 难训练
    • 梯度消失(gradient vanishing)
    • 解码器(decoder)的性能
  • 解释性差
    • 中间隐层变量可解释性差
    • 编码器(encoder)的输出

对于梯度消失(gradient vanishing)问题,往往跟模型内部选的激活函数有关,这方面不太了解,有没有什么好的方法或技巧可以某种程度上克服梯度消失的问题。

解码器(decoder)倾向于预测高频词汇是很关键的问题,它跟训练语料有关,所以一种可能的解决方法就是对语料做处理,比如data transform,另外一种方法是通过某种技巧训练得到一个更好的编码器(encoder)和解码器(decoder)。其实我们可以想象为什么解码器会倾向于预测高频词汇,因为高频词汇对模型参数的调整作的“贡献”越多,所以导致整个模型大部分时间都“服务”于高频词汇,通过梯度反向传播算法(BP algorithm),解码器(decoder)包括底层的编码器(encoder)的参数都是为了使模型能尽可能多的预测对这些高频词汇,最后使得编码器和解码器都没有得到充分训练,所以我们可以预料,编码器的输出其实可能是有某一种模式(pattern)的,这里的模式指的是在某一些维度上面,无论输入的句子是什么,它编码得到的向量在那一些维度上面的值都是正的或负的,只要编码器输出的向量满足这样一种模式的话,那它输入给解码器之后,解码器最后给出的在整个词表上的概率值一定是倾向于高频词汇的。后面我会把解码器中跟高频词汇连接的参数以及跟非高频词汇连接的参数通过一些方法打印出来,观察它们的大小关系,因为现在我猜测,那些跟高频词汇连接的参数数值要远比跟非高频词汇连接的参数数值要大,同时,我也会把编码器编码得到的向量通过一些方法打印出来,观察它们是不是满足一些模式(pattern)

以上就是这一年来我的工作,中间经历了很多低潮,踩了很多坑,也曾想过放弃,希望对大家有所帮助,也希望越来越多的人能够投入到真正有价值的研究上面。我总觉得现在很多人所谓的研究其实都是在解决一个工程上的问题,而不是本质上的问题,无论是deep learning本身还是具体到端到端对话系统这种应用场景里面,大家似乎都没有去关注底层的本质问题的研究。好了,就这样吧!顺便祝Jorbe生日快乐! :)

发表评论

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

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>