人工智能-机器学习-深度学习-自然语言处理(NLP)-生成模型:Seq2Seq模型(Encoder-Decoder框架、Attention机制)

本文主要是介绍人工智能-机器学习-深度学习-自然语言处理(NLP)-生成模型:Seq2Seq模型(Encoder-Decoder框架、Attention机制),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们之前遇到的较为熟悉的序列问题,主要是利用一系列输入序列构建模型,预测某一种情况下的对应取值或者标签,在数学上的表述也就是通过一系列形如 X i = ( x 1 , x 2 , . . . , x n ) \textbf{X}_i=(x_1,x_2,...,x_n) Xi=(x1,x2,...,xn) 的向量序列来预测 Y Y Y 值,这类的问题的共同特点是,输入可以是一个定长或者不定长的序列,但输出一般要求是一个固定长度的序列(单个标签较为常见,即长度为1的序列)。

例如利用RNN网络的文本情感分类,输入的文本长度不固定,但输出是某一个情感标签。这样的问题我们已经有相对成熟的方法解决,而在有的现实场景中,我们更希望输入与输出的序列长度都不固定,针对此类问题,则使用Seq2Seq模型。

一、Encoder-Decoder模型

  • 所谓Encoder-Decoder模型,又叫做编码-解码模型。这是一种应用于Seq2Seq问题的模型。
  • 所谓编码,就是将输入序列转化成一个固定长度的向量;解码,就是将之前生成的固定向量再转化成输出序列。
    在这里插入图片描述
  • 编码器和解码器都不是固定的,可选的有CNN/RNN/BiRNN/LSTM/GRU等等,可以自由组合。比如说,你在编码时使用BiRNN,解码时使用RNN,或者在编码时使用RNN,解码时使用LSTM等等。
  • 为了方便阐述,选取了编码和解码都是RNN的组合。
  • 在序列到序列处理不定长序列的过程中,采用了序列的起始标记<S>终止标记</S>来“告诉”编码器的编码过程何时开始与结束,也就是间接反映了当前序列的长度信息
    在这里插入图片描述

1、Encoder(编码)

  • 在RNN中,当前时间的隐藏状态是由上一时间的状态当前时间输入决定的,也就是: h t = f ( h t − 1 , x t ) h_t=f(h_{t−1},x_t) ht=f(ht1,xt)
  • 获得了各个时间段的隐藏层以后,再将隐藏层的信息汇总,生成最后的语义向量: C = q ( h 1 , h 2 , h 3 , … , h T x ) C=q(h_1,h_2,h_3,…,h_{T_x}) C=q(h1,h2,h3,,hTx)
  • 一种简单的方法是将最后的隐藏层作为语义向量C,即 C = q ( h 1 , h 2 , h 3 , … , h T x ) = h T x C=q(h_1,h_2,h_3,…,h_{T_x})=h_{T_x} C=q(h1,h2,h3,,hTx)=hTx

2、Decoder(解码)

  • 解码阶段可以看做编码的逆过程。这个阶段,我们要根据给定的语义向量 C C C 和之前已经生成的输出序列 Y 1 , Y 2 , … Y t − 1 Y_1,Y2,…Y_{t−1} Y1,Y2,Yt1 来预测下一个输出的单词 Y t Y_t Yt,即: Y t = a r g m a x P ( Y t ) = ∏ t = 1 T p ( Y t ∣ Y 1 , … , Y t − 1 , C ) Y_t=argmaxP(Y_t)=\prod^T_{t=1} p(Y_t|{Y_1,…,Y_{t−1}},C) Yt=argmaxP(Yt)=t=1Tp(YtY1,,Yt1,C)
  • 也可以写作: Y t = g ( Y 1 , … , Y t − 1 , C ) Y_t=g(Y_1,…,Y_{t−1},C) Yt=g(Y1,,Yt1,C)
  • 而在RNN中,上式又可以简化成: Y t = g ( Y t − 1 , s t , C ) Y_t=g(Y_{t−1},s_t,C) Yt=g(Yt1,st,C)
    其中 s s s 是输出RNN中的隐藏层, C C C 代表之前提过的语义向量, Y t − 1 Y_{t−1} Yt1 表示上个时间段的输出,反过来作为这个时间段的输入。而 g g g 则可以是一个非线性的多层的神经网络,产生词典中各个词语属于 Y t Y_t Yt 的概率。
  • Encoder-Decoder模型虽然非常经典,但是局限性也非常大。
  • 最大的局限性就在于编码和解码之间的唯一联系就是一个固定长度的语义向量C。
  • 也就是说,编码器要将整个序列的信息压缩进一个固定长度的向量中去。这样做有两个弊端,一是语义向量无法完全表示整个序列的信息,还有就是先输入的内容携带的信息会被后输入的信息稀释掉,或者说,被覆盖了。输入序列越长,这个现象就越严重。这就使得在解码的时候一开始就没有获得输入序列足够的信息, 那么解码的准确度自然也就要打个折扣了。

二、Attention模型

  • 为了解决Encoder-Decoder模型的弊端,提出了Attention模型(注意力模型)。
  • 简单的说,这种模型在产生输出的时候,还会产生一个“注意力范围”表示接下来输出的时候要重点关注输入序列中的哪些部分,然后根据关注的区域来产生下一个输出,如此往复。模型的大概示意图如下所示
    在这里插入图片描述
  • 相比于之前的encoder-decoder模型,attention模型最大的区别就在于它不在要求编码器将所有输入信息都编码进一个固定长度的向量之中。相反,此时编码器需要将输入编码成一个向量的序列,而在解码的时候,每一步都会选择性的从向量序列中挑选一个子集进行进一步处理。这样,在产生每一个输出的时候,都能够做到充分利用输入序列携带的信息。而且这种方法在翻译任务中取得了非常不错的成果。
  • 以翻译任务的结构为例。解码部分使用了attention模型,而在编码部分,则使用了BiRNN(bidirectional RNN,双向RNN)
    在这里插入图片描述

1、Decoder(解码)

  • 我们先来看看解码。解码部分使用了attention模型。类似的,我们可以将之前定义的条件概率写作: p ( Y i ∣ Y 1 , … , Y i − 1 , X ) = g ( Y i − 1 , s i , c i ) p(Y_i|Y_1,…,Y_{i−1},X)=g(Y_{i−1},s_i,c_i) p(YiY1,,Yi1,X)=g(Yi1,si,ci)
    上式 s i s_i si 表示解码器 i i i 时刻的隐藏状态。计算公式是: s i = f ( s i − 1 , Y i − 1 , c i ) s_i=f(s_{i−1},Y_{i−1},c_i) si=f(si1,Yi1,ci)
    注意这里的条件概率与每个目标输出 Y i Y_i Yi 相对应的内容向量 c i c_i ci 有关。而在传统的方式中,只有一个内容向量 C C C。那么这里的内容向量 c i c_i ci 又该怎么算呢?其实 c i c_i ci 是由编码时的隐藏向量序列 ( h 1 , … , h T x ) (h_1,…,h_{T_x}) (h1,,hTx) 按权重相加得到的: c i = ∑ j = 1 T x α ^ i j h j c_i=\sum^{T_x}_{j=1}\hat{α}_{ij}h_j ci=j=1Txα^ijhj
    由于编码使用了双向RNN,因此可以认为 c i c_i ci 中包含了输入序列中第 i i i 个词以及前后一些词的信息。将隐藏向量序列按权重相加,表示在生成第 i i i 个输出的时候的注意力分配是不同的。 α i j α_{ij} αij 的值越高,表示第 i i i 个输出在第 j j j 个输入上分配的注意力越多,在生成第 i i i 个输出的时候受第 j j j 个输入的影响也就越大。那么现在我们又有新问题了, α i j α_{ij} αij 又是怎么得到的呢?这个其实是由第 i − 1 i-1 i1 个输出隐藏状态 s i − 1 s_{i−1} si1 和输入中各个隐藏状态共同决定的。也即是: α i j = e α ^ i j ∑ k = 1 T x e α ^ i k α_{ij}=\cfrac{e^{\hat{α}_{ij}}}{\sum^{T_x}_{k=1}e^{\hat{α}_{ik}}} αij=k=1Txeα^ikeα^ij α ^ i k = a ( s i − 1 , h k ) \hat{α}_{ik}=a(s_{i-1},h_k) α^ik=a(si1,hk)
    也就是说, s i − 1 s_{i−1} si1 先跟隐藏向量序列 ( h 1 , … , h T x ) (h_1,…,h_{T_x}) (h1,,hTx)中的每一个 h h h 通过函数 a a a 分别计算得到一个数值,然后使用softmax得到 i i i 时刻的输出在隐藏向量序列 ( h 1 , … , h T x ) (h_1,…,h_{T_x}) (h1,,hTx)中的每一个 h h h 上的注意力分配向量。这个分配向量也就是计算 c i c_i ci 的权重。
  • 我们现在再把公式按照执行顺序汇总一下
    α ^ i k = a ( s i − 1 , h k ) \hat{α}_{ik}=a(s_{i-1},h_k) α^ik=a(si1,hk) α i j = e α ^ i j ∑ k = 1 T x e α ^ i k α_{ij}=\cfrac{e^{\hat{α}_{ij}}}{\sum^{T_x}_{k=1}e^{\hat{α}_{ik}}} αij=k=1Txeα^ikeα^ij c i = ∑ j = 1 T x α ^ i j h j c_i=\sum^{T_x}_{j=1}\hat{α}_{ij}h_j ci=j=1Txα^ijhj s i = f ( s i − 1 , Y i − 1 , c i ) s_i=f(s_{i−1},Y_{i−1},c_i) si=f(si1,Yi1,ci) Y i = p ( Y i ∣ Y 1 , … , Y i − 1 , X ) = g ( Y i − 1 , s i , c i ) Y_i=p(Y_i|Y_1,…,Y_{i−1},X)=g(Y_{i−1},s_i,c_i) Yi=p(YiY1,,Yi1,X)=g(Yi1,si,ci)
    上面这些公式就是解码器在第i个时间段内要做的事情。
    在这里插入图片描述

2、Encoder(编码)

  • 相比于上面解码的创新,这边的编码就比较普通了,只是传统的单向的RNN中,数据是按顺序输入的。
  • 因此第 j j j 个隐藏状态 h → j \overrightarrow{h}_j h j 只能携带第 j j j 个单词本身以及之前的一些信息;
  • 而如果逆序输入,则 h ← j \overleftarrow{h}_j h j包含第 j j j 个单词及之后的一些信息。
  • 如果把这两个结合起来, h j = [ h → j , h ← j ] h_j=[\overrightarrow{h}_j,\overleftarrow{h}_j] hj=[h j,h j]就包含了第 j j j 个输入和前后的信息。

3、Attention模型实验结果

  • 为了检验性能,模型作者分别使用传统模型和attention模型在英语-法语的翻译数据集上进行了测验。
  • 传统模型的编码器和解码器各有1000个隐藏单元。编码器中还有一个多层神经网络用于实现从隐藏状态到单词的映射。在优化方面,使用了SGD(minibatch stochastic gradient descent)以及Adadelta,前者负责采样,后者负责优化下降方向。
  • 得到的结果如下:
    在这里插入图片描述
  • 图中RNNenc表示传统的结构,而RNNsearch表示attention模型。后面的数字表示序列的长度。可以看到,不论序列长度,attention模型的性能均优于传统的编码-解码模型。而RNNsearch-50甚至在长文本上的性能也非常的优异
  • 除了准确度之外,还有一个很值得关注的东西:注意力矩阵。之前已经提过,每个输出都有一个长为Tx的注意力向量,那么将这些向量合起来看,就是一个矩阵。对其进行可视化,得到如下结果
    在这里插入图片描述
  • 其中x轴表示待翻译的句子中的单词(英语),y轴表示翻译以后的句子中的单词(法语)。可以看到尽管从英语到法语的过程中,有些单词的顺序发生了变化,但是attention模型仍然很好的找到了合适的位置。换句话说,就是两种语言下的单词“对齐”了。因此,也有人把注意力模型叫做对齐(alignment)模型。而且像比于用语言学实现的硬对齐,这种基于概率的软对齐更加优雅,因为能够更全面的考虑到上下文的语境。

三、Seq2Seq模型

1、Seq2Seq模型简介

  • 对于一些自然语言处理任务,比如聊天机器人,机器翻译,自动文摘等,传统的方法都是从候选集中选出答案,这对素材的完善程度要求很高,
  • 随着最近几年深度学习的兴起,国外学者将深度学习技术应用于自然语言的生成和自然语言的理解的方面的研究,并取得了一些突破性的成果,比如,Sequence-to-sequence (seq2seq) 模型,它是目前自然语言处理技术中非常重要而且非常流行的一个模型,
  • Seq2Seq模型突破了传统的固定大小输入问题框架,开通了将经典深度神经网络模型运用于翻译与职能问答这一类序列型任务的先河,并且被证实在各主流语言之间的相互翻译以及语音助手中人机短问快答的应用中有着非常好的表现。
  • seq2seq模型是在2014年,是由Google Brain团队和Yoshua Bengio 两个团队各自独立的提出来,他们发表的文章主要关注的是机器翻译相关的问题。而seq2seq模型,简单来说就是一个翻译模型,把一个语言序列翻译成另一种语言序列,
  • seq2seq模型整个处理过程是通过使用深度神经网络LSTM或者RNN,将一个序列作为输入映射为另外一个输出序列,如下图所示:

在这里插入图片描述

2、Seq2Seq模型核心思想

  • Seq2Seq模型是将一个序列信号,通过“编码&解码”生成一个新的序列信号,通常用于机器翻译、语音识别、自动对话等任务。
  • Seq2Seq是一个Encoder–Decoder 结构的网络,它的输入是一个序列,输出也是一个序列, Encoder 中将一个可变长度的信号序列变为固定长度的向量表达,Decoder 将这个固定长度的向量变成可变长度的目标的信号序列。
  • Seq2Seq模型是输出的长度不确定时采用的模型,这种情况一般是在机器翻译的任务中出现,将一句中文翻译成英文,那么这句英文的长度加粗样式有可能会比中文短,也有可能会比中文长,所以输出的长度就不确定了。如下图所,输入的中文长度为4,输出的英文长度为2。
    在这里插入图片描述

3、Seq2Seq模型的优化目标

  • 在监督学习的大部分模型中,我们都将考虑如何根据损失函数(或者叫目标函数)来更新模型参数,这也是模型训练的目标,在Seq2Seq模型中也不例外。
  • seq2seq模型的目标在于根据输入序列的信息最大化目标输出序列的概率,类似于语言模型的思路。对于所有的训练样本,有以下形式的损失函数:
    在这里插入图片描述
    其中 N N N 为训练样本数量, X n X_n Xn Y n Y_n Yn为每个样本对应的输入和输出序列, θ θ θ为待学习的参数向量。每一个 p ( Y n ∣ X n , θ ) p(Y_n|X_n,θ) p(YnXn,θ) 都由Encoder-Decoder框架生成,其中包含在神经网络中的大量参数,可通过梯度下降的方式逐步优化。



参考资料:
草稿纸上的seq2seq模型与Attention机制

这篇关于人工智能-机器学习-深度学习-自然语言处理(NLP)-生成模型:Seq2Seq模型(Encoder-Decoder框架、Attention机制)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128929

相关文章

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

解决docker目录内存不足扩容处理方案

《解决docker目录内存不足扩容处理方案》文章介绍了Docker存储目录迁移方法:因系统盘空间不足,需将Docker数据迁移到更大磁盘(如/home/docker),通过修改daemon.json配... 目录1、查看服务器所有磁盘的使用情况2、查看docker镜像和容器存储目录的空间大小3、停止dock

5 种使用Python自动化处理PDF的实用方法介绍

《5种使用Python自动化处理PDF的实用方法介绍》自动化处理PDF文件已成为减少重复工作、提升工作效率的重要手段,本文将介绍五种实用方法,从内置工具到专业库,帮助你在Python中实现PDF任务... 目录使用内置库(os、subprocess)调用外部工具使用 PyPDF2 进行基本 PDF 操作使用

k8s admin用户生成token方式

《k8sadmin用户生成token方式》用户使用Kubernetes1.28创建admin命名空间并部署,通过ClusterRoleBinding为jenkins用户授权集群级权限,生成并获取其t... 目录k8s admin用户生成token创建一个admin的命名空间查看k8s namespace 的

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

Python异常处理之避免try-except滥用的3个核心原则

《Python异常处理之避免try-except滥用的3个核心原则》在Python开发中,异常处理是保证程序健壮性的关键机制,本文结合真实案例与Python核心机制,提炼出避免异常滥用的三大原则,有需... 目录一、精准打击:只捕获可预见的异常类型1.1 通用异常捕获的陷阱1.2 精准捕获的实践方案1.3