大模型学习入门——Day7: 深入理解T5模型(Encoder-Decoder)

笔记的参考教程
在自然语言处理(NLP)的世界里,我们见证了从 Encoder-Only 模型(如 BERT)到 Decoder-Only 模型(如 GPT)的演进。BERT 通过双向编码理解上下文,在理解类任务上表现卓越;GPT 则通过自回归解码生成流畅文本,在生成类任务中大放异彩。

然而,这两种架构都有其局限性。BERT 难以直接用于文本生成,而 GPT 对输入的理解是单向的。为了融合两者的优点,研究者们回归了经典的 Encoder-Decoder 架构,并在此基础上提出了 T5 模型,为 NLP 领域带来了革命性的“大一统”思想。

本文将深入探讨 T5 (Text-To-Text Transfer Transformer) 模型,从其模型结构、独特的预训练任务,到其核心的“大一统”哲学,并附上代码示例,让你彻底搞懂 T5 的魅力。

T5模型的总体架构

什么是 T5 的“大一统”思想?

T5 模型最核心、最具影响力的理念是 “万物皆可文本生成”(Text-to-Text)。

这个思想非常简洁而强大:无论是什么 NLP 任务,都将其统一转换为“输入一段文本,输出一段文本”的格式。 这种方法极大地简化了模型设计和应用流程,我们不再需要为不同任务(如分类、问答、翻译)设计不同的模型输出层。

我们来看几个例子:

  • 翻译 (Translation):
    • 输入: translate English to French: How are you?
    • 输出: Comment ça va?
  • 文本分类 (Text Classification):
    • 输入: classify: This is a great product.
    • 输出: Positive
  • 摘要 (Summarization):
    • 输入: summarize: [一段很长的新闻文章]
    • 输出: [文章的核心摘要]
  • 问答 (Question Answering):
    • 输入: question: Who created the T5 model? context: The T5 model was created by Google.
    • 输出: Google

通过在输入文本前加上一个明确的 “任务前缀”(如 translate English to French:),模型就能知道当前需要执行什么任务。这种设计不仅让一个模型能处理多种任务,还使其在多任务学习和泛化能力上表现得更加出色。

模型结构:强大的 Encoder-Decoder

T5 采用了经典的 Encoder-Decoder 结构,其编码器和解码器均基于 Transformer 构建。T5处理文本序列的整个过程可以分为四个主要阶段:编码输入 -> Encoder理解 -> Decoder生成 -> 解码输出

我们将以一个具体的翻译任务为例,来贯穿整个流程。

任务示例:

  • 输入文本: translate English to German: The cat sat on the mat.
  • 期望输出: Die Katze saß auf der Matte.
阶段 1: 编码输入 (Tokenization)

这是数据进入模型的入口。模型不认识文字,只认识数字。Tokenizer 的工作就是将文本翻译成模型能懂的“语言”。

  1. 输入文本处理:

    • 原始输入: "translate English to German: The cat sat on the mat."
    • Tokenizer 会将其切分成一系列的子词(tokens),并添加一个句子结束符 </s>
    • 切分结果: ['translate', ' English', ' to', ' German', ':', ' The', ' cat', ' sat', ' on', ' the', ' mat', '.', '</s>']
    • 然后,它会查询一个巨大的词汇表(Vocabulary),将每个 token 转换成一个独一无二的数字 ID。
    • 数字ID序列 (Encoder的最终输入): [2163, 8, 19, 1254, 10, 6, 2369, 1530, 18, 6, 2372, 5, 1] (注:这里的数字是示意,非真实ID)
  2. 目标文本处理 (为 Decoder 做准备):

    • 训练时,Decoder 也需要一个输入和一个目标。输入是带起始符的、向右偏移一位的目标文本,目标是原始目标文本。这被称为“Teacher Forcing”。
    • 推理/预测时,Decoder 的初始输入只有一个代表“开始”的特殊 token(在 T5 中通常是 pad token,ID为0)。
    • 初始输入 (Decoder的最初输入): [0]

现在,我们有了两组数字序列,它们将分别进入 Encoder 和 Decoder。

在这里插入图片描述

阶段 2: Encoder栈 (The “Understanding” Phase)

Encoder 的唯一目标是:透彻理解输入序列的每一个细节。它会产出一个富含上下文信息的向量序列,我们称之为 encoder_hidden_states

数据流如下:

  1. 输入: Encoder 的输入是阶段1生成的数字ID序列 [2163, 8, ..., 1]

  2. 词嵌入 (Embedding): 模型内部有一个巨大的“查询表”(Embedding Layer),它会将每个数字ID转换成一个高维向量(例如,768维)。现在,我们有了一个由13个向量组成的序列,每个向量代表一个输入 token。

  3. 位置编码 (Positional Encoding): Transformer 本身无法感知顺序,所以我们需要给每个向量加入位置信息,告诉模型 “The” 是第6个词,“cat” 是第7个词。T5 使用的是一种相对位置编码的变体。

  4. 进入 Encoder Block (循环 N 次): 数据会流经一堆完全相同的 Encoder Block (比如 T5-small 有6个)。在每一个 Block 中,数据会经历:
    a. 多头自注意力 (Multi-Head Self-Attention):
    * 目的: 计算输入序列中所有词语之间的关联度。
    * 流程: 对于 “cat” 这个词的向量,自注意力机制会计算它和 “translate”, “English”, …, “mat” 等所有其他词的 “关注分数”。如果发现 “sat on the mat” 和 “cat” 关系密切,那么这些词的向量信息就会更多地融入到 “cat” 的新向量中。
    * 关键点: 这里的查询(Query)、键(Key)、值(Value)都来源于同一个地方——上一个 Block 的输出。它是在 “自己看自己”,从而理解内部的语法和语义关系。详情见大模型学习入门——Day3:注意力机制
    b. 残差连接 & RMSNorm (Add & Norm):
    * 将自注意力的输出与该 Block 的输入相加(残差连接),然后用 RMSNorm 进行归一化。这能防止网络过深时梯度消失或爆炸,稳定训练。
    RMSNorm (Root Mean Square Normalization)

    其数学公式为:
    RMSNorm ( x ) = x 1 n ∑ i = 1 n x i 2 + ϵ ⋅ γ \text{RMSNorm}(x) = \frac{x}{\sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2 + \epsilon}} \cdot \gamma RMSNorm(x)=n1i=1nxi2+ϵ xγ

    其中:

    • x x x 是输入向量
    • n n n 是向量的维度
    • g a m m a \\gamma gamma 是一个可学习的缩放参数
    • e p s i l o n \\epsilon epsilon 是一个防止除以零的小常数

    c. 前馈神经网络 (Feed-Forward Network):
    * 对每个位置的向量进行一次非线性变换,进一步提取特征。可以理解为一个简单的两层全连接神经网络。
    d. 残差连接 & RMSNorm (Add & Norm):
    * 再次执行 Add & Norm 操作。

  5. Encoder 输出: 当数据流过所有 Encoder Blocks 后,我们得到最终的 encoder_hidden_states。这是一个形状为 (序列长度, 隐藏维度) 的矩阵,比如 (13, 768)。这个矩阵就是 Encoder 对原始输入的完整理解,它将被发送给 Decoder 的每一个 Block 作为“参考资料”。

阶段 3: Decoder栈 (The “Generation” Phase)

Decoder 是一个自回归 (auto-regressive) 的生成器。它的目标是一次生成一个 token,直到生成 </s> 结束符为止。这是最核心也最复杂的部分。

我们来模拟生成第一个词 Die 的过程:

  1. 输入: Decoder 的初始输入是 [0] (起始符)。同样,它会被转换成一个词向量并加上位置编码。

  2. 进入 Decoder Block (循环 N 次): 数据流经所有 Decoder Block,在每一个 Block 中,它会经历三件事
    a. 带掩码的多头自注意力 (Masked Multi-Head Self-Attention):
    * 目的: 让 Decoder 在生成当前词时,只能看到已经生成的词。
    * 流程: 此时输入只有一个词,所以它只能“自己看自己”。当未来生成到第3个词时,这个机制通过一个“遮罩”(Mask)确保它只能看到第1、2个词,不能“偷看”未来的答案。
    * 关键点: 这里的 Q, K, V 同样来源于同一个地方——Decoder 上一个 Block 的输出。
    b. 残差连接 & RMSNorm.

    c. 交叉注意力 (Cross-Attention):
    * 目的: 这是连接 Encoder 和 Decoder 的核心桥梁。它回答了这个问题:“根据我现在想生成的内容(来自a步),我应该去关注原始输入句子中的哪些部分?”
    * 流程:
    * 查询 (Query): 来自于 Decoder 的上一步(Masked Self-Attention)的输出。它代表了 Decoder 当前的需求。
    * 键 (Key) 和 值 (Value): 全部来自于 Encoder 的最终输出 encoder_hidden_states
    * 效果: Decoder 的 Query 会和 Encoder 输出的所有 Key 计算相似度,从而决定从 Value 中提取哪些信息。比如,当它想生成 Die (The) 时,交叉注意力可能会高度关注输入中的 Thecat
    d. 残差连接 & RMSNorm.

    e. 前馈神经网络 & Add & Norm (同Encoder).

  3. Decoder 输出: 当起始符 [0] 流过所有 Decoder Blocks 后,我们得到一个最终的输出向量。

在这里插入图片描述

阶段 4: 最终解码与循环 (Final Output & The Loop)
  1. 线性层 & Softmax:

    • 阶段3得到的 Decoder 输出向量会被送入一个最终的线性层,这个线性层的输出维度等于整个词汇表的大小(比如32128)。
    • 然后通过 Softmax 函数,将这个输出转换成一个概率分布。每个词都有一个概率值,概率最高的那个词就是我们预测的下一个词。
    • 预测结果: Die (ID: 5851)
  2. 循环继续:

    • 现在,模型已经生成了第一个词 Die。它会将这个新生成的词的 ID [5851] 添加到 Decoder 的输入中。
    • 下一次循环中,Decoder 的输入就变成了 [0, 5851]
    • 整个阶段3会重新执行一遍,用 [0, 5851] 作为输入,去预测下一个词 Katze
    • 这个过程不断重复 ([0, 5851, 13795] -> saß …),直到模型生成 </s> 结束符,或者达到预设的最大长度。

这样,通过 Encoder 的一次性全面理解和 Decoder 的逐字生成与参考,T5 就完成了从输入文本到输出文本的完整转换。

预训练任务:更智能的“完形填空”

T5 的强大能力源于其在大规模无标注文本上的预训练。它使用的预训练数据集是谷歌自己构建的 C4 (Colossal Clean Crawled Corpus),一个约 750GB 的高质量英文文本数据集。

其预训练任务是对 BERT 的 MLM (Masked Language Model) 的一种改进,通常称为 Span Corruption (跨度损坏)

它和 BERT 的 MLM 有何不同?

  • BERT 的做法: 随机遮盖 15% 的词(Token),并用 [MASK] 标签替换。
    • My name is [MASK] and I live in [MASK].
  • T5 的做法: 随机遮盖一段连续的文本(Span),并用一个唯一的哨兵令牌 (sentinel token),如 <extra_id_0><extra_id_1> 等来替换。然后,让解码器按顺序生成所有被遮盖的文本段。

举个例子:

  • 原始文本: Thank you for inviting me to your party tonight.
  • 损坏后的输入 (Input): Thank you <extra_id_0> me to your party <extra_id_1>.
  • 目标输出 (Target): <extra_id_0> for inviting <extra_id_1> tonight <extra_id_2>

这种方式有两个好处:

  1. 更难的任务: 模型需要预测一整段文本,而不仅仅是单个词,这促使模型学习更好的语言结构和连贯性。
  2. 固定的输出格式: 无论遮盖了多少内容,目标输出始终是一个清晰的、由哨兵令牌和文本组成的序列,完美契合其 Text-to-Text 的思想。

需要注意: T5在预训练阶段不需要指定任务前缀。

T5 代码实战

理论讲了这么多,让我们用 Hugging Face transformers 库来实际操作一下。下面的 Python 代码展示了如何用同一个 T5 模型完成翻译、摘要和问答任务。

首先,确保你已经安装了必要的库:

pip install transformers sentencepiece torch
代码示例
import torch
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
import os

# 解决连不上huggingface的问题
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

# 1. 加载预训练的 T5 模型和分词器
model_name = 'google-t5/t5-base'
tokenizer = AutoTokenizer.from_pretrained(
    model_name
    )
model = AutoModelForSeq2SeqLM.from_pretrained(
    model_name,
    torch_dtype=torch.float16,
    device_map="auto"
    )

# 封装一个函数来执行T5的文本到文本任务
def run_t5_task(task_prefix, text_input, max_length=128):
    """
    使用T5模型执行指定的文本到文本任务。
    
    参数:
    - task_prefix: 任务前缀,如 "translate English to German: "
    - text_input: 待处理的文本
    - max_length: 生成文本的最大长度
    """
    # 组合前缀和输入文本
    input_text = f"{task_prefix}{text_input}"
    
    # 2. 对输入进行分词 (Tokenization)
    input_ids = tokenizer(input_text, return_tensors="pt").input_ids
    
    # 3. 模型生成输出
    # T5是Encoder-Decoder模型,使用 .generate() 方法
    outputs = model.generate(input_ids, max_length=max_length)
    
    # 4. 解码输出,得到人类可读的文本
    decoded_output = tokenizer.decode(outputs[0], skip_special_tokens=True)
    
    print(f"任务: {task_prefix.strip()}")
    print(f"输入: '{text_input}'")
    print(f"输出: '{decoded_output}'\n")

# --- 任务1: 翻译 (English to German) ---
translate_prefix = "translate English to German: "
english_text = "The house is wonderful."
run_t5_task(translate_prefix, english_text)

# --- 任务2: 文本摘要 ---
summarize_prefix = "summarize: "
long_text = (
    "The James Webb Space Telescope (JWST) is a space telescope designed primarily to conduct "
    "infrared astronomy. As the largest optical telescope in space, its high resolution and "
    "sensitivity allow it to view objects too old, distant, or faint for the Hubble Space Telescope. "
    "This will enable investigations in many fields of astronomy and cosmology, such as observation "
    "of the first stars and the formation of the first galaxies, and detailed atmospheric "
    "characterization of potentially habitable exoplanets."
)
run_t5_task(summarize_prefix, long_text, max_length=60)

# --- 任务3: 语法纠错 (CoLA - Corpus of Linguistic Acceptability) ---
cola_prefix = "cola sentence: "
cola_sentence_correct = "This is a correct sentence."
cola_sentence_incorrect = "This sentence has has a mistake."
run_t5_task(cola_prefix, cola_sentence_correct)
run_t5_task(cola_prefix, cola_sentence_incorrect)

总结

T5 模型通过其“大一统”的 Text-to-Text 思想,成功地将各种复杂的 NLP 任务简化为一个统一的框架。它不仅继承了 Transformer 强大的 Encoder-Decoder 结构,还通过创新的预训练任务学习到了深厚的语言知识。

T5 的出现,不仅在多个 NLP 基准测试中取得了顶尖性能,更重要的是,它为后续的多任务、多模态大模型的发展铺平了道路,证明了通过一个通用接口处理多样化任务的可行性和巨大潜力。理解 T5,就是理解现代大语言模型演进道路上的一个关键里程碑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值