编码器-解码器架构_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. 时间序列预测

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

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

相关推荐
余炜yw3 小时前
【LSTM实战】跨越千年,赋诗成文:用LSTM重现唐诗的韵律与情感
人工智能·rnn·深度学习
莫叫石榴姐3 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
96773 小时前
对抗样本存在的原因
深度学习
javaDocker3 小时前
业务架构、数据架构、应用架构和技术架构
架构
YRr YRr4 小时前
深度学习:神经网络中的损失函数的使用
人工智能·深度学习·神经网络
静静的喝酒4 小时前
深度学习笔记之BERT(二)BERT精简变体:ALBERT
深度学习·bert·albert
麦麦大数据4 小时前
Python棉花病虫害图谱系统CNN识别+AI问答知识neo4j vue+flask深度学习神经网络可视化
人工智能·python·深度学习
JosieBook5 小时前
【架构】主流企业架构Zachman、ToGAF、FEA、DoDAF介绍
架构
谢眠5 小时前
深度学习day3-自动微分
python·深度学习·机器学习
z千鑫5 小时前
【人工智能】深入理解PyTorch:从0开始完整教程!全文注解
人工智能·pytorch·python·gpt·深度学习·ai编程