草庐IT

Encoder-Decoder 模型架构详解

_Summer tree 2023-12-08 原文

文章目录

概述

  • Encoder-Decoder 并不是一个具体的模型,而是一个通用的框架。
  • Encoder 和 Decoder 部分可以是任意文字,语音,图像,视频数据
  • 模型可以是 CNN,RNN,LSTM,GRU,Attention 等等
  • 所谓编码,就是将输入序列转化转化成一个固定长度向量, 解码,就是讲之前生成的固定向量再转化出输出序列。

注意点:

  1. 不管输入序列和输出序列长度是什么,中间的「向量 c」长度都是固定的。 这是Encoder-decoder框架的的缺点
  2. 不同的任务可以选择不同的编码器和解码器 (RNN,CNN,LSTM,GRU)。
  3. Encoder-Decoder 是一个 End-to-End 的学习算法,以机器翻译为力,可以将法语翻译成英语。这样的模型也可以叫做 Seq2Seq

Seq2Seq( Sequence-to-sequence )

  • 输入序列和输出序列的长度是可变的
  • Seq2Seq 强调目的,不特指具体方法,满足输入序列,输出序列的目的,都可以统称为 Seq2Seq 模型。
  • Seq2Seq 使用的具体方法基本都是属于 Encoder-Decoder 模型的范畴。

For example

  • 在训练数据集中,我们可以在每个句子后附特殊字符 ”“ (end of sequence) 以表示序列终止
  • 每个句子前用到了特殊字符 “” (begin of seqence) 表示序列开始
  • Encoder 在最终时间步的隐状态作为输入句子表征和编码信息。??
  • Decoder 在各个时间步中使用输入句子的编码信息和上一个时间步的输出以及隐藏状态作为输入。 ??

案例:英文 it is a cat. 翻译成中文的过程。

  1. 先将整个源句子进行符号化处理,以一个固定的特殊标记作为翻译的开始符号和结束符号。此时句子变成 it is a cat .
  2. 对序列进行建模,得到概率最大的译词,如第一个词为 “这”。将生成的词加入译文序列,重复上述步骤,不断迭代。
  3. 直到终止符号被模型选择出来,停止迭代过程,并进行反符号化处理,得到译文。

Encoder-Decoder的缺陷

中间的「向量 c」长度都是固定的

  • RNN 结构的 Encoder-Decoder 模型存在长程梯度消失问题
  • 对于较长的句子,我们很难寄希望于将输入的序列转化为定长的向量而保存所有有效信息
  • 即便 LSTM 加了门控机制可以选择性遗忘和记忆,随着所需翻译的句子难度增加,这个结构的效果仍然不理想

Attention 机制的引入

  • Attention 就是为了解决信息过长导致信息丢失的问题
  • 在 Attention 模型中,我们翻译当前词,会寻找源语句中相对应的几个词语,然后结合之前已经翻译的序列来翻译下一个词

Attention 如何准确将注意力放在关注的地方呢?

  • 对 RNN 的输出计算注意程度,通过计算最终时刻的向量与任意 i 时刻向量的权重,通过 softmax 计算出得到注意力偏向分数,如果对某一个序列特别注意,那么计算的偏向分数将会比较大。
  • 计算 Encoder 中每个时刻的隐向量 ??
  • 将各个时刻对于最后输出的注意力分数进行加权,计算出每个时刻 i 向量应该赋予多少注意力
  • decoder 每个时刻都会将 ③ 部分的注意力权重输入到 Decoder 中,此时 Decoder 中的输入有:经过注意力加权的隐藏层向量,Encoder 的输出向量,以及 Decoder 上一时刻的隐向量
  • Decoder 通过不断迭代,Decoder 可以输出最终翻译的序列。

引入 Attention 的 Encoder-Decoder 框架下,完成机器翻译任务的大致流程如下:






Transformer中的Encoder-Decoder

  • Transformer 中的 Attention 是 Self-Attention (自注意力机制),而且是 Multi-Head Attention (多头注意力机制)

Attention 机制

  • Source 是由一系列 组成,此时给定 Target 中某个元素 Query,通过计算 Query 和 各个 Key 的相似性,得到每个 Key 对 Value 的权重系数,然后对 Value 进行加权求和,即得到最终 Attention 数值。

self-Attention

  • 指的不是 Target 和 Source 之间的 Attention 机制,而是 Source 内部元素之间或者 Target 内部元素之间发生的 Attention 机制,也可以理解为 Target = Source 的特殊情况下的 Attention 机制。
  • Source = Target,也即是 Key = Value = Query
  • Self-Attention 可以捕获同一个句子中单词之间的一些句法特征 (图 1:有一定距离的短语结构) 或语义特征 (图 2:its 指代的对象 Law)。
  • 引入 Self-Attention 后会更容易捕获句子中长距离相互依赖特征,因为 Self-Attention 在计算过程中直接将句子任意两个单词的联系起来
  • 由于不依赖时间序列这一特性,Self-Attention 增加了计算的并行性。

Multi-Head Attention

  • 将模型分为多个头,形成多个子空间,可以让模型去关注不同方向的信息
  • Transformer 或 Bert 的特定层是有独特功能的,底层更偏向于关注语法,顶层更偏向于关注语义
  • 同一层中,总有那么一两个头独一无二,和其它头关注的 Token 不同
  • 下面是两个 Self-Attention 执行同一个句子时候展现的不同的注意力,利用多头机制,明显学会了不同的任务下采取不一样的注意力。

Transformer 中 Encoder 由 6 个相同的层组成,每个层包含 2 个部分:

  • Multi-Head Self-Attention
  • Position-Wise Feed-Forward Network (全连接层)

Decoder 也是由 6 个相同的层组成,每个层包含 3 个部分:

  • Multi-Head Self-Attention
  • Multi-Head Context-Attention
  • Position-Wise Feed-Forward Network

上面每个部分都有残差连接 (redidual connection),然后接一个 Layer Normalization。

encoder-decoder的局限性:
编码和解码之间的唯一联系就是一个固定长度的语义向量C。编码器要将整个序列的信息压缩进一个固定长度的向量中去 。

  • 语义向量无法完全表示整个序列的信息
  • 先输入的内容携带的信息会被后输入的信息稀释掉

注意力模型
模型在产生输出的时候,还会产生一个“注意力范围”表示接下来输出的时候要重点关注输入序列中的哪些部分,然后根据关注的区域来产生下一个输出,如此往复。

attention模型最大的区别就在于它不在要求编码器将所有输入信息都编码进一个固定长度的向量之中。

  • 编码器需要将输入编码成一个向量的序列,而在解码的时候,每一步都会选择性的从向量序列中挑选一个子集进行进一步处理。
  • 这样,在产生每一个输出的时候,都能够做到充分利用输入序列携带的信息。、

编码解码器的表示

几点说明

  • 不论输入和输出的长度是什么,中间的“向量c”长度都是固定的(这是它的缺陷所在)。
  • 根据不同的任务可以选择不同的编码器和解码器(例如,CNN、RNN、LSTM、GRU等)
  • Encoder-Decoder的一个显著特征就是:它是一个end-to-end的学习算法。
  • 只要符合这种框架结构的模型都可以统称为Encoder-Decoder模型。

Seq2Seq与Encoder-Decoder的关系
Encoder-Decoder强调的是模型设计(编码-解码的一个过程),Seq2Seq强调的是任务类型(序列到序列的问题)。

Encoder-Decoder的四种模式
最简单的解码模式

带输出回馈的解码模式

带编码向量的解码模式

带注意力的解码模式


参考链接:

  1. https://zhuanlan.zhihu.com/p/109585084
  2. https://blog.csdn.net/u014595019/article/details/52826423
  3. https://blog.csdn.net/u010626937/article/details/104819570

有关Encoder-Decoder 模型架构详解的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  5. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  6. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  7. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  8. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  9. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  10. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

随机推荐