文本生成seq2seq框架

文本生成seq2seq框架

1. 概述

Seq2Seq是Sequence to Sequence的缩写,作用是将一个序列(sequence)映射成另一个序列(sequence)。文献[1]和文献[2]分别提出利用深度神经网络DNN实现端到端的Seq2Seq学习,将Seq2Seq应用于神经机器翻译(Neural Machine Translation,NMT),唯一不同的是在[1]中使用LSTM作为基础网络,而在[2]中则是使用的是RNN。在Seq2Seq框架中包含了两个模块,一个是encoder模块,另一个是decoder模块。这种同时包含encoder和decoder的结构与AutoEncoder网络相似,不同的是AutoEncoder模型是将输入通过encoder的网络生成中间的结果,并通过decoder对中间的结果还原,AutoEncoder的模型结构如下图所示:

www.zeeklog.com  - 文本生成seq2seq框架


而在Seq2Seq中,相同的是两者都包含了Encoder和Decoder,不同的是,在Seq2Seq中,输入与输出并不是相同的,而在AutoEncoder中,输入与输出是相同的。

2. Seq2Seq框架

2.1. Seq2Seq框架的概述

Seq2Seq框架最初是在神经机器翻译(Neural Machine Translation,NMT)领域中提出,用于将一种语言(sequence)翻译成另一种语言(sequence)。由于在Seq2Seq结构中同时包含了encoder和decoder的结构,通常Seq2Seq又被称为Encoder-Decoder结构,Seq2Seq的结构如下图所示:

www.zeeklog.com  - 文本生成seq2seq框架

在Seq2Seq结构中,Encoder和Decoder分别是两个独立的神经网络模型,用于对不同的文本建模,通常对序列化文本建模的方法如LSTM[1],RNN[2]等。Encoder通过神经网络将原始的输入 { x 1 , x 2 , ⋯ , x T x } \left \{ x_1,x_2,\cdots ,x_{T_x} \right \} {x1​,x2​,⋯,xTx​​}转换成固定长度的中间向量 { c 1 , c 2 , ⋯ , c l } \left \{ c_1,c_2,\cdots ,c_l \right \} {c1​,c2​,⋯,cl​},Decoder将此中间向量作为输入,得到最终的输出 { y 1 , y 2 , ⋯ , y T y } \left \{ y_1,y_2,\cdots ,y_{T_y} \right \} {y1​,y2​,⋯,yTy​​}。

对于机器翻译NMT问题,从概率的角度分析,即对于给定输入 x = { x 1 , x 2 , ⋯ , x T x } \mathbf{x}=\left \{ x_1,x_2,\cdots ,x_{T_x} \right \} x={x1​,x2​,⋯,xTx​​},求目标输出 y = { y 1 , y 2 , ⋯ , y T y } \mathbf{y}=\left \{ y_1,y_2,\cdots ,y_{T_y} \right \} y={y1​,y2​,⋯,yTy​​},使得条件概率 p ( y ∣ x ) p\left ( \mathbf{y}\mid \mathbf{x} \right ) p(y∣x)最大,即 a r g m a x y p ( y ∣ x ) argmax_{\mathbf{y}}\;p\left ( \mathbf{y}\mid \mathbf{x} \right ) argmaxy​p(y∣x)。

2.1. Encoder

为了便于阐述,这里选取RNN[2](Recurrent Neural Network)作为Encoder和Decoder,一个典型的RNN结构如下图所示:

www.zeeklog.com  - 文本生成seq2seq框架

在RNN中,当前时刻 t t t的隐含层状态 h t h_t ht​是由上一时刻 t − 1 t-1 t−1的隐含层状态 h t − 1 h_{t-1} ht−1​和当前时刻的输入 x t x_t xt​共同决定的,可由下式表示:

h t = f ( h t − 1 , x t ) h_t=f\left ( h_{t-1},x_t \right ) ht​=f(ht−1​,xt​)

假设在Seq2Seq框架中,输入序列为 x = { x 1 , x 2 , ⋯ , x T x } \mathbf{x}=\left \{ x_1,x_2,\cdots ,x_{T_x} \right \} x={x1​,x2​,⋯,xTx​​},其中, x i ∈ R K x x_i\in \mathbb{R}^{K_x} xi​∈RKx​,输出序列为 y = { y 1 , y 2 , ⋯ , y T y } \mathbf{y}=\left \{ y_1,y_2,\cdots ,y_{T_y} \right \} y={y1​,y2​,⋯,yTy​​},其中, y i ∈ R K y y_i\in \mathbb{R}^{K_y} yi​∈RKy​。在编码阶段,RNN通过学习到每个时刻的隐含层状态后,最终得到所有隐含层状态序列:

{ h 1 , h 2 , ⋯ , h T x } \left \{h_1,h_2,\cdots ,h_{T_x}\right \} {h1​,h2​,⋯,hTx​​}

具体过程可由下图表示:

www.zeeklog.com  - 文本生成seq2seq框架

通过对这些隐藏层的状态进行汇总,得到上图中固定长度的语义编码向量 C C C,如下式所示:

C = f ( h 1 , h 2 , ⋯ , h T x ) C=f\left ( h_1,h_2,\cdots ,h_{T_x} \right ) C=f(h1​,h2​,⋯,hTx​​)

其中 f f f表示某种映射函数。通常取最后的隐含层状态 h T x h_{T_x} hTx​​作为语义编码向量 C C C,即

C = f ( h 1 , h 2 , ⋯ , h T x ) = h T x C=f\left ( h_1,h_2,\cdots ,h_{T_x} \right )=h_{T_x} C=f(h1​,h2​,⋯,hTx​​)=hTx​​

2.2. Decoder

在解码阶段,在当前时刻 t t t,根据在编码阶段得到的语义向量 c c c和已经生成的输出序列 y 1 , y 2 , ⋯ , y t − 1 y_1,y_2,\cdots ,y_{t-1} y1​,y2​,⋯,yt−1​来预测当前的输出的 y t y_t yt​,其具体过程可由下图表示:

www.zeeklog.com  - 文本生成seq2seq框架

上述过程可以由下式表示:

y t = a r g m a x P ( y t ) = ∏ t = 1 T p ( y t ∣ y 1 , y 2 , ⋯ , y t − 1 , c ) y_t=argmax\; P\left ( y_t \right )=\prod_{t=1}^{T}p\left ( y_t\mid y_1,y_2,\cdots ,y_{t-1},c \right ) yt​=argmaxP(yt​)=t=1∏T​p(yt​∣y1​,y2​,⋯,yt−1​,c)

简化可得:

y t = f ( y t ∣ y 1 , y 2 , ⋯ , y t − 1 , c ) y_t=f\left ( y_t\mid y_1,y_2,\cdots ,y_{t-1},c \right ) yt​=f(yt​∣y1​,y2​,⋯,yt−1​,c)

其中 f f f表示某种映射函数。在RNN中,上式可简化为:

y t = f ( y t − 1 , s t − 1 , c ) y_t=f\left ( y_{t-1},s_{t-1},c \right ) yt​=f(yt−1​,st−1​,c)

其中 y t − 1 y_{t-1} yt−1​表示 t − 1 t-1 t−1时刻的输出, s t − 1 s_{t-1} st−1​表示Decoder中RNN在 t − 1 t-1 t−1时刻的神经元的隐含层的状态,  c c c代表的是Encoder网络生成的语义向量。

3. Attention

上述的基于Encoder-Decoder的Seq2Seq框架成功应用在NMT任务中,但是在Encoder和Decoder之间的固定长度的语义向量 C C C限制了Seq2Seq框架的性能。主要表现为固定长度的语义向量 C C C可能无法完整表示整个序列的信息,尤其是对于较长的句子。为了解决长句子表示的问题,Bahdanau等人[3]在2016年在Seq2Seq框架中引入了Attention机制,同时将上述的Encoder阶段中的RNN替换成双向的RNN(BiRNN),即bidirectional recurrent neural network。

3.1. 带有Attention机制的Encoder

在[3]中的Encoder中,采用的是BiRNN,具体过程如下图所示:

www.zeeklog.com  - 文本生成seq2seq框架


对于BiRNN,其包含了两个阶段的RNN过程,分别为正向RNN和反向RNN,其中,正向RNN生成的隐含层状态序列为:

{ h 1 → , h 2 → , ⋯ , h T x → } \left \{\overrightarrow{h_1},\overrightarrow{h_2},\cdots ,\overrightarrow{h_{T_x}}\right \} {h1​   ​,h2​   ​,⋯,hTx​​   ​}

反向RNN生成的隐含层状态序列为:

{ h 1 ← , h 2 ← , ⋯ , h T x ← } \left \{\overleftarrow{h_1},\overleftarrow{h_2},\cdots ,\overleftarrow{h_{T_x}}\right \} {h1​   ​,h2​   ​,⋯,hTx​​   ​}

对于 t t t时刻的隐含层状态 h t h_t ht​通常是将正向和反向的隐含层状态concat在一起,即:

h t = [ h t T → ; h t T ← ] T h_t=\left [ \overrightarrow{h_t^T};\overleftarrow{h_t^T} \right ]^T ht​=[htT​   ​;htT​   ​]T

3.2. 带有Attention机制的Decoder

与上述的Decoder一致,这里的Decoder也是一个标准的RNN,其过程可由下式表示:

y t = f ( y t − 1 , s t − 1 , c t ) y_t=f\left ( y_{t-1},s_{t-1},c_t \right ) yt​=f(yt−1​,st−1​,ct​)

注意到此处与上面不一样的是这里的Encoder网络生成的语义向量不再是固定的,而是变化的。对于第 i i i个词的Decoder过程中, c t c_t ct​为:

c i = ∑ j = 1 T x α i j h j c_i=\sum_{j=1}^{T_x}\alpha _{ij}h_j ci​=j=1∑Tx​​αij​hj​

其中, α i j \alpha _{ij} αij​为归一化权重,其具体为:

α i j = e x p ( e i j ) ∑ k = 1 T x e x p ( e i k ) \alpha _{ij}=\frac{exp\left ( e_{ij} \right )}{\sum_{k=1}^{T_x}exp\left ( e_{ik} \right )} αij​=∑k=1Tx​​exp(eik​)exp(eij​)​

其中, e i j e_{ij} eij​表示的是第 i i i个输出前一个隐藏层状态 s i − 1 s_{i-1} si−1​与第 j j j个输入隐层向量 h j h_j hj​之间的相关性,可以通过一个MLP神经网络进行计算,即:

e i j = a ( s i − 1 , h j ) = v a T t a n h ( W a s i − 1 + U a h j ) e_{ij}=a\left ( s_{i-1},h_j \right )=v_a^Ttanh\left ( W_as_{i-1}+U_ah_j \right ) eij​=a(si−1​,hj​)=vaT​tanh(Wa​si−1​+Ua​hj​)

其具体过程可由下图表示:

www.zeeklog.com  - 文本生成seq2seq框架

这里的Attention机制对所有的编码器隐含层状态 h j h_j hj​都分配了权重,表示的是输出与编码器中每个隐含层状态的相关关系。

4. 总结

与原始的Encoder-Decoder模型相比,加入Attention机制后最大的区别就是原始的Encoder将所有输入信息都编码进一个固定长度的向量之中。而加入Attention后,Encoder将输入编码成一个向量的序列,在Decoder的时候,每一步都会选择性的从向量序列中挑选一个集合进行进一步处理。这样,在产生每一个输出的时候,都能够做到充分利用输入序列携带的信息。

参考文献

[1] Cho K, Merrienboer B V, Gulcehre C, et al. Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation[J]. Computer Science, 2014.

[2] Sutskever I, Vinyals O, Le Q V. Sequence to sequence learning with neural networks[C]//Advances in neural information processing systems. 2014: 3104-3112.

[3] Bahdanau D, Cho K, Bengio Y. Neural machine translation by jointly learning to align and translate[J]. arXiv preprint arXiv:1409.0473, 2014.

[4]

Read more

深入理解 Proxy 和 Object.defineProperty

在JavaScript中,对象是一种核心的数据结构,而对对象的操作也是开发中经常遇到的任务。在这个过程中,我们经常会使用到两个重要的特性:Proxy和Object.defineProperty。这两者都允许我们在对象上进行拦截和自定义操作,但它们在实现方式、应用场景和灵活性等方面存在一些显著的区别。本文将深入比较Proxy和Object.defineProperty,包括它们的基本概念、使用示例以及适用场景,以帮助读者更好地理解和运用这两个特性。 1. Object.defineProperty 1.1 基本概念 Object.defineProperty 是 ECMAScript 5 引入的一个方法,用于直接在对象上定义新属性或修改已有属性。它的基本语法如下: javascript 代码解读复制代码Object.defineProperty(obj, prop, descriptor); 其中,obj是目标对象,prop是要定义或修改的属性名,descriptor是一个描述符对象,用于定义属性的特性。 1.2 使用示例 javascript 代码解读复制代码//

By Ne0inhk

Proxy 和 Object.defineProperty 的区别

Proxy 和 Object.defineProperty 是 JavaScript 中两个不同的特性,它们的作用也不完全相同。 Object.defineProperty 允许你在一个对象上定义一个新属性或者修改一个已有属性。通过这个方法你可以精确地定义属性的特征,比如它是否可写、可枚举、可配置等。该方法的使用场景通常是需要在一个对象上创建一个属性,然后控制这个属性的行为。 Proxy 也可以用来代理一个对象,但是相比于 Object.defineProperty,它提供了更加强大的功能。使用 Proxy 可以截获并重定义对象的基本操作,比如访问属性、赋值、函数调用等等。在这些操作被执行之前,可以通过拦截器函数对这些操作进行拦截和修改。因此,通过 Proxy,你可以完全重写一个对象的默认行为。该方法的使用场景通常是需要对一个对象的行为进行定制化,或者需要在对象上添加额外的功能。 对比 以下是 Proxy 和 Object.defineProperty 的一些区别对比: 方面ProxyObject.defineProperty语法使用 new Proxy(target,

By Ne0inhk