编码器-解码器架构_by《李沐:动手学深度学习v2》pytorch版

系列文章目录


文章目录


一、引言

正如我们在上一节中所讨论的, 机器翻译是序列转换模型的一个核心问题, 其输入和输出都是长度可变的序列。 为了处理这种类型的输入和输出, 我们可以设计一个包含两个主要组件的架构: 第一个组件是一个编码器(encoder): 它接受一个长度可变的序列作为输入, 并将其转换为具有固定形状的编码状态。 第二个组件是解码器(decoder): 它将固定形状的编码状态映射到长度可变的序列。 这被称为编码器-解码器 (encoder-decoder)架构, 如下图所示。

我们以英语到法语的机器翻译为例: 给定一个英文的输入序列:"They""are""watching""."。 首先,这种"编码器-解码器"架构将长度可变的输入序列编码成一个"状态", 然后对该状态进行解码, 一个词元接着一个词元地生成翻译后的序列作为输出: "Ils""regordent""."。 由于"编码器-解码器"架构是形成后续章节中不同序列转换模型的基础, 因此本节将把这个架构转换为接口方便后面的代码实现。

编码器

在编码器接口中,我们只指定长度可变的序列作为编码器的输入X。任何继承这个Encoder基类的模型将完成代码实现。

python 复制代码
from torch import nn


class Encoder(nn.Module):
    """编码器-解码器架构的基本编码器接口"""
    def __init__(self, **kwargs):
        super(Encoder, self).__init__(**kwargs)

    def forward(self, X, *args):
        raise NotImplementedError

解码器

在下面的解码器接口中,我们新增一个init_state函数,用于将编码器的输出(enc_outputs)转换为编码后的状态。

注意,此步骤可能需要额外的输入,例如:输入序列的有效长度,

这在上一节中进行了解释。为了逐个地生成长度可变的词元序列,解码器在每个时间步都会将输入(例如:在前一时间步生成的词元)和编码后的状态映射成当前时间步的输出词元。

python 复制代码
#@save
class Decoder(nn.Module):
    """编码器-解码器架构的基本解码器接口"""
    def __init__(self, **kwargs):
        # 调用父类 nn.Module 的构造函数进行初始化
        super(Decoder, self).__init__(**kwargs)

    def init_state(self, enc_outputs, *args):
        # 初始化解码器状态,基于编码器的输出
        # 该方法尚未实现,需在子类中具体定义
        raise NotImplementedError

    def forward(self, X, state):
        # 定义解码器的前向传播过程
        # 接受输入 X 和当前状态 state
        # 该方法尚未实现,需在子类中具体定义
        raise NotImplementedError

合并编码器和解码器

总而言之,"编码器-解码器"架构包含了一个编码器和一个解码器,并且还拥有可选的额外的参数。

在前向传播中,编码器的输出用于生成编码状态,这个状态又被解码器作为其输入的一部分。

python 复制代码
#@save
class EncoderDecoder(nn.Module):
    """编码器-解码器架构的基类"""
    def __init__(self, encoder, decoder, **kwargs):
        # 调用父类 nn.Module 的构造函数进行初始化
        super(EncoderDecoder, self).__init__(**kwargs)
        # 保存传入的编码器和解码器对象
        self.encoder = encoder
        self.decoder = decoder

    def forward(self, enc_X, dec_X, *args):
        # 通过编码器处理输入 enc_X,获取编码器的输出
        enc_outputs = self.encoder(enc_X, *args)
        # 初始化解码器的状态,基于编码器的输出
        dec_state = self.decoder.init_state(enc_outputs, *args)
        # 使用解码器处理输入 dec_X 和初始化的状态,返回最终输出
        return self.decoder(dec_X, dec_state)

"编码器-解码器"体系架构中的术语状态

会启发人们使用具有状态的神经网络来实现该架构。

在下一节中,我们将学习如何应用循环神经网络,

来设计基于"编码器-解码器"架构的序列转换模型。

小结

  • "编码器-解码器"架构可以将长度可变的序列作为输入和输出,因此适用于机器翻译等序列转换问题。
  • 编码器将长度可变的序列作为输入,并将其转换为具有固定形状的编码状态。
  • 解码器将具有固定形状的编码状态映射为长度可变的序列。

练习

  1. 假设我们使用神经网络来实现"编码器-解码器"架构,那么编码器和解码器必须是同一类型的神经网络吗?
  2. 除了机器翻译,还有其它可以适用于"编码器-解码器"架构的应用吗?

答案

1. 编码器和解码器是否必须是同一类型的神经网络?

不,编码器和解码器不必是同一类型的神经网络。虽然它们通常在同一架构中协同工作,但可以使用不同类型的网络。例如:

  • 编码器 可以是卷积神经网络(CNN),用于处理图像数据,而解码器可以是循环神经网络(RNN),用于生成序列数据。
  • 在某些情况下,编码器和解码器也可以是同一类型的网络,例如都使用RNN,但它们的具体结构和参数可以不同。

2. 除了机器翻译,还有其它可以适用于"编码器-解码器"架构的应用吗?

是的,编码器-解码器架构适用于多种应用,除了机器翻译之外,还包括:

  1. 图像生成

    • 例如,图像到图像的转换(如从素描到真实图像)。
  2. 文本摘要

    • 自动生成文章的简要摘要。
  3. 语音识别

    • 将语音信号编码为文本。
  4. 对话系统

    • 生成对话回复,基于用户输入的上下文。
  5. 视频分析

    • 从视频中提取特征并生成描述或动作预测。
  6. 图像标注

    • 为图像生成描述性文本。
  7. 时间序列预测

    • 从历史数据预测未来的数值序列。

这些应用展示了编码器-解码器架构的灵活性和广泛适用性。

相关推荐
踹断瘸子那条好腿.7 分钟前
视觉检测中的深度学习应用
人工智能·深度学习·视觉检测
未来的JAVA高级开发工程师37 分钟前
网关登录校验(2)----网关如何将用户信息传递给微服务
java·数据库·微服务·架构
lovPopcorn1 小时前
微服务保护详细笔记(一):雪崩问题--Sentinel
笔记·微服务·架构
杨诚实2 小时前
20240924软考架构-------软考191-195答案解析
运维·架构
u0135212963 小时前
001.从0开始实现线性回归(pytorch)
深度学习·回归·线性回归
橙子小哥的代码世界3 小时前
【深度学习】03-神经网络01-4 神经网络的pytorch搭建和参数计算
人工智能·深度学习·神经网络
Bosenya123 小时前
【PyTorch】张量操作与线性回归
人工智能·pytorch·线性回归
吉小雨3 小时前
PyTorch 图像分割模型教程
人工智能·pytorch·python
Star_.3 小时前
RNN股票预测(Pytorch版)
人工智能·rnn·深度学习