006 《注意力机制与Transformer:原理、模型与应用深度解析》
🌟🌟🌟本文由Gemini 2.5 Flash Preview 04-17生成,用来辅助学习。🌟🌟🌟
书籍大纲
▮▮ 1. 引言:为何注意力机制和Transformer如此重要?
▮▮▮▮ 1.1 人工智能的发展历程回顾
▮▮▮▮ 1.2 序列建模的挑战与瓶颈
▮▮▮▮ 1.3 注意力机制的提出与初步应用
▮▮▮▮ 1.4 Transformer模型的横空出世及其影响
▮▮▮▮ 1.5 本书结构与阅读指南
▮▮ 2. 注意力机制:核心原理与分类
▮▮▮▮ 2.1 注意力机制的基本思想
▮▮▮▮ 2.2 经典的注意力机制模型
▮▮▮▮▮▮ 2.2.1 加性注意力 (Additive Attention)
▮▮▮▮▮▮ 2.2.2 点积注意力 (Dot-Product Attention)
▮▮▮▮▮▮ 2.2.3 缩放点积注意力 (Scaled Dot-Product Attention)
▮▮▮▮ 2.3 自注意力机制 (Self-Attention)
▮▮▮▮ 2.4 注意力机制在Encoder-Decoder模型中的应用
▮▮ 3. Transformer模型架构深度解析
▮▮▮▮ 3.1 Transformer整体结构概述
▮▮▮▮ 3.2 编码器 (Encoder) 详解
▮▮▮▮▮▮ 3.2.1 输入嵌入与位置编码 (Input Embedding and Positional Encoding)
▮▮▮▮▮▮ 3.2.2 多头自注意力层 (Multi-Head Self-Attention Layer)
▮▮▮▮▮▮ 3.2.3 前馈神经网络 (Feed-Forward Network)
▮▮▮▮▮▮ 3.2.4 残差连接与层归一化 (Residual Connection and Layer Normalization)
▮▮▮▮ 3.3 解码器 (Decoder) 详解
▮▮▮▮▮▮ 3.3.1 解码器输入与位置编码
▮▮▮▮▮▮ 3.3.2 带掩码的多头自注意力层 (Masked Multi-Head Self-Attention)
▮▮▮▮▮▮ 3.3.3 编码器-解码器注意力层 (Encoder-Decoder Attention)
▮▮▮▮▮▮ 3.3.4 前馈神经网络与Add & Norm
▮▮▮▮▮▮ 3.3.5 线性层与Softmax输出
▮▮▮▮ 3.4 参数共享与计算效率
▮▮ 4. Transformer模型训练与优化
▮▮▮▮ 4.1 训练目标与损失函数
▮▮▮▮ 4.2 优化器选择与配置
▮▮▮▮ 4.3 学习率调度策略 (Learning Rate Scheduling)
▮▮▮▮ 4.4 正则化技术 (Regularization Techniques)
▮▮▮▮ 4.5 序列生成策略 (Sequence Generation Strategies)
▮▮ 5. Transformer的变体与家族
▮▮▮▮ 5.1 预训练语言模型 (Pre-trained Language Models) 的兴起
▮▮▮▮ 5.2 仅编码器模型 (Encoder-only Models)
▮▮▮▮▮▮ 5.2.1 BERT及其变体 (RoBERTa, ALBERT, ELECTRA等)
▮▮▮▮▮▮ 5.2.2 应用场景:文本分类、命名实体识别等
▮▮▮▮ 5.3 仅解码器模型 (Decoder-only Models)
▮▮▮▮▮▮ 5.3.1 GPT系列 (GPT-1, GPT-2, GPT-3, GPT-4等)
▮▮▮▮▮▮ 5.3.2 应用场景:文本生成、对话系统等
▮▮▮▮ 5.4 编码器-解码器模型 (Encoder-Decoder Models)
▮▮▮▮▮▮ 5.4.1 T5与文本到文本框架
▮▮▮▮▮▮ 5.4.2 BART与去噪自编码预训练
▮▮▮▮▮▮ 5.4.3 应用场景:机器翻译、文本摘要等
▮▮▮▮ 5.5 高效Transformer (Efficient Transformers)
▮▮ 6. Transformer在多领域的应用
▮▮▮▮ 6.1 自然语言处理 (NLP)
▮▮▮▮ 6.2 计算机视觉 (Computer Vision)
▮▮▮▮ 6.3 语音处理 (Speech Processing)
▮▮▮▮ 6.4 生物信息学 (Bioinformatics)
▮▮▮▮ 6.5 跨模态学习 (Cross-modal Learning)
▮▮ 7. 实践指南:使用Transformer模型
▮▮▮▮ 7.1 主流框架中的实现 (Implementations in Major Frameworks)
▮▮▮▮ 7.2 拥抱Hugging Face Transformers库
▮▮▮▮ 7.3 使用预训练模型与微调 (Fine-tuning Pre-trained Models)
▮▮▮▮ 7.4 从头开始训练Transformer模型
▮▮▮▮ 7.5 模型评估与分析
▮▮▮▮ 7.6 模型部署与优化
▮▮ 8. 高级话题、理论分析与未来展望
▮▮▮▮ 8.1 注意力机制的理论解释
▮▮▮▮ 8.2 Transformer模型的可解释性 (Interpretability)
▮▮▮▮ 8.3 Transformer的局限性与挑战
▮▮▮▮ 8.4 与符号主义AI的结合
▮▮▮▮ 8.5 未来研究方向
▮▮ 9. 结论
▮▮▮▮ 9.1 本书核心知识点回顾
▮▮▮▮ 9.2 Transformer时代的机遇与挑战
▮▮▮▮ 9.3 持续学习与探索的建议
▮▮ 附录A: 术语表 (Glossary)
▮▮ 附录B: 参考文献 (References)
▮▮ 附录C: 常用资源与工具 (Resources and Tools)
▮▮ 附录D: 代码示例 (Code Examples)
1. 引言:为何注意力机制和Transformer如此重要?
欢迎来到《注意力机制与Transformer:原理、模型与应用深度解析》这本书。在这个计算能力爆炸式增长、数据呈海量涌现的时代,深度学习(Deep Learning)技术以前所未有的速度推动着人工智能(Artificial Intelligence, AI)的发展。在众多革新性的技术中,注意力机制(Attention Mechanism)和 Transformer 模型无疑是近几年来最为耀眼的明星技术之一。它们不仅在自然语言处理(Natural Language Processing, NLP)领域取得了突破性的进展,更迅速扩展到计算机视觉(Computer Vision)、语音处理(Speech Processing)、生物信息学(Bioinformatics)等多个领域,成为现代人工智能技术栈中不可或缺的基石。本章作为全书的开篇,旨在帮助读者理解注意力机制和 Transformer 模型出现的技术背景、它们解决了哪些关键问题,以及为何它们能够引发如此深远的影响。我们将简要回顾AI的发展历程,探讨传统序列建模面临的挑战,引出注意力机制的思想,并重点介绍 Transformer 模型的诞生及其带来的变革。最后,我们将概述本书的结构,并为不同背景的读者提供阅读建议。
1.1 人工智能的发展历程回顾
人工智能的梦想由来已久,从早期的符号主义(Symbolism AI)到专家系统(Expert Systems),人类一直在探索如何让机器拥有智能。然而,直到神经网络(Neural Networks)的兴起,特别是深度学习的崛起,人工智能才真正迎来爆发式发展。
① 早期神经网络与浅层学习(Early Neural Networks and Shallow Learning)
▮▮▮▮人工神经网络(Artificial Neural Networks, ANNs)的概念源于对生物神经元的模拟。感知机(Perceptron)是早期的尝试,但受限于计算能力和理论不足,一度陷入低谷(即“AI冬天”)。
▮▮▮▮20世纪80-90年代,反向传播算法(Backpropagation)的提出重新燃起了研究热情,使得训练具有隐藏层的神经网络成为可能,例如多层感知机(Multi-Layer Perceptron, MLP)。但受限于计算资源和数据量,这些“浅层”模型难以处理复杂的高维数据。
② 深度学习的兴起
▮▮▮▮进入21世纪,随着计算能力的提升(尤其是 GPU 的发展)、海量数据的可用以及新的训练技术(如 ReLU 激活函数、Dropout 正则化、Adam 优化器等)的出现,深度学习克服了浅层网络的诸多限制。
▮▮▮▮卷积神经网络(Convolutional Neural Networks, CNN)在图像识别任务上取得了巨大成功,其核心思想是利用卷积层(Convolutional Layer)和池化层(Pooling Layer)来提取图像的局部特征并逐层抽象。CNN的参数共享(Parameter Sharing)和局部连接(Local Connectivity)特性使其在处理图像、视频等网格状数据时表现出色。
▮▮▮▮循环神经网络(Recurrent Neural Networks, RNN)及其变体(如长短期记忆网络 Long Short-Term Memory, LSTM 和门控循环单元 Gated Recurrent Unit, GRU)则在处理序列数据(Sequential Data)方面展现了强大能力,例如自然语言、时间序列等。RNN通过隐藏状态(Hidden State)在序列中的传播,理论上可以捕捉序列的长期依赖(Long-Range Dependencies)。
③ CNN和RNN的局限性
▮▮▮▮尽管 CNN 和 RNN 取得了巨大成功,但它们在处理特定任务时也暴露出了局限性。CNN主要关注局部信息,难以直接处理变长序列的全局依赖。RNN 虽然理论上能处理序列依赖,但在实践中,尤其是在处理非常长的序列时,其捕捉长距离依赖的能力会显著下降,并且由于其固有的循环结构,难以实现高效的并行计算(Parallel Computation),这成为了训练大规模RNN模型的瓶颈。
1.2 序列建模的挑战与瓶颈
序列建模是许多核心AI任务的基础,例如机器翻译(Machine Translation)、语音识别(Speech Recognition)、文本摘要(Text Summarization)、问答系统(Question Answering)等。传统上,RNN及其变体 LSTM 和 GRU 是处理这类任务的主力模型,通常采用编码器-解码器(Encoder-Decoder)架构。
① RNN/LSTM/GRU 在序列建模中的工作方式
▮▮▮▮编码器(Encoder)逐个读取输入序列的元素,并将整个序列的信息压缩到一个固定长度的隐藏状态向量(Context Vector)中。
▮▮▮▮解码器(Decoder)接收编码器的上下文向量,并逐步生成输出序列的元素。
② 面临的核心挑战
▮▮▮▮长距离依赖问题(Long-Range Dependencies Problem):RNN通过时间步(Time Step)传递信息。当序列很长时,早期时间步的信息在经过多次传递后可能会逐渐衰减或被稀释,导致模型难以有效地捕捉到距离较远的元素之间的关联,即所谓的“梯度消失”(Vanishing Gradient)问题。LSTM和GRU在一定程度上缓解了这个问题,但并未完全解决。
▮▮▮▮固定长度的上下文向量(Fixed-length Context Vector):在基本的 Encoder-Decoder 模型中,输入序列的所有信息被编码成一个固定长度的向量。这对于较长的输入序列来说,难以包含所有重要的信息,形成信息瓶颈。
▮▮▮▮并行计算的限制(Limited Parallelism):RNN的计算是顺序进行的,即计算当前时间步的隐藏状态依赖于前一个时间步的隐藏状态。这种固有的循环结构使得在单个序列内部很难进行大规模并行计算,从而限制了模型的训练速度和可扩展性。虽然可以在批处理(Batch Processing)层面进行并行,但序列内部的顺序性仍然是瓶颈。
这些挑战促使研究者寻找新的模型架构,以便更有效地处理长序列、捕捉复杂的依赖关系,并提升训练效率。
1.3 注意力机制的提出与初步应用
为了解决传统 Encoder-Decoder 模型在处理长序列时遇到的信息瓶颈和长距离依赖问题,注意力机制应运而生。
① 注意力机制的核心思想
▮▮▮▮注意力机制模仿人类认知系统的选择性注意(Selective Attention)能力。当我们阅读一篇文章或观察一幅图片时,我们会将注意力集中在当前最相关或最重要的信息上,而不是平均地关注所有信息。
▮▮▮▮将这一思想应用到序列模型中,注意力机制允许模型在处理序列的某个元素时,能够“回顾”并“关注”输入序列中与之相关的部分,并从中提取信息。
▮▮▮▮具体来说,注意力机制通过计算输入序列中各个元素与当前处理的输出元素之间的“相关性”或“重要性”权重,然后根据这些权重对输入序列的隐藏状态进行加权求和,从而得到一个更有针对性的上下文向量。
② 注意力机制的初步应用:改进 RNN Encoder-Decoder 模型
▮▮▮▮注意力机制最早在2015年被 Bahdanau 等人应用于机器翻译任务,结合 RNN Encoder-Decoder 模型。
▮▮▮▮在这种架构中,解码器在生成每个目标词时,不再仅仅依赖于编码器最终的固定上下文向量,而是根据当前已生成的目标词和编码器中每个输入词的隐藏状态,动态地计算一个注意力分布(Attention Distribution),然后基于这个分布对所有输入词的隐藏状态进行加权平均,得到一个随当前输出词变化而变化的上下文向量。
▮▮▮▮这种机制使得模型能够“对齐”(Align)输入序列和输出序列的相关部分,显著提高了机器翻译的性能,特别是在处理长句子时。
③ 注意力机制作为一种通用思想
▮▮▮▮注意力机制的核心思想是“加权求和”,即通过计算权重来选择性地汇聚信息。这种思想非常通用,可以应用于各种模态的数据和不同的任务中,而不仅仅局限于 RNN Encoder-Decoder 结构。它的成功为后续 Transformer 模型的出现奠定了基础。
1.4 Transformer模型的横空出世及其影响
注意力机制在改进 RNN 模型方面取得了巨大成功,但这只是一个开始。2017年,Vaswani 等人在论文《Attention Is All You Need》中提出了 Transformer 模型,彻底改变了序列建模的范式。
① Transformer 的核心创新:完全抛弃循环和卷积
▮▮▮▮与传统的序列模型不同,Transformer 模型完全基于注意力机制(尤其是自注意力机制 Self-Attention)和前馈神经网络(Feed-Forward Networks),完全移除了循环(Recurrence)和卷积(Convolution)。
▮▮▮▮这意味着 Transformer 模型不再需要按顺序处理序列元素,而是可以并行地计算序列中所有位置的表示。
② Transformer 的关键优势
▮▮▮▮更好的并行性:由于没有循环结构,Transformer 的计算可以高度并行化,极大地提高了训练效率,使得训练更大规模的模型成为可能。
▮▮▮▮更有效地捕捉长距离依赖:自注意力机制允许模型直接计算序列中任意两个位置之间的关联度,无论它们在序列中的距离有多远。这克服了 RNN/LSTM 在处理长距离依赖方面的根本性问题。
▮▮▮▮更强的表示能力:通过堆叠多个注意力层和前馈网络层,Transformer 模型能够学习到输入序列更丰富、更抽象的表示。
③ Transformer 带来的革命性影响
▮▮▮▮NLP 领域的统治者:Transformer 迅速成为自然语言处理领域的标准模型架构。基于 Transformer 的预训练语言模型(Pre-trained Language Models),如 BERT、GPT 系列、T5 等,通过在海量无标注文本数据上进行预训练,学习通用的语言表示,然后在各种下游任务(如文本分类、命名实体识别、问答、文本生成等)上进行微调(Fine-tuning),取得了前所未有的SOTA(State-of-the-Art,当前最优)性能。
▮▮▮▮跨领域的扩散:Transformer 的成功并非局限于 NLP。研究者们发现可以通过适当的方式将其他模态的数据转化为序列形式,然后应用 Transformer 进行处理。例如,Vision Transformer (ViT) 将图像分割成小块并视为序列,成功应用于计算机视觉任务;类似的思想也被应用于语音处理、生物信息学等领域,并取得了突破性进展(如 AlphaFold 在蛋白质结构预测上的成功)。
▮▮▮▮模型规模的爆炸式增长:Transformer 的并行计算能力促进了模型规模的不断扩大,参数量从几亿到几千亿甚至万亿,催生了大型语言模型(Large Language Models, LLMs),这些模型展现出了惊人的零样本(Zero-shot)和少样本(Few-shot)学习能力,并开启了AI生成内容(Artificial Intelligence Generated Content, AIGC)的新时代。
可以说,注意力机制是改进传统序列模型的重要思想,而 Transformer 模型则是将这一思想发挥到极致并引发AI领域深刻变革的关键架构。理解它们的工作原理对于掌握现代深度学习技术至关重要。
1.5 本书结构与阅读指南
本书旨在系统而深入地讲解注意力机制和 Transformer 模型,适合从入门到进阶直至希望深入研究的各类读者。
① 本书结构概述
▮▮▮▮第1章 (引言):介绍背景、动机和本书概览(即您正在阅读的这一章)。
▮▮▮▮第2章 (注意力机制):详细讲解注意力机制的基本原理、数学表达式以及不同类型(如加性注意力、点积注意力、自注意力)及其早期应用。
▮▮▮▮第3章 (Transformer模型架构):本书的核心章节,逐层、逐模块地深度剖析 Transformer 模型的编码器和解码器结构,包括多头注意力(Multi-Head Attention)、位置编码(Positional Encoding)、前馈网络、残差连接(Residual Connection)和层归一化(Layer Normalization)等关键组件。
▮▮▮▮第4章 (Transformer模型训练与优化):讨论训练 Transformer 模型时的实践细节,如损失函数、优化器、学习率调度、正则化技术以及推理阶段的生成策略。
▮▮▮▮第5章 (Transformer的变体与家族):介绍基于 Transformer 架构演变出的各类重要模型,如 BERT、GPT 系列、T5 等,并分析它们的特点和应用场景。
▮▮▮▮第6章 (Transformer在多领域的应用):展示 Transformer 模型如何在自然语言处理、计算机视觉、语音处理、生物信息学等多个领域落地开花。
▮▮▮▮第7章 (实践指南):提供实用的代码实践指导,包括如何在主流深度学习框架中使用和微调 Transformer 模型(重点介绍 Hugging Face Transformers 库)。
▮▮▮▮第8章 (高级话题与未来展望):探讨关于 Transformer 的一些更深层次的话题,如模型的理论解释、可解释性、局限性以及未来的研究方向。
▮▮▮▮第9章 (结论):总结全书内容,并对读者未来的学习和实践提供建议。
▮▮▮▮附录 (Appendices):提供术语表、参考文献、常用资源和代码示例等辅助信息。
② 目标读者分级与阅读建议
本书力求兼顾不同水平的读者,但涉及一些数学公式和深度学习基础知识。
▮▮▮▮初学者(Beginners):如果您刚接触深度学习或对注意力机制和 Transformer 只有初步了解,建议重点阅读 第1、2、3、7章。这几章将为您建立扎实的理论基础和实践框架。对于第3章,可以先把握整体架构和各模块的功能,不必一次性深究所有数学细节。
▮▮▮▮中级读者(Intermediate):如果您对深度学习有一定基础,接触过 RNN/CNN,并希望深入理解 Transformer 的工作原理和应用,建议通读 全书。可以重点关注 第3、4、5、6、7章,并通过实践代码加深理解。
▮▮▮▮专家(Experts):如果您已经是深度学习领域的专家或研究人员,本书可以作为系统回顾和查阅资料的参考。可以快速浏览基础章节,重点关注 第5、6、8章 中的最新模型、跨领域应用、高级话题和未来展望,并参考附录中的参考文献。
无论您的背景如何,都建议在阅读过程中:
⚝ 结合图示理解模型结构和数据流。
⚝ 对于数学公式,理解其背后的思想和计算过程,而不是死记硬背。
⚝ 尝试运行书中的代码示例,或利用公开资源(如 Hugging Face 库)亲自动手实践,加深对理论的理解。
⚝ 积极思考各部分设计的原因以及它们如何协同工作。
希望本书能够帮助您全面、深入地掌握注意力机制和 Transformer 模型这一强大的技术,并激发您在该领域的进一步探索和创新。让我们一起开启这段精彩的学习旅程吧!💪📖
2. 注意力机制:核心原理与分类
本章将带领读者深入注意力机制(Attention Mechanism)的核心世界。注意力机制是现代深度学习,特别是处理序列数据(如文本、语音)和复杂结构数据(如图像)任务中一个至关重要的概念。它赋予了模型在处理信息时,“关注”到输入中最相关或最重要的部分的能力,从而极大地提升了模型的性能和解释性。本章将详细讲解注意力机制的基本数学原理,不同类型的注意力机制及其在各种模型中的应用方式。
2.1 注意力机制的基本思想
人类在处理信息时,往往不是平均地接收和处理所有信息,而是会根据当前的需要或目标,有选择地将注意力集中在某些特定的区域或信息源上。例如,当我们阅读一篇文章时,我们会根据句子的结构和含义,将注意力放在关键词上;当我们在拥挤的房间里寻找某个朋友时,我们会专注于面部特征,而忽略背景中的其他人。这种选择性关注的能力,使我们能够高效地处理复杂信息,忽略不相关内容,并快速找到关键信息。
注意力机制在深度学习中的基本思想正是模仿了人类这种“注意力”的行为。模型在处理输入序列或数据时,不是机械地对所有输入元素一视同仁,而是能够动态地分配不同的“注意力权重”(Attention Weights)给不同的输入部分。权重高的部分表示模型认为这些部分对当前任务更重要,应该给予更多关注;权重低的部分则相对不那么重要。
具体来说,注意力机制通常包含以下核心步骤:
① 计算注意力分数(Attention Scores):衡量输入序列中的某个元素与当前正在处理的查询(Query)元素之间的关联程度。这个分数越高,表示两者越相关。
② 通过 Softmax 函数或其他归一化方法将注意力分数转化为注意力权重:这些权重是介于 0 和 1 之间的数值,且所有权重的和为 1。这些权重代表了模型在处理当前信息时,对输入序列中每个元素的关注程度。
③ 使用注意力权重对输入序列的元素进行加权求和:得到一个加权的表示向量,这个向量融合了输入序列中所有元素的信息,但侧重于那些注意力权重高的元素。
通过这种方式,模型可以:
⚝ 在处理长序列时,避免将所有信息压缩成一个固定大小的向量,从而缓解 RNN/LSTM 等模型在处理长距离依赖(Long-Range Dependencies)时遇到的瓶颈。
⚝ 动态地调整对输入不同部分的关注程度,使得模型能够更灵活地适应不同的输入和任务。
⚝ 提升模型的可解释性(Interpretability),因为我们可以分析注意力权重的分布,了解模型在做决策时主要“看”的是哪些输入部分。
注意力机制的提出,为解决传统序列模型(Sequential Models)的局限性提供了新的思路,并为 Transformer 等新型网络架构奠定了基础。
2.2 经典的注意力机制模型
注意力机制的数学实现有多种方式,其中最经典和常用的包括加性注意力(Additive Attention)和点积注意力(Dot-Product Attention)。这两种机制在计算注意力分数(Attention Scores)的方式上有所不同。在 Transformer 模型中,使用了一种称为缩放点积注意力(Scaled Dot-Product Attention)的变体。
这两种注意力机制的核心思想都是根据一个“查询”(Query, \(Q\))、一组“键”(Keys, \(K\)) 和一组“值”(Values, \(V\)) 来计算加权平均的值。在序列处理任务中,Query 通常代表当前要处理的元素或状态,Keys 代表输入序列中所有元素的标识或特征,而 Values 则代表输入序列中所有元素的实际信息内容。模型通过比较 Query 和 Keys 来计算注意力分数,然后用这些分数对 Values 进行加权求和。
\[ \text{Attention}(Q, K, V) = \sum_{i=1}^{L} \text{AttentionWeight}(Q, K_i) \cdot V_i \]
其中,\(L\) 是输入序列的长度,\(K_i\) 和 \(V_i\) 分别是 Keys 和 Values 序列中的第 \(i\) 个元素。注意力权重的计算是关键,下面我们分别看几种经典的计算方式。
2.2.1 加性注意力 (Additive Attention)
加性注意力(Additive Attention),也被称为 Bahdanau 注意力,是最早被广泛应用的注意力机制之一。它由 Dzmitry Bahdanau 等人在 2014 年的论文《Neural Machine Translation by Jointly Learning to Align and Translate》中提出,用于改进基于 RNN 的机器翻译模型。
加性注意力的核心思想是使用一个前馈神经网络(Feed-Forward Network)来计算 Query 和 Key 之间的注意力分数。具体来说,它首先将 Query 和 Key 向量连接起来(或者分别通过不同的线性变换),然后通过一个隐藏层为 \(tanh\) 激活函数的前馈网络,最后通过一个线性层得到一个标量的分数。
数学表达式如下:
\[ \text{Score}(Q, K_i) = \mathbf{v}_a^\top \tanh(\mathbf{W}_q Q + \mathbf{W}_k K_i + \mathbf{b}_a) \]
其中:
⚝ \(Q\) 是 Query 向量。
⚝ \(K_i\) 是 Keys 序列中的第 \(i\) 个 Key 向量。
⚝ \(\mathbf{W}_q\),\(\mathbf{W}_k\),\(\mathbf{v}_a\),\(\mathbf{b}_a\) 都是待学习的参数矩阵、向量和偏置项。
⚝ \(\tanh\) 是激活函数。
在计算得到所有 Query 和 \(K_i\) 之间的分数 \(\text{Score}(Q, K_i)\) 后,使用 Softmax 函数将这些分数归一化,得到注意力权重 \(\alpha_i\):
\[ \alpha_i = \text{Softmax}(\text{Score}(Q, K_i)) = \frac{\exp(\text{Score}(Q, K_i))}{\sum_{j=1}^L \exp(\text{Score}(Q, K_j))} \]
最终的加权 Values 向量 \(C\) 是所有 \(V_i\) 基于权重 \(\alpha_i\) 的加权求和:
\[ C = \sum_{i=1}^L \alpha_i V_i \]
加性注意力的优点在于它理论上能够处理 Query 和 Key 维度不同的情况,并且由于引入了非线性激活函数,其表达能力可能更强。缺点是计算成本相对较高,需要更多的参数。它在早期的机器翻译模型中取得了显著成功。
2.2.2 点积注意力 (Dot-Product Attention)
点积注意力(Dot-Product Attention),也被称为乘性注意力(Multiplicative Attention),是一种更简洁高效的注意力形式。它通过计算 Query 向量与 Key 向量之间的点积来衡量它们之间的关联程度。
数学表达式如下:
\[ \text{Score}(Q, K_i) = Q \cdot K_i \]
或者使用矩阵乘法表示 Query \(Q\) 与整个 Keys 矩阵 \(K\)(每一行是一个 Key 向量)的分数计算:
\[ \text{Scores} = QK^\top \]
其中,\(Q\) 是 Query 向量(或表示多个 Query 的矩阵),\(K\) 是 Keys 矩阵。这里要求 Query 和 Key 向量的维度必须相同。
计算得到分数后,同样使用 Softmax 函数将分数归一化为注意力权重:
\[ \alpha_i = \text{Softmax}(\text{Score}(Q, K_i)) = \frac{\exp(Q \cdot K_i)}{\sum_{j=1}^L \exp(Q \cdot K_j)} \]
然后使用这些权重对 Values 进行加权求和:
\[ C = \sum_{i=1}^L \alpha_i V_i \]
点积注意力的优点是计算简单高效,特别是在使用矩阵乘法时,可以利用高度优化的线性代数库进行加速。它不需要额外的参数来计算注意力分数(除了 Query、Key、Value 自身的线性变换可能需要的参数)。缺点是在 Query 和 Key 向量维度较高时,点积结果的方差可能会很大,导致 Softmax 函数的输入值( logits )变得很大或很小,使得梯度变得非常小,不利于训练。
2.2.3 缩放点积注意力 (Scaled Dot-Product Attention)
缩放点积注意力(Scaled Dot-Product Attention)是点积注意力的一种改进,也是 Transformer 模型中采用的注意力形式。为了解决高维度下点积结果方差过大的问题,它在计算点积之后,会除以一个缩放因子。
这个缩放因子通常是 Key 向量维度 \(d_k\) 的平方根,即 \(\sqrt{d_k}\)。
数学表达式如下:
\[ \text{Score}(Q, K_i) = \frac{Q \cdot K_i}{\sqrt{d_k}} \]
使用矩阵乘法表示:
\[ \text{Scores} = \frac{QK^\top}{\sqrt{d_k}} \]
其中,\(Q\) 是 Query 矩阵,\(K\) 是 Keys 矩阵,\(d_k\) 是 Key 向量的维度。
同样,注意力权重通过 Softmax 计算:
\[ \alpha = \text{Softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right) \]
最终的加权 Values 向量 \(C\) 是权重矩阵 \(\alpha\) 与 Values 矩阵 \(V\) 的乘积:
\[ C = \alpha V \]
缩放点积注意力的优点继承了点积注意力的计算效率,并且通过缩放因子有效地控制了分数的范围,使得 Softmax 的输入更加稳定,缓解了梯度消失的问题,有利于模型训练。Transformer 模型正是依赖于这种高效且稳定的注意力形式。
2.3 自注意力机制 (Self-Attention)
自注意力机制(Self-Attention),也称为内部注意力(Intra-Attention),是一种特殊的注意力机制,它的 Query、Keys 和 Values 都来自于同一个输入序列。换句话说,模型不是去关注外部的另一个序列(如机器翻译中,解码器关注编码器的输出),而是关注输入序列内部不同位置之间的关联。
在自注意力机制中,输入序列 \(X = (x_1, x_2, \dots, x_L)\) 中的每一个元素 \(x_i\) 都会生成一个 Query \(q_i\)、一个 Key \(k_i\) 和一个 Value \(v_i\)。这些 \(q_i, k_i, v_i\) 通常是通过对原始输入向量 \(x_i\) 进行线性变换得到的:
\[ q_i = x_i \mathbf{W}_Q \]
\[ k_i = x_i \mathbf{W}_K \]
\[ v_i = x_i \mathbf{W}_V \]
其中,\(\mathbf{W}_Q\),\(\mathbf{W}_K\),\(\mathbf{W}_V\) 是待学习的权重矩阵。
然后,对于序列中的每一个位置 \(i\),它的 Query \(q_i\) 会与序列中的所有位置 \(j\) 的 Key \(k_j\) 计算注意力分数。最常见的是使用缩放点积:
\[ \text{Score}(q_i, k_j) = \frac{q_i \cdot k_j}{\sqrt{d_k}} \]
接着,将分数通过 Softmax 归一化得到注意力权重:
\[ \alpha_{ij} = \text{Softmax}_j(\text{Score}(q_i, k_j)) = \frac{\exp(\text{Score}(q_i, k_j))}{\sum_{p=1}^L \exp(\text{Score}(q_i, k_p))} \]
最后,位置 \(i\) 的输出表示 \(y_i\) 是对所有位置 \(j\) 的 Value \(v_j\) 进行加权求和:
\[ y_i = \sum_{j=1}^L \alpha_{ij} v_j \]
通过自注意力机制,模型在计算序列中某个元素的表示时,能够考虑到序列中所有其他元素(包括它自身)的信息,并且这种考虑是动态的、基于数据驱动的。例如,在处理句子“The animal didn't cross the street because it was too tired”时,自注意力机制可以帮助模型学习到“it”这个词与“animal”这个词之间的关联。
自注意力机制的优势包括:
⚝ 能够直接建立序列中任意两个位置之间的联系,不受距离限制,这对于捕捉长距离依赖(Long-Range Dependencies)非常有利。相比之下,RNN 需要通过隐藏状态逐步传递信息,距离越远信息衰减越多。
⚝ 计算是高度并行化的。每个位置的注意力输出可以独立计算,这与 RNN 的序列性计算形成鲜明对比,极大地提高了训练效率。
⚝ 模型的表达能力更强,可以学习到更复杂的特征表示,因为它能够灵活地组合来自序列不同位置的信息。
自注意力机制是 Transformer 模型的核心构建块,也是其在自然语言处理(NLP)等领域取得巨大成功的基础。
2.4 注意力机制在Encoder-Decoder模型中的应用
在 Transformer 模型出现之前,注意力机制就已经被成功地应用于基于循环神经网络(RNN)或长短期记忆网络(LSTM)的编码器-解码器(Encoder-Decoder)模型中,特别是针对序列到序列(Sequence-to-Sequence)任务,如机器翻译。
传统的 RNN/LSTM Encoder-Decoder 模型在处理输入序列时,编码器会将整个输入序列压缩成一个固定长度的“上下文向量”(Context Vector),然后解码器利用这个上下文向量逐步生成输出序列。这种固定长度的上下文向量成为了模型处理长序列时的瓶颈,信息容易丢失。
为了解决这个问题,Bahdanau 等人(2014)提出了将注意力机制引入到 Encoder-Decoder 模型中。在这种架构中:
① 编码器(Encoder)依然是一个 RNN/LSTM 网络,它处理输入序列的每一个元素,并生成一系列的隐藏状态(Hidden States)。这些隐藏状态可以看作是输入序列的“键”(Keys)和“值”(Values)。
② 解码器(Decoder)也是一个 RNN/LSTM 网络,它在生成输出序列的每一个词时,不仅仅依赖于前一个时刻的隐藏状态和已生成的词,还会使用注意力机制来“关注”编码器输出的隐藏状态。
③ 具体来说,解码器在生成当前词的隐藏状态(Query)时,会使用这个 Query 与编码器输出的所有隐藏状态(Keys)计算注意力分数和权重。
④ 然后,用这些注意力权重对编码器输出的隐藏状态(Values)进行加权求和,得到一个动态生成的上下文向量(Context Vector)。这个上下文向量是输入序列的一个加权表示,权重取决于当前解码器需要关注的输入部分。
⑤ 解码器结合其当前隐藏状态、上一个时间步生成的词以及这个动态上下文向量来预测下一个输出词。
\[ \text{ContextVector}_t = \sum_{i=1}^L \alpha_{ti} h_{i}^{\text{encoder}} \]
\[ \alpha_{ti} = \text{AttentionWeight}(\text{DecoderState}_t, h_{i}^{\text{encoder}}) \]
其中,\(\text{DecoderState}_t\) 是解码器在时间步 \(t\) 的隐藏状态(作为 Query),\(h_{i}^{\text{encoder}}\) 是编码器在时间步 \(i\) 的隐藏状态(作为 Key 和 Value)。注意力权重 \(\alpha_{ti}\) 表示解码器在生成时间步 \(t\) 的输出时,对编码器时间步 \(i\) 的输入的关注程度。
通过引入注意力机制,RNN/LSTM Encoder-Decoder 模型能够:
⚝ 在生成每个输出词时,有选择地关注输入序列中最相关的部分,而不是依赖于一个固定的上下文向量。这使得模型能够更好地处理长序列,捕捉远距离的依赖关系。
⚝ 在机器翻译等任务中,注意力机制的权重分布通常可以可视化,显示出输出词与输入词之间的“对齐”(Alignment)关系,提供了模型决策的可解释性。
这种带有注意力的 RNN/LSTM 模型在机器翻译等任务上取得了显著的性能提升,为后来的 Transformer 模型完全基于注意力机制的设计提供了重要的灵感和基础。Transformer 可以看作是抛弃了 RNN/LSTM 的循环结构,完全依赖自注意力和前馈网络来处理序列信息的一种更激进和高效的架构。
3. Transformer模型架构深度解析
欢迎来到本书的核心章节!在第二章中,我们深入探讨了注意力机制的基本原理,理解了它是如何赋予模型关注序列中不同部分的能力。现在,我们将把这一强大的工具——注意力机制,特别是自注意力机制——作为基石,构建一个全新的、革命性的模型架构:Transformer。由 Vaswani 等人于 2017 年在经典论文《Attention Is All You Need》中提出,Transformer 彻底改变了序列建模领域,成为当前大多数最先进深度学习模型的基础,尤其是在自然语言处理(NLP)领域。
本章将以前所未有的细节,带您逐一剖析 Transformer 模型的每一个组成部分。我们将像拆解一台精密机器一样,理解每个模块的功能、内部工作原理,以及它们如何协同工作,共同完成复杂的序列到序列(Sequence-to-Sequence)转换任务。无论您是初学者、希望深入理解模型细节的中级开发者,还是寻求理论洞察的专家,本章都将为您提供清晰、权威的指导。
我们将从 Transformer 的整体架构概览开始,然后分别深入到编码器(Encoder)和解码器(Decoder)的每一个子层,包括输入处理、各种注意力机制、前馈网络、残差连接和层归一化。最后,我们将讨论模型中的参数共享以及其对计算效率的影响。准备好了吗?让我们一起揭开 Transformer 的神秘面纱!🚀
3.1 Transformer整体结构概述
Transformer 模型最初是为了解决机器翻译等序列转换任务而设计的。它的核心思想是完全抛弃了循环(Recurrence)和卷积(Convolution)结构,转而完全依赖于注意力机制(Attention Mechanism)来捕捉输入和输出序列之间的依赖关系。这一大胆的设计使得 Transformer 具备了卓越的并行计算能力,从而能够处理更长的序列并在大规模数据集上进行高效训练。
从宏观上看,Transformer 沿袭了经典的编码器-解码器(Encoder-Decoder)框架。它由以下两个主要部分组成:
① 编码器 (Encoder): 负责处理输入序列。它接收一个序列作为输入,例如一句待翻译的源语言句子,并将其转换成一系列连续的向量表示,这些向量包含了输入序列的语义信息。编码器是一个堆叠结构,由 N 个(原论文中是 N=6)相同的层组成。每一层又包含两个子层:一个多头自注意力机制(Multi-Head Self-Attention)和一个简单的、位置独立的前馈神经网络(Position-wise Feed-Forward Network)。
② 解码器 (Decoder): 负责生成输出序列。它接收编码器的输出(输入的表示)和一个已经生成的部分输出序列(例如已翻译的目标语言词汇),然后预测序列中的下一个词。解码器也是一个堆叠结构,由 N 个(同样是 N=6)相同的层组成。每一层包含三个子层:一个带有掩码的多头自注意力机制(Masked Multi-Head Self-Attention),一个多头编码器-解码器注意力机制(Multi-Head Encoder-Decoder Attention),以及一个位置独立的前馈神经网络。
输入序列首先通过嵌入层(Embedding Layer)转换为稠密的向量表示,然后加入位置编码(Positional Encoding)以保留序列的顺序信息。这个带有位置信息的嵌入向量序列被送入编码器堆栈。
编码器的输出是一系列向量,它们代表了输入序列的上下文丰富表示。这些向量被送入解码器。
解码器接收目标序列的嵌入(在训练时是真实目标序列,在推理时是已生成的部分序列),同样加上位置编码。解码器的带掩码自注意力层允许其关注已生成的部分输出序列。编码器-解码器注意力层则允许解码器的每个位置关注输入序列的所有位置。
最终,解码器堆栈的输出通过一个线性层(Linear Layer)和 Softmax 层,生成目标词汇表上每个词的概率分布,从而预测下一个词。
Transformer 的整体数据流呈现为一个“漏斗”形状:输入序列经过编码器被压缩或转换为高级表示,然后解码器利用这个表示逐步展开,生成输出序列。
下图(此处通常会配一张Transformer整体架构图)概括了 Transformer 的主要组件和数据流。理解这张图是理解整个模型架构的关键第一步。接下来,我们将深入探讨这张图中的每一个“盒子”和“箭头”。
3.2 编码器 (Encoder) 详解
编码器是 Transformer 的左半部分,它的任务是将输入的词语序列转换为一个连续表示的序列。原论文中的编码器由 N=6 个相同的层堆叠而成。每一层都接收其下方(或输入嵌入层)的输出,并产生一个等长的向量序列作为其输出,传递给下一层(或解码器)。
3.2.1 输入嵌入与位置编码 (Input Embedding and Positional Encoding)
在将输入文本序列送入 Transformer 模型之前,需要进行两步重要的预处理:词嵌入和位置编码。
词嵌入 (Word Embedding):
首先,输入序列中的每一个词(或 sub-word,子词)都需要被转换成一个固定维度的稠密向量。这一过程由嵌入层完成。嵌入层本质上是一个查找表,将离散的词汇索引映射到连续的向量空间中。这些嵌入向量的维度,通常记为 \( d_{model} \),是模型的一个重要超参数。在训练过程中,这些嵌入向量会根据模型处理任务的需求进行学习和调整。
将输入序列 \( (x_1, x_2, \dots, x_n) \) 通过嵌入层后,我们得到一个向量序列 \( (\mathbf{v}_1, \mathbf{v}_2, \dots, \mathbf{v}_n) \),其中 \( \mathbf{v}_i \in \mathbb{R}^{d_{model}} \)。
位置编码 (Positional Encoding):
Transformer 模型完全基于注意力机制,而标准的自注意力机制在处理序列时是位置无关的。换句话说,如果简单地打乱输入序列的顺序,自注意力计算的结果将完全一样,因为它们只计算不同词向量之间的相似度。然而,在序列任务(如机器翻译)中,词语的顺序至关重要。为了向模型引入序列中词语的位置信息,Transformer 引入了位置编码。
位置编码是一些与输入嵌入向量维度相同的向量,它们包含了词语在序列中绝对或相对位置的信息。这些位置编码向量被简单地加到对应的词嵌入向量上,形成最终送入编码器第一层的输入。
原论文中采用了正弦(Sine)和余弦(Cosine)函数来生成位置编码。对于位置 \( pos \) 和维度 \( i \)(范围从 0 到 \( d_{model}-1 \)),位置编码的值计算如下:
\[ \begin{align*} PE(pos, 2i) &= \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) \\ PE(pos, 2i+1) &= \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) \end{align*} \]
这种选择的理由:
⚝ 它可以生成任意长度序列的位置编码。
⚝ 它具有周期性,可以帮助模型处理不同长度的序列。
⚝ 某个位置的编码可以表示为其他位置编码的线性函数,这可能有助于模型捕捉相对位置信息。具体来说,对于任意固定的偏移量 \( k \),\( PE(pos+k, i) \) 可以由 \( PE(pos, i) \) 的线性组合表示(利用三角函数和差化积公式)。
将词嵌入向量 \( \mathbf{v}_{pos} \) 和位置编码向量 \( \mathbf{p}_{pos} \) 相加后,得到送入编码器的最终输入向量 \( \mathbf{e}_{pos} = \mathbf{v}_{pos} + \mathbf{p}_{pos} \)。这样,每个输入向量不仅包含了词语本身的语义信息,还融合了其在序列中的位置信息。
3.2.2 多头自注意力层 (Multi-Head Self-Attention Layer)
多头自注意力机制是 Transformer 模型的核心创新之一。它允许模型在计算一个词的表示时,同时关注输入序列中的所有其他词,并根据它们之间的关联性来加权。
自注意力 (Self-Attention):
自注意力的基本思想是,序列中的每一个元素都能与序列中的所有其他元素(包括自身)计算一个“注意力分数”,然后根据这些分数对所有元素的表示进行加权求和,得到当前元素的新的表示。这个新的表示融合了序列中所有元素的信息,并且权重由它们与当前元素的关联性决定。
自注意力层接收一组输入向量 \( X = [\mathbf{x}_1, \mathbf{x}_2, \dots, \mathbf{x}_n] \),其中 \( \mathbf{x}_i \in \mathbb{R}^{d_{model}} \)。为了计算注意力,每个输入向量 \( \mathbf{x}_i \) 会通过三个不同的线性变换(乘以不同的权重矩阵 \( W_Q, W_K, W_V \))分别得到查询向量(Query)、键向量(Key)和值向量(Value):
\[ \begin{align*} \mathbf{q}_i &= \mathbf{x}_i W_Q \\ \mathbf{k}_i &= \mathbf{x}_i W_K \\ \mathbf{v}_i &= \mathbf{x}_i W_V \end{align*} \]
这里 \( W_Q \in \mathbb{R}^{d_{model} \times d_k} \),\( W_K \in \mathbb{R}^{d_{model} \times d_k} \),\( W_V \in \mathbb{R}^{d_{model} \times d_v} \)。原论文中 \( d_k = d_v = d_{model}/h \),其中 \( h \) 是头的数量。
将整个序列的向量堆叠起来,可以得到 Query 矩阵 \( Q \in \mathbb{R}^{n \times d_k} \),Key 矩阵 \( K \in \mathbb{R}^{n \times d_k} \),Value 矩阵 \( V \in \mathbb{R}^{n \times d_v} \)。
自注意力的计算主要分为三步:
① 计算注意力分数:使用查询 \( Q \) 和键 \( K \) 的点积来衡量它们之间的相似度或关联性。
\[ \text{Scores} = QK^T \]
这里的 \( QK^T \) 是一个 \( n \times n \) 的矩阵,其中元素 \( (i, j) \) 表示第 \( i \) 个查询向量 \( \mathbf{q}_i \) 与第 \( j \) 个键向量 \( \mathbf{k}_j \) 的点积 \( \mathbf{q}_i \cdot \mathbf{k}_j \)。
② 缩放与Softmax:为了防止点积结果过大导致梯度消失,对分数进行缩放,通常除以 \( \sqrt{d_k} \)。然后,对每行的分数应用 Softmax 函数,将其转换为注意力权重,这些权重是非负的且和为 1。
\[ \text{Attention Weights} = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) \]
这个 \( n \times n \) 的矩阵的每一行表示当前位置(由 Query 决定)对所有位置(由 Key 决定)的注意力分布。
③ 加权求和:使用注意力权重对值 \( V \) 进行加权求和,得到自注意力的输出。
\[ \text{Output} = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V \]
这里的 Output 是一个 \( n \times d_v \) 的矩阵,其中每一行 \( \mathbf{y}_i \) 是对应于输入 \( \mathbf{x}_i \) 的新的表示,它是所有 \( \mathbf{v}_j \) 的加权和: \( \mathbf{y}_i = \sum_{j=1}^n \alpha_{ij} \mathbf{v}_j \),其中 \( \alpha_{ij} \) 是 \( \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) \) 矩阵的第 \( (i, j) \) 个元素。
这整个过程被称为缩放点积注意力 (Scaled Dot-Product Attention)。
\[ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V \]
多头注意力 (Multi-Head Attention):
单头自注意力虽然强大,但可能限制了模型从不同表示子空间学习关联信息的能力。多头注意力通过并行地执行多个(\( h \) 个)自注意力计算来解决这个问题。
具体步骤:
1. 将输入的 \( Q, K, V \) 分别线性投影到 \( h \) 个不同的低维空间。每个“头”有自己独立的投影矩阵 \( W_{Qi}, W_{Ki}, W_{Vi} \),其中 \( i=1, \dots, h \)。
\[ \begin{align*} Q_i &= Q W_{Qi} \\ K_i &= K W_{Ki} \\ V_i &= V W_{Vi} \end{align*} \]
这里 \( W_{Qi}, W_{Ki} \in \mathbb{R}^{d_{model} \times d_k} \) 且 \( W_{Vi} \in \mathbb{R}^{d_{model} \times d_v} \)。原论文中设定 \( d_k = d_v = d_{model}/h \)。
2. 对每个投影后的 \( Q_i, K_i, V_i \) 执行缩放点积注意力计算,得到 \( h \) 个不同的注意力输出:
\[ \text{head}_i = \text{Attention}(Q_i, K_i, V_i) \]
3. 将所有 \( h \) 个注意力输出 \( [\text{head}_1, \text{head}_2, \dots, \text{head}_h] \) 沿着维度 \( d_v \) 拼接起来。
4. 将拼接后的结果再通过一个最终的线性投影矩阵 \( W_O \in \mathbb{R}^{h \cdot d_v \times d_{model}} \) 进行变换,得到多头注意力的最终输出。
\[ \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) W_O \]
多头注意力的优势在于,它允许模型在不同的“注意力头”中学习到不同的关注模式。例如,某个头可能学会关注语法结构,另一个头可能关注语义相关的词汇。这增强了模型的表达能力。
在编码器中,这个多头自注意力层接收来自下方层的输出(最初是带有位置编码的词嵌入),并输出一个经过自注意力加权的新表示序列。
3.2.3 前馈神经网络 (Feed-Forward Network)
编码器层中的另一个子层是一个简单的、完全连接的前馈神经网络(Feed-Forward Network),也称为位置独立的前馈网络(Position-wise Feed-Forward Network)。虽然被称为“前馈网络”,但它实际上由两个线性变换和一个非线性激活函数组成。
\[ \text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2 \]
这里的 \( x \) 是来自前一个子层(多头自注意力或 Add & Norm)的输出向量。FFN 的关键特性在于,它对输入序列中的每一个位置(每一个向量)都独立地应用相同的线性变换和激活函数。也就是说,对于输入矩阵 \( X \in \mathbb{R}^{n \times d_{model}} \),FFN 是对每一行 \( \mathbf{x}_i \in \mathbb{R}^{d_{model}} \) 应用相同的函数 \( FFN(\mathbf{x}_i) \)。
FFN 的内部维度通常比 \( d_{model} \) 大。原论文中,中间层的维度是 2048,而 \( d_{model} \) 是 512。因此,FFN 可以写作:
\[ \text{FFN}(x) = \text{Linear}( \text{ReLU}(\text{Linear}(x)) ) \]
其中第一个线性层将 \( d_{model} \) 映射到 2048 维,ReLU 是激活函数 \( \max(0, \cdot) \),第二个线性层将 2048 维映射回 \( d_{model} \) 维。
这个前馈网络的作用是为模型提供非线性能力,并在不同位置之间独立地转换表示。它可以在每个位置上进一步处理从自注意力层获得的包含全局上下文信息的向量。
3.2.4 残差连接与层归一化 (Residual Connection and Layer Normalization)
Transformer 模型非常深(原论文有 6 层编码器和 6 层解码器),为了有效训练如此深的神经网络,残差连接(Residual Connection)和层归一化(Layer Normalization)是必不可少的技巧。
残差连接 (Residual Connection):
残差连接(也称为跳跃连接,Skip Connection)由 He 等人提出,是 ResNet 中的关键组件。在 Transformer 中,每个子层(无论是多头注意力还是前馈网络)的输出都与其输入相加:
\[ \text{Output} = \text{Input} + \text{Sublayer}(\text{Input}) \]
其中 \( \text{Sublayer}(\text{Input}) \) 是子层本身的输出(例如,多头自注意力层的输出)。为了使加法可行,子层的输出和输入必须具有相同的维度,这正是 Transformer 设计中 \( d_{model} \) 贯穿始终的原因之一。
残差连接的主要作用是帮助梯度在反向传播时更顺畅地流过网络层,缓解了深度网络训练中的梯度消失问题,使得训练更深的模型成为可能。
层归一化 (Layer Normalization):
在每个子层输出与输入相加之后,紧接着会进行层归一化。层归一化(Layer Normalization)是另一种归一化技术,与批归一化(Batch Normalization)不同,层归一化是对每个样本的单个层的输入(或输出)进行归一化,而不是对一个批次(Batch)在某个维度上进行归一化。
对于一个输入向量 \( x \in \mathbb{R}^{d_{model}} \),层归一化的计算如下:
\[ \text{LayerNorm}(x) = \gamma \odot \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta \]
其中 \( \mu \) 是 \( x \) 的均值,\( \sigma^2 \) 是 \( x \) 的方差,\( \epsilon \) 是一个很小的数值(防止除以零),\( \gamma \) 和 \( \beta \) 是可学习的缩放和偏移参数。均值和方差是在 \( d_{model} \) 维度上计算的。
\[ \begin{align*} \mu &= \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} x_i \\ \sigma^2 &= \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} (x_i - \mu)^2 \end{align*} \]
层归一化的作用是稳定每层输入的分布,使得训练过程更加稳定和快速,并且对 Batch Size 不敏感,这对于序列模型尤其重要。
在 Transformer 中,残差连接和层归一化通常组合在一起,构成一个 "Add & Norm" 子层。它通常位于每个子层(自注意力或前馈网络)之后。即:
\[ \text{Output} = \text{LayerNorm}(\text{Input} + \text{Sublayer}(\text{Input})) \]
编码器中的每一层都包含一个多头自注意力子层和一个前馈网络子层,每个子层后面都跟着一个 Add & Norm 操作。整个编码器堆栈接收带有位置编码的输入嵌入,并通过 N 层处理后,输出最终的编码表示。
3.3 解码器 (Decoder) 详解
解码器是 Transformer 的右半部分,其任务是根据编码器的输出以及已生成的部分目标序列,逐个生成(预测)目标序列的词语。原论文中的解码器也由 N=6 个相同的层堆叠而成。与编码器类似,每一层接收其下方层的输出,并传递给上方层。然而,解码器层结构比编码器层更复杂,它包含三个子层:一个带掩码的多头自注意力层,一个编码器-解码器注意力层,以及一个位置独立的前馈网络。
3.3.1 解码器输入与位置编码
解码器的输入是目标序列。在训练阶段,解码器的输入是真实的目标序列,但会向右偏移一个位置(Shifted Right)。例如,如果目标序列是 "
",那么送入解码器的输入将是 "
"。这样做是为了让模型在预测当前位置的词时,只能看到其之前(或自身)的词,而不能看到未来的词。这模拟了推理(生成)过程:当模型生成第 \(t\) 个词时,它只能依赖于已经生成的词 \(1, \dots, t-1\) 以及编码器的输出。
与编码器类似,目标序列的输入首先通过一个目标嵌入层(Target Embedding Layer)转换为 \( d_{model} \) 维的向量,然后加上位置编码(Positional Encoding)。位置编码与编码器中使用的方法相同。
3.3.2 带掩码的多头自注意力层 (Masked Multi-Head Self-Attention)
解码器的第一个子层是一个带掩码的多头自注意力机制。它与编码器中的多头自注意力基本相同,区别在于注意力计算过程中引入了一个掩码(Mask)。
掩码是一个下三角矩阵(或可以生成下三角矩阵的逻辑)。它的作用是阻止解码器的任何位置关注到它之后的位置。在计算注意力权重时,对于任何查询位置 \( i \) 和键位置 \( j > i \),对应的点积分数 \( Q_i \cdot K_j^T \) 会被设置为一个非常小的负数(例如 \( -\infty \))。在 Softmax 步骤中,这些非常小的负数经过指数函数后会趋近于零,从而使得对应的注意力权重为零。
\[ \text{Masked Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T + M}{\sqrt{d_k}}\right)V \]
这里的 \( M \) 是掩码矩阵,当 \( j > i \) 时 \( M_{ij} = -\infty \),否则 \( M_{ij} = 0 \)。
这个掩码机制是确保解码器自回归(Auto-regressive)生成序列的关键。它保证了在预测位置 \( i \) 的词时,模型只能利用位置 \( 1 \) 到 \( i-1 \) 的信息(以及编码器的输出),而不能“偷看”位置 \( i \) 之后的真实词。
带掩码的多头自注意力层同样在其后紧跟着一个 Add & Norm 操作。
3.3.3 编码器-解码器注意力层 (Encoder-Decoder Attention)
解码器的第二个子层是编码器-解码器注意力(Encoder-Decoder Attention),也被称为交叉注意力(Cross-Attention)。这个注意力层负责连接编码器和解码器。
它的 Query (Q) 来自于解码器的下方层(即带掩码自注意力的输出),而 Key (K) 和 Value (V) 来自于编码器的最终输出。
具体来说:
⚝ 查询矩阵 \( Q \) 是解码器当前层的输入经过一个线性变换 \( W_Q^{dec} \) 得到的。
⚝ 键矩阵 \( K \) 和值矩阵 \( V \) 都是编码器最终输出经过不同的线性变换 \( W_K^{enc}, W_V^{enc} \) 得到的。
\[ \begin{align*} Q_{dec} &= \text{Decoder Input} \cdot W_Q^{dec} \\ K_{enc} &= \text{Encoder Output} \cdot W_K^{enc} \\ V_{enc} &= \text{Encoder Output} \cdot W_V^{enc} \end{align*} \]
然后,计算注意力输出:
\[ \text{Output} = \text{Attention}(Q_{dec}, K_{enc}, V_{enc}) = \text{softmax}\left(\frac{Q_{dec}K_{enc}^T}{\sqrt{d_k}}\right)V_{enc} \]
这个注意力机制允许解码器在生成每个词时,查询(Query)编码器输出(Key)中与之最相关的部分(Value),从而集中注意力于输入序列中的重要信息。这模仿了传统 Seq2Seq 模型中注意力机制的功能,是实现机器翻译、文本摘要等任务中输入-输出序列对齐的关键。
这个编码器-解码器注意力层同样采用了多头机制,并在其后跟着一个 Add & Norm 操作。
3.3.4 前馈神经网络与Add & Norm
解码器的第三个子层与编码器中的前馈网络完全相同:一个位置独立的两层全连接前馈网络,中间使用 ReLU 激活函数。它接收编码器-解码器注意力层的输出,并独立地对每个位置进行变换。
\[ \text{FFN}(x) = \text{Linear}( \text{ReLU}(\text{Linear}(x)) ) \]
这个前馈网络后面也跟着一个 Add & Norm 操作。
3.3.5 线性层与Softmax输出
在解码器堆栈的顶层,其输出向量序列(维度为 \( n_{target} \times d_{model} \),其中 \( n_{target} \) 是目标序列长度)会经过一个最终的线性变换层。这个线性层将 \( d_{model} \) 维的向量映射到词汇表大小(Vocabulary Size)的维度。
\[ \text{Logits} = \text{Decoder Output} \cdot W_{linear} + b_{linear} \]
这里的 \( W_{linear} \in \mathbb{R}^{d_{model} \times |Vocab|} \),\( |Vocab| \) 是目标词汇表的大小。输出的 Logits 是一个 \( n_{target} \times |Vocab| \) 的矩阵,每一行对应目标序列中的一个位置,每一列对应词汇表中的一个词。
最后,对 Logits 矩阵的每一行独立地应用 Softmax 函数。Softmax 将 Logits 转换为一个概率分布,表示在当前位置生成词汇表中每个词的概率。
\[ \text{Probabilities} = \text{softmax}(\text{Logits}) \]
在训练时,这些概率分布与真实目标序列的独热编码(One-Hot Encoding)表示计算交叉熵损失(Cross-Entropy Loss),用于优化模型参数。在推理(生成)时,通常会选择每个位置概率最高的词(贪婪解码,Greedy Decoding)或使用集束搜索(Beam Search)等更复杂的策略来生成完整的输出序列。
3.4 参数共享与计算效率
在 Transformer 模型中,存在一些参数共享的策略,这不仅可以减少模型总参数量,有时也能起到正则化作用,提高泛化能力。
一个常见的参数共享是输入嵌入层和输出 Softmax 层之前的线性层。如果输入和输出使用相同的词汇表,并且 \( d_{model} \) 相同,那么输入嵌入矩阵和这个线性层的转置矩阵通常是共享的。
另一个潜在的共享是编码器和解码器的位置编码。虽然位置编码不是学习参数,而是固定的函数计算,但计算方式在编码器和解码器中是相同的。
在计算效率方面,Transformer 相较于传统的 RNN/LSTM 模型具有显著优势,这主要归功于自注意力机制的可并行计算性。
与 RNN/LSTM 的对比:
⚝ RNN/LSTM: 序列的计算是严格顺序的。计算当前时间步的隐藏状态必须依赖于前一个时间步的隐藏状态。这导致长序列的计算无法并行化,并且难以捕捉长距离依赖(梯度消失或爆炸问题)。计算复杂度通常是 \( O(n \cdot d^2) \),其中 \( n \) 是序列长度,\( d \) 是模型维度。
⚝ Transformer (Self-Attention): 自注意力机制允许序列中的每一个位置同时计算与其他所有位置的关联。矩阵乘法 \( QK^T \) 和随后的操作可以高度并行化。这使得 Transformer 能够有效地利用现代硬件(如 GPU/TPU)的并行计算能力,并在训练时处理长序列。
Transformer 的计算复杂度分析:
⚝ 自注意力层: 计算 \( QK^T \) 的复杂度是 \( O(n \cdot d_k \cdot n) = O(n^2 d_k) \)。计算 \( \text{softmax}(\cdot) V \) 的复杂度是 \( O(n \cdot n \cdot d_v) = O(n^2 d_v) \)。由于 \( d_k, d_v \) 通常与 \( d_{model} \) 成正比,单头自注意力的复杂度是 \( O(n^2 d_{model}) \)。多头注意力由于是将 \( d_{model} \) 分割到多个头进行并行计算,总的计算量与单头类似,但涉及 \( h \) 个并行矩阵乘法和一次拼接/投影。总的来说,多头自注意力的计算复杂度为 \( O(n^2 \cdot d_{model}) \) (忽略 \( h \cdot d_k \approx d_{model} \))。
⚝ 前馈网络: 前馈网络对每个位置独立计算,复杂度为 \( O(n \cdot d_{model}^2) \) (假设中间层维度与 \( d_{model} \) 成正比)。
⚝ 总复杂度: Transformer 编码器或解码器的单层总复杂度是自注意力层和前馈网络层复杂度之和,即 \( O(n^2 \cdot d_{model} + n \cdot d_{model}^2) \)。在实际应用中,通常 \( n \) 和 \( d_{model} \) 都是重要的因素。当序列长度 \( n \) 大于模型维度 \( d_{model} \) 时(长序列),自注意力层的 \( O(n^2 \cdot d_{model}) \) 复杂度成为瓶颈;当 \( d_{model} \) 较大时,前馈网络的复杂度也很大。
长序列处理的挑战:
尽管并行性是巨大优势,但自注意力层中 \( O(n^2) \) 的计算复杂度(相对于序列长度)意味着处理非常长的序列时,计算成本和内存需求会急剧增加。一个包含 1024 个 token 的序列需要计算 \( 1024 \times 1024 \approx 10^6 \) 个注意力分数;如果序列长度增加一倍到 2048,计算量将变为原来的四倍。这限制了标准 Transformer 模型直接处理超长文本、高分辨率图像或长时间序列数据的能力。这正是后续许多高效 Transformer 变体(如 Longformer, Reformer 等)研究的动机,它们试图通过改变注意力计算方式来降低复杂度。
总而言之,Transformer 模型通过完全依赖并行化的注意力机制,摆脱了传统序列模型的计算瓶颈,实现了在大规模数据上的高效训练和卓越性能。理解其编码器和解码器的精巧设计是掌握其工作原理的关键。
4. Transformer模型训练与优化
本章探讨如何有效地训练Transformer模型,包括损失函数、优化器选择、学习率调度等实践细节。理解这些训练和优化技术对于成功应用Transformer模型至关重要。
4.1 训练目标与损失函数
在序列到序列(Sequence-to-Sequence)任务中,如机器翻译或文本摘要,Transformer模型的训练目标通常是最大化给定输入序列下,目标序列出现的对数概率。这本质上是一个条件概率建模问题。
模型在训练时,接收输入序列和目标序列(通常是“teacher forcing”方式,即在生成第 \(t\) 个词时,模型被给予真实的目标序列中的第 \(t-1\) 个词)。解码器在每个时间步预测下一个词的概率分布。训练过程就是调整模型参数,使得这些预测的概率分布尽可能接近真实目标序列的词汇分布。
最常用的损失函数是交叉熵损失(Cross-Entropy Loss)。对于一个批次(Batch)中的一个样本,假设目标序列长度为 \(L\),词汇表大小为 \(V\),模型在时间步 \(t\) 预测的词汇概率分布为 \(\hat{y}_t \in \mathbb{R}^V\),真实目标词汇的独热(One-Hot)编码为 \(y_t \in \mathbb{R}^V\)(即真实词汇对应位置为1,其余为0)。则该时间步的交叉熵损失为:
\[ L_t = - \sum_{i=1}^V y_{t,i} \log(\hat{y}_{t,i}) \]
由于 \(y_t\) 是独热编码,这个损失函数实际上等价于 \(L_t = -\log(\hat{y}_{t, true\_token\_index})\),即只关注真实目标词汇的预测概率。
整个序列的损失通常是所有时间步损失的平均或求和:
\[ L_{sequence} = \frac{1}{L} \sum_{t=1}^L L_t \]
对于一个训练批次,总损失是批次中所有序列损失的平均。
在实际实现中,特别是对于序列生成任务,通常会在目标序列的末尾添加一个特殊的结束标记(End-of-Sequence Token),例如 <eos>
。训练时,模型需要学会预测这个结束标记,表示序列生成完成。损失函数的计算直到遇到这个标记为止。同时,为了避免模型预测填充标记(Padding Token),在计算损失时通常会忽略(Mask)掉这些填充位置的损失。
4.2 优化器选择与配置
训练大型深度学习模型,尤其是Transformer这样参数量巨大的模型,需要高效且稳定的优化器。传统的随机梯度下降(Stochastic Gradient Descent, SGD)及其带有动量(Momentum)的变体可能在大规模训练中收敛较慢或不够稳定。
目前,用于训练Transformer模型最流行的优化器是基于适应性学习率(Adaptive Learning Rate)的方法,其中 Adam (Adaptive Moment Estimation) 及其变体 AdamW 是首选。
① Adam 优化器
▮▮▮▮Adam 结合了动量和 RMSprop 的优点。它为每个参数独立计算适应性学习率,这基于梯度的第一阶矩(均值)和第二阶矩(非中心方差)的估计。其更新规则大致如下:
▮▮▮▮ⓐ 计算当前梯度 \(g_t\)。
▮▮▮▮ⓑ 更新有偏的第一个矩估计 \(m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t\)。
▮▮▮▮ⓒ 更新有偏的第二个矩估计 \(v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2\)。
▮▮▮▮ⓓ 计算无偏的第一个矩估计 \(\hat{m}_t = m_t / (1 - \beta_1^t)\)。
▮▮▮▮ⓔ 计算无偏的第二个矩估计 \(\hat{v}_t = v_t / (1 - \beta_2^t)\)。
▮▮▮▮ⓕ 更新参数 \(\theta_t = \theta_{t-1} - \alpha \cdot \hat{m}_t / (\sqrt{\hat{v}_t} + \epsilon)\)。
▮▮▮▮其中,\(\alpha\) 是学习率,\(\beta_1\) 和 \(\beta_2\) 是衰减率(通常接近1),\(\epsilon\) 是为了数值稳定性而加的小常数。
② AdamW 优化器
▮▮▮▮AdamW 是 Adam 的一个改进版本,它正确地解耦了权重衰减(Weight Decay)和 L2 正则化。在许多深度学习框架中,Adam 实现的权重衰减是直接加到梯度上的(相当于 L2 正则化),而不是在更新步骤中应用。这对于使用动量的优化器来说可能不是最优的。AdamW 将权重衰减从梯度计算中移出,直接在参数更新时进行衰减。这在许多任务上,特别是涉及权重衰减时,能获得更好的性能和泛化能力。
▮▮▮▮AdamW 的参数更新步骤如下:
▮▮▮▮ⓐ 按 Adam 计算 \(\Delta \theta_t = \alpha \cdot \hat{m}_t / (\sqrt{\hat{v}_t} + \epsilon)\)。
▮▮▮▮ⓑ 应用权重衰减:\(\theta_t = \theta_{t-1} - \Delta \theta_t - \lambda \cdot \theta_{t-1}\),其中 \(\lambda\) 是权重衰减率。
▮▮▮▮在训练 Transformer 模型时,AdamW 通常是比 Adam 更优的选择,特别是在大规模预训练时。
配置技巧:
⚝ 学习率(Learning Rate, \(\alpha\)): 这是最重要的超参数之一,通常需要结合学习率调度策略(见下一节)。
⚝ \(\beta_1, \beta_2\) 参数: Adam 论文中推荐的默认值通常工作得很好(例如 \(\beta_1=0.9\), \(\beta_2=0.999\))。
⚝ \(\epsilon\) 参数: 通常设置为 \(10^{-8}\) 或 \(10^{-6}\)。
⚝ 权重衰减率 (\(\lambda\)) (针对 AdamW): 需要根据具体任务和模型大小进行调整,通常在一个较小的范围内搜索,如 \(10^{-4}\) 到 \(10^{-2}\)。
4.3 学习率调度策略 (Learning Rate Scheduling)
学习率调度是指在训练过程中动态调整学习率。对于训练深度模型,尤其像 Transformer 这样对学习率敏感的模型,一个好的学习率调度策略至关重要。它可以帮助模型更快地收敛到更好的局部最优解,并提高训练稳定性。
原始的 Transformer 论文《Attention Is All You Need》提出了一种特别设计的学习率调度策略,该策略在训练初期使用“预热”(Warm-up),然后逐渐衰减学习率。
① 预热(Warm-up)阶段
▮▮▮▮在训练刚开始的几个训练步(或 epoch)内,学习率从一个很小的值线性地增加到一个峰值。
▮▮▮▮作用: 在模型参数随机初始化时,计算出的梯度可能很不稳定且方差很大。使用小的学习率可以避免训练初期的大幅度震荡,有助于模型稳定地进入收敛区域。
② 衰减(Decay)阶段
▮▮▮▮在预热阶段之后,学习率开始逐渐减小。原始 Transformer 论文中使用的衰减策略是与训练步数的平方根成反比。
▮▮▮▮原始论文中使用的学习率调度公式为:
\[ lrate = d_{model}^{-0.5} \cdot \min(step\_num^{-0.5}, step\_num \cdot warmup\_steps^{-1.5}) \]
▮▮▮▮其中:
▮▮▮▮ⓐ \(d_{model}\) 是模型的隐藏层维度(例如 Transformer Base 模型是 512)。
▮▮▮▮ⓑ \(step\_num\) 是当前的训练步数。
▮▮▮▮ⓒ \(warmup\_steps\) 是预热阶段的总步数(一个超参数)。
▮▮▮▮这个公式的含义是:
▮▮▮▮ⓐ 如果 \(step\_num < warmup\_steps\),学习率随 \(step\_num\) 线性增加(\(step\_num \cdot warmup\_steps^{-1.5}\) 项在 \(step\_num\) 小时占主导,且与 \(step\_num\) 成正比)。
▮▮▮▮ⓑ 如果 \(step\_num \ge warmup\_steps\),学习率随 \(step\_num^{-0.5}\) 衰减(\(step\_num^{-0.5}\) 项在 \(step\_num\) 大时占主导)。
为何采用这种调度?
⚝ 预热阶段帮助模型克服初始阶段的不稳定性。
⚝ 后续的衰减使得模型在接近最优解时,参数更新的步长减小,有助于模型在损失函数底部精细地收敛,而不是来回震荡。
除了这种特定的调度策略,实践中也常使用其他调度方法,例如:
⚝ 余弦退火(Cosine Annealing): 学习率按照余弦函数周期性地变化,或者单调地衰减到0。
⚝ 阶梯式衰减(Step Decay): 在预设的训练步数或 epoch 数时,将学习率乘以一个衰减因子(如 0.1)。
选择哪种调度策略以及如何调整参数(如预热步数、峰值学习率、衰减率等)通常需要实验来确定,并且与优化器、批次大小等其他超参数紧密相关。
4.4 正则化技术 (Regularization Techniques)
为了防止模型过拟合(Overfitting),提高模型的泛化能力,训练 Transformer 模型时会使用多种正则化技术。
① Dropout
▮▮▮▮Dropout 是一种常用的正则化技术,它在训练过程中随机地“丢弃”(设置为零)一部分神经元的输出。
▮▮▮▮在 Transformer 中,Dropout 通常应用于:
▮▮▮▮ⓐ 在词嵌入(Embedding)和位置编码(Positional Encoding)相加之后。
▮▮▮▮ⓑ 在编码器和解码器中的每个子层(多头注意力层和前馈网络)的输出之后,残差连接(Residual Connection)之前。
▮▮▮▮ⓒ 在注意力权重的计算之后,应用 Softmax 之前。
▮▮▮▮作用: 强制网络学习更加鲁棒的特征,减少神经元之间的互相依赖,从而降低过拟合风险。在推理(Inference)时,Dropout 会被关闭。
② DropConnect (较少在标准Transformer中使用,但概念相关)
▮▮▮▮DropConnect 是 Dropout 的一个变体,它不是随机丢弃神经元的输出,而是随机丢弃神经元之间的连接(即权重)。每个权重都有一定概率被设置为零。
▮▮▮▮虽然 Transformer 的标准实现中主要使用 Dropout,但理解 DropConnect 有助于理解更广泛的正则化思想。
③ 权重衰减(Weight Decay)
▮▮▮▮权重衰减通常通过在损失函数中添加模型权重的 L2 范数(或 L1 范数)的惩罚项来实现。
\[ L_{total} = L_{task} + \lambda \sum w^2 \]
▮▮▮▮其中 \(L_{task}\) 是任务相关的损失(如交叉熵),\(w\) 是模型的权重,\(\lambda\) 是权重衰减系数。
▮▮▮▮如前所述,AdamW 优化器将权重衰减直接集成到参数更新规则中,这通常比简单的 L2 正则化表现更好。权重衰减鼓励模型使用较小的权重,从而降低模型的复杂度。
④ 标签平滑 (Label Smoothing)
▮▮▮▮在分类任务(包括序列生成中的下一个词预测)中,交叉熵损失鼓励模型为真实标签预测极高的概率(接近1),这可能导致模型过于自信,在面对不确定或标签噪声的数据时泛化能力下降。
▮▮▮▮标签平滑是一种正则化技术,它将硬目标(Hard Targets,如独热编码)转换为软目标(Soft Targets)。它将真实标签的概率从1分散到1-\(\epsilon\),并将剩余的概率 \(\epsilon\) 平均分配给所有其他非真实类别(或词汇)。
▮▮▮▮例如,如果真实标签是类别 \(k\),词汇表大小为 \(V\),标签平滑后的目标概率分布 \(y'_{smoothed}\) 为:
▮▮▮▮\[ y'_{smoothed, i} = \begin{cases} 1 - \epsilon + \epsilon / V & \text{if } i = k \\ \epsilon / V & \text{if } i \ne k \end{cases} \]
▮▮▮▮在 Transformer 论文中,标签平滑也被用于训练,有助于提高模型的泛化能力和翻译质量。
4.5 序列生成策略 (Sequence Generation Strategies)
训练好的 Transformer 模型在进行推理(Inference)时,需要根据输入的序列生成输出序列。这个生成过程是一个迭代过程,通常是自回归(Auto-regressive)的:在生成当前时间步的词时,会利用已经生成的前面所有时间步的词作为解码器的输入。
从解码器的输出概率分布中选择下一个词的方法称为序列生成策略。不同的策略在生成文本的多样性、流畅性和质量之间进行权衡。
① 贪婪解码 (Greedy Decoding)
▮▮▮▮原理: 在每个时间步,模型直接选择概率最高的词作为下一个词,然后将这个词作为输入送给解码器以生成下一个时间步的词,直到生成结束标记(<eos>
)。
▮▮▮▮优点: 实现简单,计算速度快。
▮▮▮▮缺点: 这是一种局部最优策略。在当前步选择概率最高的词,并不能保证最终生成的整个序列具有最高的概率。可能会错过一些虽然当前概率不高,但后续能导出更高总体概率序列的路径,导致生成质量不高或重复。
② 集束搜索 (Beam Search)
▮▮▮▮原理: 集束搜索是一种启发式搜索策略,旨在找到概率较高的整个序列,而不是仅仅在每个时间步选择概率最高的词。它维护一个大小为 \(k\) (集束宽度,Beam Size)的候选序列集合。在每个时间步,它基于当前的所有 \(k\) 个候选序列,预测下一个词的概率,然后从所有 \(k \times V\) (\(V\) 是词汇表大小)种可能的扩展中,选出总对数概率最高的 \(k\) 个新的候选序列。这个过程持续进行,直到所有候选序列都生成了结束标记,或者达到最大序列长度。最终,从这些完成的序列中选择总对数概率最高的作为最终输出。
▮▮▮▮通常计算的是序列的对数概率之和:\(\sum_{t=1}^L \log P(y_t | y_{
▮▮▮▮缺点: 计算量比贪婪解码大(与集束宽度 \(k\) 成正比),需要更多的内存。集束宽度 \(k\) 是一个需要调整的超参数,过大的 \(k\) 收益递减且计算开销大。
其他策略简述 (不在本章大纲要求内,作为补充):
⚝ 采样 (Sampling): 直接从模型的输出概率分布中随机采样下一个词。可以增加生成文本的多样性。
⚝ Top-k 采样 (Top-k Sampling): 只从概率最高的 \(k\) 个词中进行采样。
⚝ 核采样/P采样 (Nucleus Sampling / Top-p Sampling): 从累积概率超过某个阈值 \(p\) 的最小词汇集合中进行采样。这些采样方法通常与温度(Temperature)参数结合使用,温度可以控制采样分布的尖锐程度,从而影响生成文本的随机性。
在实际应用中,对于需要高质量、确定性输出的任务(如机器翻译),通常使用集束搜索;对于需要生成多样化或创意性文本的任务(如故事生成、对话),采样策略可能更合适。
5. Transformer的变体与家族
本章介绍基于Transformer架构演变出的各类明星模型,如BERT、GPT系列、T5等,分析它们的特点和适用场景。
在第三章中,我们深入剖析了经典的Transformer模型架构,它以其革命性的自注意力机制(Self-Attention Mechanism)和并行计算能力,打破了循环神经网络(Recurrent Neural Network - RNN)在序列建模领域的统治地位。然而,原始的Transformer模型并非终点,而是开启了一个全新的时代。自其诞生以来,无数研究人员在其基础上进行了改进、扩展和变体设计,催生了大量在各种下游任务中取得巨大成功的预训练模型(Pre-trained Models)。本章将带领读者探索这些形形色色的Transformer家族成员,理解它们的设计理念、核心特点以及在不同领域的典型应用。我们将重点关注在自然语言处理(Natural Language Processing - NLP)领域具有里程碑意义的几大类模型:仅编码器模型(Encoder-only Models)、仅解码器模型(Decoder-only Models)以及编码器-解码器模型(Encoder-Decoder Models),并简要介绍为解决计算效率问题而涌现的高效Transformer变体。
5.1 预训练语言模型的兴起
介绍大规模预训练在自然语言处理中的重要性。
在Transformer出现之前,深度学习模型通常针对特定任务从零开始训练,或者使用词嵌入(Word Embeddings)等预训练组件。这种方式依赖于大量的任务标注数据,且模型泛化能力有限。随着计算能力的提升和大规模文本语料库(Corpus)的可用性增加,预训练语言模型(Pre-trained Language Models - PLMs)范式应运而生,并迅速成为自然语言处理领域的主流。
其核心思想是:
⚝ 首先,在一个庞大且多样化的无标注文本数据集上训练一个大型语言模型,使其学习语言的通用知识、语法结构、语义信息以及世界知识。这个过程称为预训练(Pre-training)。
⚝ 然后,将预训练好的模型作为一个基础,针对特定的下游任务(Downstream Task),如文本分类、问答、命名实体识别等,使用少量标注数据进行微调(Fine-tuning)。
这种范式的优势在于:
① 模型在预训练阶段已经学习到了丰富的语言表示,这使得它在微调阶段能够用更少的标注数据快速适应新任务。
② 大规模预训练模型通常具有更强的泛化能力,能够在各种不同的任务和领域表现出色。
③ 预训练模型可以被视为一种“知识库”,为下游任务提供了强大的起点。
Transformer架构的出现,特别是其捕获长距离依赖的能力以及适合并行计算的特性,极大地推动了大规模预训练语言模型的发展,并使得模型的规模得以以前所未有的速度增长,从数亿参数发展到万亿参数级别,带来了惊人的性能提升和“涌现能力(Emergent Abilities)”。
5.2 仅编码器模型 (Encoder-only Models)
详细介绍BERT (Bidirectional Encoder Representations from Transformers) 的结构和预训练任务。
仅编码器模型,顾名思义,是只使用Transformer的编码器堆叠(Encoder Stack)构建的模型。这类模型通常用于理解和编码输入序列,生成富有上下文信息的词或句子表示。它们非常适合需要对输入文本进行深入理解的任务,而不是生成新的文本序列。
最具代表性的仅编码器模型是BERT(Bidirectional Encoder Representations from Transformers)。BERT模型由多个相同的Transformer编码器层堆叠而成。每个编码器层都包含一个多头自注意力机制(Multi-Head Self-Attention Mechanism)和一个位置前馈网络(Position-wise Feed-Forward Network),并辅以残差连接(Residual Connection)和层归一化(Layer Normalization)。
BERT最核心的创新在于其预训练任务(Pre-training Tasks)的设计,使其能够学习到双向(Bidirectional)的上下文表示:
① 掩码语言模型 (Masked Language Model - MLM):
▮▮▮▮这是受Cloze任务启发的一种预训练任务。模型随机遮盖(mask)输入序列中一部分词(通常15%),然后训练模型预测这些被遮盖的词。
▮▮▮▮例如,输入句子“The man went to the [MASK] store.”,模型需要预测[MASK]是“grocery”或“market”等。
▮▮▮▮不同于传统的从左到右或从右到左的语言模型,MLM任务使得模型在预测每个被遮盖的词时,能够同时利用其左右两侧的上下文信息,从而学习到真正的双向表示。
② 下一句预测 (Next Sentence Prediction - NSP):
▮▮▮▮这是一个二分类任务,模型需要判断两个句子是否是原文中连续的句子。
▮▮▮▮在预训练数据中,50%的句子对是原文中相邻的句子(标记为IsNext),另外50%是随机抽取的非相邻句子(标记为NotNext)。
▮▮▮▮这个任务旨在让模型理解句子之间的关系,对于问答和自然语言推理等任务有益(尽管后续研究表明NSP任务的收益有限,甚至可以移除)。
通过这两个预训练任务,BERT能够在海量无标注文本上学习到强大的、上下文相关的词向量表示。
5.2.1 BERT及其变体 (RoBERTa, ALBERT, ELECTRA等)
分析不同BERT变体的改进之处。
BERT的成功引爆了预训练语言模型的研究热潮,随之而来的是一系列在其基础上进行的改进和优化,形成了BERT家族:
① RoBERTa (A Robustly Optimized BERT Pretraining Approach):
▮▮▮▮RoBERTa由Facebook AI提出,其核心是对BERT的预训练过程进行优化,而不是改变模型结构。
▮▮▮▮改进点包括:
▮▮▮▮▮▮▮▮❶ 使用更大规模的数据集进行预训练。
▮▮▮▮▮▮▮▮❷ 训练更长时间,使用更大的批次(batch size)。
▮▮▮▮▮▮▮▮❸ 使用动态掩码(Dynamic Masking):在每次输入序列送入模型时,都重新生成掩码策略,而不是像BERT那样在数据预处理时就固定掩码。这使得模型能够看到同一个词在不同上下文和不同掩码情况下的表示。
▮▮▮▮▮▮▮▮❹ 移除了下一句预测(NSP)任务,认为它对下游任务的收益不大。
▮▮▮▮通过这些优化,RoBERTa在多项下游任务上取得了比原始BERT更好的性能。
② ALBERT (A Lite BERT for Self-supervised Learning of Language Representations):
▮▮▮▮ALBERT由Google Research提出,其主要目标是减少BERT模型的参数数量和内存消耗,同时提高训练速度。
▮▮▮▮核心优化点:
▮▮▮▮▮▮▮▮❶ 参数共享(Parameter Sharing):在跨层之间共享所有的前馈网络和注意力参数。
▮▮▮▮▮▮▮▮❷ 词嵌入参数化分解(Factorized Embedding Parameterization):将one-hot向量映射到低维空间,再映射到隐藏层维度,减少词嵌入矩阵的参数。
▮▮▮▮同时,ALBERT将NSP任务替换为句子顺序预测(Sentence Order Prediction - SOP)任务,判断两个连续的句子是否被交换了顺序,这个任务被认为比NSP更能有效捕捉句子间的连贯性关系。ALBERT能够在参数量大幅减少的情况下,保持甚至超越BERT的性能。
③ ELECTRA (Efficiently Learning an Encoder from a Transformer):
▮▮▮▮ELECTRA由Google Research和Stanford University提出,引入了一种更高效的预训练任务:替换Token检测(Replaced Token Detection - RTD)。
▮▮▮▮RTD任务使用一个“生成器(Generator)”(通常是一个小型掩码语言模型)来预测被遮盖的词,然后用这些预测的词替换原文中的部分词。
▮▮▮▮接着,训练一个“判别器(Discriminator)”(即主要的ELECTRA模型)来判断输入序列中的每个词是原始词还是被生成器替换过的词。
▮▮▮▮这种任务形式使得模型需要对序列中的每一个词进行判断,而不是像MLM那样只对被遮盖的词进行预测,因此能够更有效地利用计算资源,并达到与BERT同等性能所需的计算量更少。
除了这些,还有SpanBERT(关注连续文本片段预测)、Funnel-Transformer(通过部分输入传递信息减少计算)等众多BERT变体,它们都在特定方面对原始BERT进行了改进。
5.2.2 应用场景:文本分类、命名实体识别等
探讨Encoder-only模型适用的下游任务。
仅编码器模型通过预训练学习到了强大的文本编码能力,它们的输出通常是输入序列中每个Token(词或子词)的上下文向量表示。这些表示可以作为特征,输入到下游任务的分类器或序列标注层中。因此,这类模型非常适合处理需要对输入文本进行理解和分析的任务,包括:
① 文本分类 (Text Classification):
▮▮▮▮例如,情感分析(Sentiment Analysis)、垃圾邮件检测(Spam Detection)、新闻主题分类(News Topic Classification)等。
▮▮▮▮通常做法是将整个输入序列(或特殊的[CLS] Token)经过Encoder后得到的向量表示,输入到一个简单的全连接层(Fully Connected Layer)或多层感知机(Multilayer Perceptron - MLP)进行分类。
② 命名实体识别 (Named Entity Recognition - NER):
▮▮▮▮识别文本中的人名、地名、组织名、日期等实体。
▮▮▮▮将Encoder输出的每个Token的向量表示,输入到一个序列标注层(如CRF或Softmax层)进行分类。
③ 问答系统 (Question Answering - QA):
▮▮▮▮特别是抽取式问答(Extractive QA),即答案是原文中的一个片段。
▮▮▮▮模型预测答案片段的起始和结束位置。通常通过在Encoder输出上添加两个线性层,分别预测每个Token是答案起始位置的概率和结束位置的概率。
④ 句子对任务 (Sentence Pair Tasks):
▮▮▮▮例如,自然语言推理(Natural Language Inference - NLI)、句子相似度匹配(Sentence Similarity Matching)等。
▮▮▮▮将两个句子用特殊分隔符连接后输入Encoder,然后使用[CLS] Token的表示进行分类。
⑤ 序列标注 (Sequence Labeling):
▮▮▮▮除了NER,还包括词性标注(Part-of-Speech Tagging)、语义角色标注(Semantic Role Labeling)等。
▮▮▮▮与NER类似,在每个Token的Encoder输出上添加分类层。
总而言之,仅编码器模型在各种判别式(Discriminative)的自然语言理解(Natural Language Understanding - NLU)任务中表现出色。
5.3 仅解码器模型 (Decoder-only Models)
详细介绍GPT (Generative Pre-trained Transformer) 系列的结构和自回归预训练任务。
与仅编码器模型相对的是仅解码器模型。这类模型只使用Transformer的解码器堆叠(Decoder Stack)构建,并且利用了解码器中的带掩码的多头自注意力机制(Masked Multi-Head Self-Attention)。这种带掩码的注意力确保了在生成序列中的当前Token时,模型只能访问其左侧(即前面已生成的Token)的信息,而不能“看到”右侧(即尚未生成的Token)。这使得仅解码器模型天生就适合进行自回归(Auto-regressive)的序列生成任务。
仅解码器模型中最著名的家族是GPT(Generative Pre-trained Transformer)系列。GPT系列模型的核心是一个由多个Transformer解码器层组成的堆叠。每个解码器层包含一个带掩码的多头自注意力层和一个位置前馈网络,同样辅以残差连接和层归一化。需要注意的是,由于是"仅解码器",这里的解码器层不包含对编码器输出的交叉注意力(Cross-Attention)。
GPT模型的预训练任务是简单的因果语言建模(Causal Language Modeling)或称为自回归语言建模。模型的目标是根据前文预测序列中的下一个词。
\[ P(x_t | x_1, x_2, ..., x_{t-1}) \]
通过最大化训练语料库中所有Token的条件概率之和来训练模型:
\[ \sum_{i=1}^{L} \log P(x_i | x_1, ..., x_{i-1}) \]
其中 \(L\) 是序列长度。
这种预训练方式使得GPT模型非常擅长生成连贯且符合上下文的文本序列。
5.3.1 GPT系列 (GPT-1, GPT-2, GPT-3, GPT-4等)
分析GPT系列模型的演进和能力。
GPT系列模型的演进主要体现在模型规模、数据规模以及随之而来的能力提升:
① GPT-1:
▮▮▮▮第一个GPT模型,由OpenAI于2018年提出。
▮▮▮▮结构基于Transformer解码器,预训练任务是标准的语言模型。
▮▮▮▮在预训练后,需要针对不同的下游任务进行有监督微调(Supervised Fine-tuning)。
② GPT-2:
▮▮▮▮于2019年发布,规模比GPT-1大得多(最大版本有15亿参数)。
▮▮▮▮一个重要理念是零样本学习(Zero-shot Learning)和少样本学习(Few-shot Learning)的能力。作者认为,如果模型规模足够大,并且在足够多样化的数据上进行预训练,它应该能够无需额外的微调就能在各种任务上表现良好,只需通过任务描述或少量示例作为输入即可。
▮▮▮▮虽然在实践中微调仍然常用,但GPT-2确实展现了强大的文本生成能力和一定的跨任务泛化能力。
③ GPT-3:
▮▮▮▮于2020年发布,拥有惊人的1750亿参数,是当时规模最大的语言模型。
▮▮▮▮进一步验证了模型规模对性能的关键影响,尤其是在情境学习(In-context Learning)方面,即通过在输入中提供任务指令和几个输入-输出示例,模型就能执行新任务,而无需更新模型权重。
▮▮▮▮GPT-3在文本生成、翻译、问答等多种任务上展现出前所未有的能力,尤其擅长生成高质量、长篇的文本。
④ GPT-4:
▮▮▮▮于2023年发布,具体参数量未公开,但普遍认为远超GPT-3,并且是一个多模态(Multimodal)模型(虽然目前主要以文本接口为主)。
▮▮▮▮在理解复杂指令、处理更长的上下文、事实性和推理能力、以及跨语言能力等方面相比GPT-3有显著提升。
▮▮▮▮GPT-4是目前许多先进人工智能应用的核心驱动力。
GPT系列模型的演进史,在很大程度上是“大力出奇迹”(Scaling Laws)的体现,即在Transformer架构下,增加模型和数据规模可以带来能力的显著提升,甚至涌现出新的能力。
5.3.2 应用场景:文本生成、对话系统等
探讨Decoder-only模型适用的下游任务。
由于其自回归的生成特性,仅解码器模型在各种需要生成新文本序列的任务中表现出色:
① 文本生成 (Text Generation):
▮▮▮▮这是GPT系列最擅长的任务,包括故事写作、文章续写、创意文本生成、诗歌生成等。
▮▮▮▮模型根据给定的起始文本(Prompt)逐词生成后续内容。
② 对话系统 (Dialogue Systems):
▮▮▮▮作为聊天机器人(Chatbot)或虚拟助手(Virtual Assistant)的核心。
▮▮▮▮模型可以根据用户的输入和对话历史,生成自然、相关的回复。
③ 代码生成 (Code Generation):
▮▮▮▮根据自然语言描述生成程序代码,或根据代码片段续写代码。
▮▮▮▮例如,OpenAI Codex(基于GPT-3)。
④ 摘要生成 (Summarization):
▮▮▮▮特别是抽象式摘要(Abstractive Summarization),模型生成原文中没有出现的新句子来概括内容。
▮▮▮▮可以将原文作为Prompt输入模型,然后引导模型生成摘要。
⑤ 开放域问答 (Open-domain Question Answering):
▮▮▮▮生成答案而不是仅仅抽取。
▮▮▮▮将问题和相关上下文作为Prompt输入模型,生成对问题的回答。
⑥ 机器翻译 (Machine Translation):
▮▮▮▮虽然经典的机器翻译使用Encoder-Decoder模型,但GPT系列也可以通过构建合适的Prompt来实现翻译任务,例如 "Translate English to French: [English Sentence]"。
仅解码器模型在各种生成式(Generative)任务中展现了强大的能力,尤其是随着模型规模的增大,其生成内容的质量和多样性显著提高。
5.4 编码器-解码器模型 (Encoder-Decoder Models)
介绍T5 (Text-to-Text Transfer Transformer) 和 BART (Bidirectional and Auto-Regressive Transformer) 等模型。
编码器-解码器模型是原始Transformer架构的完整体现,包含一个编码器堆叠和一个解码器堆叠。编码器处理输入序列并将其编码为一个隐藏表示,解码器则根据这个隐藏表示自回归地生成输出序列,同时在生成过程中通过交叉注意力(Cross-Attention)机制关注编码器的输出。这类模型天然适合序列到序列(Sequence-to-Sequence - Seq2Seq)任务。
在预训练模型时代,一些重要的模型也采用了编码器-解码器架构,并通过创新的预训练任务实现了强大的文本迁移(Text-to-Text Transfer)能力。
5.4.1 T5与文本到文本框架
介绍T5将所有任务转化为文本到文本格式的统一范式。
T5(Text-to-Text Transfer Transformer)由Google Research于2019年提出。其最重要的贡献在于提出了文本到文本(Text-to-Text)的统一框架。
其核心理念是:将所有自然语言处理任务都视为文本输入到文本输出的问题,通过在输入文本前添加一个任务前缀(Task Prefix)来区分不同的任务。
例如:
⚝ 机器翻译:输入 "translate English to German: That is good.",期望输出 "Das ist gut."
⚝ 文本摘要:输入 "summarize: [文章内容]",期望输出 "[摘要内容]"
⚝ 问答:输入 "question: [问题] context: [上下文]",期望输出 "[答案]"
⚝ 文本分类:输入 "cola sentence: [句子]",期望输出 "acceptable" 或 "unacceptable" (CoLA是语言可接受性判断任务)
T5模型本身是标准的Transformer编码器-解码器结构,通过在海量无标注数据(Colossal Clean Crawled Corpus - C4)上进行去噪目标(Denoising Objective)的预训练来实现文本到文本的转换能力。它的预训练任务类似于掩码语言模型,但目标是预测被掩盖的完整文本跨度(Span),而不是单个Token。
这种统一的文本到文本框架使得T5具有极强的通用性,可以使用相同的模型、损失函数和超参数来处理各种不同的NLP任务,极大地简化了模型设计和应用流程。
5.4.2 BART与去噪自编码预训练
介绍BART通过重构被破坏文本进行预训练的方法。
BART(Bidirectional and Auto-Regressive Transformer)由Facebook AI于2019年提出。它也采用了标准的Transformer编码器-解码器结构。
BART的创新之处在于其去噪自编码(Denoising Autoencoding)的预训练任务。它通过以下两个步骤进行训练:
① 破坏(corrupt)原始文本:使用多种方式对输入文本进行破坏,例如:
▮▮▮▮ⓑ Token Masking (Token掩码):随机遮盖Token,类似于BERT的MLM。
▮▮▮▮ⓒ Token Deletion (Token删除):随机删除Token。
▮▮▮▮ⓓ Text Infilling (文本填充):将多个连续的文本跨度替换为一个特殊的[MASK] Token。
▮▮▮▮ⓔ Sentence Permutation (句子重排):打乱句子的顺序。
▮▮▮▮ⓕ Document Rotation (文档旋转):随机选择一个Token作为文档的起始点,将文档“旋转”过来。
⑦ 重构(reconstruct)原始文本:训练解码器根据被破坏的输入文本重构出原始的文本序列。这是一个自回归的生成任务。
这种预训练任务结合了BERT的双向编码(通过编码器处理被破坏文本)和GPT的自回归生成(通过解码器重构原始文本)的优点,使得BART在各种文本生成和文本理解任务上都表现出色。它的预训练目标比传统的MLM或自回归语言模型更全面地捕捉了文本的结构和语义信息。
5.4.3 应用场景:机器翻译、文本摘要等
探讨Encoder-Decoder模型适用的下游任务。
编码器-解码器模型由于其输入序列到输出序列的转换特性,非常适合各种Seq2Seq任务:
① 机器翻译 (Machine Translation):
▮▮▮▮这是Encoder-Decoder模型的经典应用领域,模型将源语言序列(输入)翻译成目标语言序列(输出)。
② 文本摘要 (Text Summarization):
▮▮▮▮将长文本(输入)概括为短文本(输出)。Encoder-Decoder模型尤其擅长抽象式摘要。
③ 文本生成 (Text Generation):
▮▮▮▮虽然Decoder-only模型更常用于开放式文本生成,但Encoder-Decoder模型也可以用于有条件的文本生成,例如根据关键词生成句子,或根据结构化数据生成自然语言描述。
④ 问答系统 (Question Answering):
▮▮▮▮生成式问答,根据问题和上下文生成回答。
⑤ 对话系统 (Dialogue Systems):
▮▮▮▮生成对话回复。
⑥ 风格迁移 (Style Transfer):
▮▮▮▮将输入文本转换为具有特定风格(如正式、幽默等)的输出文本。
Encoder-Decoder模型在各种需要将一种序列转换为另一种序列的任务中展现出强大的能力,尤其是T5和BART等预训练模型,通过微调可以在各种Seq2Seq任务上取得优秀的性能。
5.5 高效Transformer (Efficient Transformers)
介绍为处理长序列和提高计算效率而设计的Transformer变体,如 Longformer, Reformer, Performer等。
尽管原始Transformer架构在许多任务上取得了巨大成功,但其核心的多头自注意力机制存在一个显著的计算瓶颈:计算注意力权重矩阵的复杂度与序列长度 \(L\) 的平方成正比,即 \(O(L^2)\),内存占用也是 \(O(L^2)\)。这使得Transformer在处理非常长的序列(例如,文档级别的文本、高分辨率图像、长音频序列)时面临计算成本过高和内存不足的问题。
为了解决这一问题,研究人员提出了各种高效Transformer(Efficient Transformers)变体,它们通过修改或近似注意力机制,将计算复杂度降低到接近线性(\(O(L)\) 或 \(O(L \log L)\))。主要思路包括:
① 稀疏注意力 (Sparse Attention):
▮▮▮▮不是计算序列中所有位置之间的注意力,而是只计算部分位置之间的注意力。例如,限制注意力范围(Local Attention)、引入跨步注意力(Strided Attention)、或者基于图结构/固定模式的注意力。
▮▮▮▮代表模型:
▮▮▮▮▮▮▮▮❶ Longformer:结合了局部窗口注意力(Local Windowed Attention)和全局注意力(Global Attention),局部注意力捕捉近距离依赖,全局注意力捕捉特定重要Token(如[CLS] Token)与序列中所有其他Token的依赖。复杂度为 \(O(L)\)。
▮▮▮▮▮▮▮▮❷ Reformer:使用了局部敏感哈希(Locality Sensitive Hashing - LSH)来分组Token,只计算同一组内Token的注意力,近似实现了稀疏注意力。此外还引入了可逆层(Reversible Layers)来降低内存消耗。复杂度为 \(O(L \log L)\)。
② 线性化注意力 (Linearized Attention):
▮▮▮▮尝试将注意力机制的计算分解,避免构建显式的 \(L \times L\) 的注意力矩阵。通常利用核方法(Kernel Methods)或引入循环结构。
▮▮▮▮代表模型:
▮▮▮▮▮▮▮▮❶ Performer:使用正交随机特征(Orthogonal Random Features - ORF)对softmax注意力进行核近似,将注意力的计算复杂度降低到 \(O(L)\)。
③ 低秩注意力 (Low-Rank Attention):
▮▮▮▮基于注意力矩阵通常是低秩(Low-Rank)的假设,通过一些方法近似计算低秩表示,从而降低计算量。
▮▮▮▮代表模型:
▮▮▮▮▮▮▮▮❶ Linformer:通过线性投影将Key和Value的序列长度从 \(L\) 投影到一个更小的常数 \(k\),使得注意力计算复杂度降低到 \(O(L \cdot k)\),近似于 \(O(L)\)。
这些高效Transformer的设计目标是在保持Transformer强大建模能力的同时,突破其在长序列处理上的限制,为处理文档级任务、高分辨率图像分析、长时间序列预测等应用提供了可能。虽然它们在特定任务上可能与标准Transformer略有差异,但它们为Transformer家族开辟了新的研究方向和应用领域。
6. Transformer在多领域的应用
6.1 自然语言处理 (NLP)
注意力机制(Attention Mechanism)和Transformer模型最初在自然语言处理(Natural Language Processing, NLP)领域崭露头角,并迅速成为该领域的基石技术。它们有效解决了传统循环神经网络(RNN)和长短期记忆网络(LSTM)在处理长序列时遇到的长距离依赖(Long-Range Dependencies)和并行计算效率低下的问题。本节将详细探讨Transformer在多个经典NLP任务中的应用及其带来的影响。
Transformer模型的核心优势在于其自注意力机制(Self-Attention),它允许模型在处理序列中的某个词时,能够同时考虑序列中的所有其他词,并根据重要性分配不同的权重。这种全局感知能力对于理解复杂的语言结构至关重要。
① 机器翻译 (Machine Translation)
▮▮▮▮机器翻译是Transformer最初提出并取得巨大成功的领域。经典的Encoder-Decoder架构结合注意力机制在统计机器翻译和早期的神经机器翻译中取得了显著进展。Transformer模型完全基于注意力机制,抛弃了循环结构,这使得模型可以更好地捕捉长距离依赖,并显著提高了训练的并行度。
▮▮▮▮以论文《Attention Is All You Need》提出的Transformer模型为例,编码器(Encoder)负责将源语言句子编码为一系列向量表示,解码器(Decoder)则根据编码器的输出和已生成的目标语言序列,逐步生成目标语言句子。解码器的注意力机制(Encoder-Decoder Attention)允许其在生成每个目标词时,重点关注源语言句子中最相关的部分。
▮▮▮▮Transformer在机器翻译任务上取得了当时最先进(State-of-the-Art, SOTA)的性能,特别是在处理长句子时,其翻译质量和速度都远超基于RNN的模型。
② 文本分类 (Text Classification)
▮▮▮▮文本分类是将文本段落(如评论、新闻文章)划分到预定义类别(如正面/负面情感、体育/财经新闻)的任务。Transformer模型,尤其是仅编码器模型(Encoder-only Models)如BERT,在文本分类任务上表现出色。
▮▮▮▮通常的做法是,将文本输入预训练的Transformer编码器,获取整个文本的上下文相关的表示(例如,[CLS] token 的最终隐藏状态),然后将这个表示输入一个简单的线性分类器(Linear Classifier)进行分类。
▮▮▮▮自注意力机制使得模型能够理解文本中词语之间的复杂关系,从而更准确地捕捉文本的整体含义和情感。
③ 问答系统 (Question Answering, QA)
▮▮▮▮问答系统旨在根据给定的文本(如文档、段落)回答用户提出的问题。Transformer模型在抽取式问答(Extractive QA)和生成式问答(Generative QA)中都有广泛应用。
▮▮▮▮对于抽取式问答,模型需要从原文中找到答案所在的起始和结束位置。使用 BERT 等模型时,通常会将问题和原文拼接起来作为输入,然后训练两个线性层来预测答案的起始和结束位置。
▮▮▮▮对于生成式问答,模型需要根据原文生成一个全新的答案。T5 或 GPT 系列等Encoder-Decoder或Decoder-only模型更适合此类任务。它们可以将问题和原文作为输入,生成流畅且准确的答案。
④ 文本摘要 (Text Summarization)
▮▮▮摘要生成是将长文本压缩成简短、准确概括原文主旨的摘要。这通常是一个序列到序列(Sequence-to-Sequence)任务,非常适合使用Transformer的Encoder-Decoder架构。
▮▮▮模型编码器处理原文,解码器生成摘要。注意力机制帮助解码器在生成摘要时,聚焦于原文中最关键的信息点。
▮▮▮Transformer模型可以用于抽取式摘要(从原文中抽取句子组成摘要)和生成式摘要(生成全新的句子作为摘要)。BART、T5等模型在生成式摘要任务中取得了显著成果。
⑤ 对话系统 (Dialogue Systems)
▮▮▮▮对话系统涵盖任务型对话和开放域聊天机器人。Transformer模型在两类对话系统中都扮演着重要角色。
▮▮▮▮在开放域对话中,模型需要理解用户的话语并生成连贯、自然的回复。Decoder-only模型如GPT系列因其强大的文本生成能力而被广泛应用于构建聊天机器人。它们可以将对话历史作为输入,生成下一个回合的回复。
▮▮▮▮在任务型对话中,Transformer可以用于自然语言理解(Natural Language Understanding, NLU)环节,解析用户的意图和槽位信息;也可以用于对话状态追踪(Dialogue State Tracking, DST)或自然语言生成(Natural Language Generation, NLG)环节。
总而言之,Transformer凭借其强大的并行计算能力和捕捉长距离依赖的能力,在NLP的几乎所有子领域都取得了革命性的进展,并催生了以预训练大模型(Pre-trained Large Models)为代表的新范式。
6.2 计算机视觉 (Computer Vision)
Transformer模型最初是为序列数据(如文本)设计的,但很快研究人员发现其核心机制——自注意力(Self-Attention)——能够非常有效地捕捉输入元素之间的相互关系,这使得它也非常适用于处理图像等非序列数据。将Transformer引入计算机视觉(Computer Vision, CV)领域,带来了与卷积神经网络(CNN)截然不同的处理范式。
① 视觉Transformer (Vision Transformer, ViT)
▮▮▮▮将Transformer直接应用于图像的关键挑战在于图像的高维度和网格状结构。ViT模型的创新之处在于,它将一张图像分割成固定大小的图像块(Image Patches),并将这些图像块展平(Flatten)成一个序列。每个图像块可以被视为一个“token”,类似于文本中的词。
▮▮▮▮具体步骤如下:
▮▮▮▮▮▮▮▮❶ 图像分块与展平 (Patching and Flattening): 将输入的 \( H \times W \times C \) 图像分割成 \( N \) 个大小为 \( P \times P \) 的图像块,其中 \( N = HW/P^2 \)。这些块被展平为 \( N \) 个 \( P^2C \) 维向量。
▮▮▮▮▮▮▮▮❷ 线性嵌入 (Linear Embedding): 将每个展平的图像块通过一个线性投影层映射到模型的隐藏维度 \( D \)。
▮▮▮▮▮▮▮▮❸ 位置嵌入 (Positional Embedding): 由于Transformer本身不具备位置信息,需要向图像块嵌入中添加位置编码(Positional Encoding),以保留图像块的空间信息。可以使用可学习的位置嵌入或固定位置编码。
▮▮▮▮▮▮▮▮❹ Transformer编码器 (Transformer Encoder): 将带有位置信息的图像块嵌入序列输入到一个标准的Transformer编码器中。编码器由多个多头自注意力(Multi-Head Self-Attention)层和前馈神经网络(Feed-Forward Network)组成。自注意力机制使得模型能够计算图像中不同图像块之间的相互关系,捕捉全局依赖。
▮▮▮▮▮▮▮▮❺ 分类头 (Classification Head): 为了进行图像分类,ViT在序列的开头添加一个特殊的 [CLS] token(类似于BERT),该token的输出表示整个图像的特征。将 [CLS] token 的最终表示通过一个MLP头进行分类。
\[ \text{Image} \rightarrow \text{Patches} \rightarrow \text{Linear Projection} \rightarrow \text{Patch Embeddings} + \text{Positional Embeddings} \rightarrow \text{Transformer Encoder} \rightarrow \text{[CLS] Token Output} \rightarrow \text{Classification} \]
▮▮▮▮ViT证明了在足够大的数据集上(如 JFT-300M)进行预训练时,Transformer模型可以达到甚至超越CNN模型在图像分类任务上的性能,而且参数量更少。这开启了将Transformer应用于各种视觉任务的新篇章。
② 目标检测 (Object Detection)
▮▮▮▮目标检测是识别图像中物体的位置和类别。传统的Faster R-CNN等方法依赖于区域提议(Region Proposal)或锚框(Anchor Box),流程相对复杂。DETR (DEtection TRansformer) 是第一个完全端到端(End-to-end)的使用Transformer进行目标检测的模型。
▮▮▮▮DETR将目标检测视为一个序列预测问题。它使用CNN骨干网络提取图像特征,然后将这些特征展平并作为Transformer编码器的输入。解码器则并行地预测一组固定数量(例如100个)的目标框(Bounding Box)和类别。
▮▮▮▮解码器的独特之处在于使用了“目标查询”(Object Queries),这些查询是可学习的嵌入向量,通过自注意力和编码器-解码器注意力与编码器输出交互。每个查询负责检测图像中的一个潜在目标。Transformer的注意力机制使得模型能够直接预测目标框,无需非极大值抑制(Non-Maximum Suppression, NMS)等后处理步骤,简化了检测流程。
③ 图像分割 (Image Segmentation)
▮▮▮▮图像分割是将图像中的每个像素分类到不同的语义类别或实例。Transformer也被应用于语义分割和实例分割任务。
▮▮▮▮例如,Segmentation Transformer (SETR) 将ViT的思想应用于语义分割,通过Transformer编码器处理图像块序列,然后在编码器输出的基础上进行上采样(Upsampling)以生成像素级别的预测。
▮▮▮▮MaskFormer及其变体则将分割任务统一为一个基于查询(Query-based)的预测问题,利用Transformer解码器通过查询来预测一组二进制掩码(Binary Masks)和对应的类别,能够同时处理语义分割、实例分割和全景分割(Panoptic Segmentation)。
④ 其他视觉任务
▮▮▮▮Transformer还在许多其他计算机视觉任务中取得了成功,例如:
▮▮▮▮▮▮▮▮❶ 图像生成 (Image Generation):扩散模型(Diffusion Models)和生成对抗网络(GANs)中开始融入Transformer结构,例如在生成器或判别器中。
▮▮▮▮▮▮▮▮❷ 视频处理 (Video Processing):将视频帧序列或视频块序列输入Transformer,用于视频分类、动作识别等任务。
▮▮▮▮▮▮▮▮❸ 三维视觉 (3D Vision):将点云(Point Cloud)数据视为点的序列,使用Transformer处理点云分类、分割等任务。
尽管Transformer在视觉领域取得了巨大成功,但其计算开销(特别是自注意力机制)在处理高分辨率图像时仍然是一个挑战,许多研究致力于开发更高效的视觉Transformer变体。
6.3 语音处理 (Speech Processing)
语音处理(Speech Processing)领域涉及将语音信号转换为文本(语音识别,Automatic Speech Recognition, ASR)或将文本转换为语音信号(语音合成,Text-to-Speech, TTS),以及其他如说话人识别、语音增强等任务。语音数据本质上也是一种序列数据(随时间变化的声波信号或其特征表示),这使得Transformer模型非常适合处理这类任务。
① 自动语音识别 (Automatic Speech Recognition, ASR)
▮▮▮▮ASR的目标是将连续的语音信号转化为文本序列。传统ASR系统通常包含声学模型(Acoustic Model)、发音词典(Pronunciation Dictionary)和语言模型(Language Model),流程较为复杂。端到端(End-to-end)ASR模型简化了流程,直接将声学特征序列映射到文本序列。Transformer在端到端ASR模型中发挥了关键作用。
▮▮▮▮常见的基于Transformer的端到端ASR模型包括:
▮▮▮▮▮▮▮▮❶ Encoder-Decoder模型: 类似于机器翻译,编码器处理输入的声学特征序列(例如MFCC或Fbank特征),解码器生成文本序列。Attention机制在这里用于对齐声学特征和文本。
▮▮▮▮▮▮▮▮❷ 基于Connectionist Temporal Classification (CTC) 的模型: Transformer编码器输出声学特征的序列表示,CTC层直接从这个序列预测输出,无需显式对齐。
▮▮▮▮▮▮▮▮❸ 基于Transformer Transducer 的模型: 结合了CTC和Attention机制的思想,能够进行流式(Streaming)ASR。
▮▮▮▮此外,结合卷积神经网络(CNN)和Transformer的模型,如Conformer,在ASR任务中取得了领先性能。CNN善于捕捉局部特征,而Transformer善于捕捉全局依赖,二者结合能更好地处理语音序列。
② 语音合成 (Text-to-Speech, TTS)
▮▮▮▮TTS的目标是将文本序列转化为自然的语音波形。这是一个将文本特征映射到声学特征或原始波形的序列生成任务。Transformer结构在TTS的各个阶段都有应用。
▮▮▮▮经典的Tacotron2等模型使用Attention机制对齐文本和声学特征。基于Transformer的端到端TTS模型如Transformer TTS则完全依赖于Transformer架构,编码器处理输入文本序列,解码器生成梅尔谱图(Mel-spectrogram)或其他声学特征序列,然后通过声码器(Vocoder,如WaveGlow, HiFi-GAN)将声学特征转换为波形。
▮▮▮▮Transformer的并行计算能力提高了TTS的推理速度,其强大的建模能力有助于生成更自然、更富有表现力的语音。
③ 语音表示学习 (Speech Representation Learning)
▮▮▮▮类似于自然语言处理中的词嵌入或预训练语言模型,Transformer也被用于从大规模无标注语音数据中学习通用的语音表示。
▮▮▮▮例如,Wav2Vec 2.0 模型使用对比学习(Contrastive Learning)的方式,通过Transformer编码器处理原始音频波形,学习上下文敏感的语音单元表示。这些预训练的语音表示可以迁移到下游任务,如ASR、语音识别等,显著提高小数据集上的性能。
④ 其他语音任务
▮▮▮▮Transformer还在说话人识别(Speaker Recognition)、语音分离(Speech Separation)、语音增强(Speech Enhancement)等语音处理任务中展现出潜力,通过建模语音信号中不同部分之间的关系来提升任务性能。
Transformer模型在语音处理领域的成功应用,证明了其作为通用序列建模器(Universal Sequence Modeler)的强大能力,能够有效地处理和理解复杂的语音信号。
6.4 生物信息学 (Bioinformatics)
生物信息学(Bioinformatics)是一个利用计算方法研究生物数据(如DNA序列、蛋白质序列、基因表达数据)的交叉学科。生物序列数据,如DNA(由A、T、C、G四种碱基组成的序列)和蛋白质(由20种氨基酸组成的序列),天然地适合使用序列模型进行处理。Transformer凭借其在处理长序列和捕捉序列内部复杂依赖关系方面的优势,在生物信息学领域取得了突破性进展。
① 蛋白质结构预测 (Protein Structure Prediction)
▮▮▮▮蛋白质的功能与其三维结构紧密相关。从氨基酸序列预测蛋白质的精确三维结构是生物信息学领域长期以来最具挑战性的问题之一。AlphaFold2是DeepMind开发的一款基于深度学习的蛋白质结构预测系统,它在CASP(Critical Assessment of protein Structure Prediction)竞赛中取得了惊人的准确性,其核心架构大量借鉴了Transformer的思想。
▮▮▮▮AlphaFold2 使用了一种称为“演变式Transformer”(Evoformer)的架构,该架构是Transformer的变体。它同时处理蛋白质的氨基酸序列和相关的多序列比对(Multiple Sequence Alignment, MSA)信息。Evoformer通过多次迭代,利用自注意力机制(在序列方向和MSA方向)和交叉注意力机制(Cross-Attention)来推理氨基酸残基之间的相互作用,预测氨基酸之间的距离和角度。
▮▮▮▮这种方法能够有效地捕捉蛋白质序列中远距离氨基酸残基之间的相互作用,这些相互作用对于决定蛋白质如何折叠成其最终的三维结构至关重要。AlphaFold2的成功极大地推动了生物学研究的进程。
② 基因组学 (Genomics)
▮▮▮▮基因组是DNA序列的集合,分析基因组数据对于理解遗传、疾病机制等至关重要。Transformer也被应用于基因组学任务:
▮▮▮▮▮▮▮▮❶ DNA序列分析: 将DNA序列视为由A、T、C、G组成的文本序列,使用Transformer模型进行序列分类(如预测非编码DNA区域的功能)、序列比对、变异检测等。
▮▮▮▮▮▮▮▮❷ 基因表达预测: Transformer可以用来预测基因表达水平,或者理解调控序列(Regulatory Sequences)如何影响基因表达。
▮▮▮▮▮▮▮▮❸ 蛋白质-DNA相互作用预测: 预测蛋白质在基因组上的结合位点,这对于理解基因调控网络非常重要。Transformer可以通过建模蛋白质序列和DNA序列之间的相互作用来实现。
③ 药物发现 (Drug Discovery)
▮▮▮▮在药物发现过程中,研究人员需要分析大量分子数据(如化合物结构、蛋白质靶点)并预测它们之间的相互作用。Transformer可以应用于:
▮▮▮▮▮▮▮▮❶ 分子性质预测: 将化学分子表示为序列(例如SMILES字符串)或图结构(Graph Structure),使用Transformer或其变体来预测分子的物理化学性质或药代动力学(Pharmacokinetics)性质。
▮▮▮▮▮▮▮▮❷ 蛋白质-配体结合亲和力预测: 预测小分子药物与蛋白质靶点结合的强度。这可以建模为蛋白质序列和分子序列之间的相互作用问题,用Transformer进行处理。
生物信息学领域中的数据往往庞大且复杂,序列中的长距离依赖和复杂的相互作用是常见特征。Transformer模型强大的关系建模能力使其成为解决这些挑战性问题的有力工具,并在蛋白质结构预测等领域带来了革命性的突破。
6.5 跨模态学习 (Cross-modal Learning)
跨模态学习(Cross-modal Learning)旨在构建能够理解和关联来自不同模态(如文本、图像、音频、视频)信息的模型。人类能够轻松地在不同模态之间进行切换和理解,例如看图说话、听音辨物。构建具备类似能力的AI系统是人工智能的重要目标。Transformer模型,特别是其灵活的注意力机制,为实现跨模态信息的有效融合和理解提供了强大的框架。
① 跨模态任务的挑战
▮▮▮▮不同模态的数据具有不同的结构(如图像是网格,文本是序列,音频是时序信号)和表示形式。跨模态学习的核心挑战在于如何对齐(Alignment)和融合(Fusion)这些异构信息,使得模型能够同时理解和关联它们的内容。
② Transformer在跨模态学习中的作用
▮▮▮▮Transformer的注意力机制天生适合处理跨模态任务:
▮▮▮▮▮▮▮▮❶ 统一表示: 可以将不同模态的数据通过各自的编码器(例如,文本用Text Transformer,图像用Vision Transformer)转化为统一的向量空间中的表示。
▮▮▮▮▮▮▮▮❷ 跨模态注意力 (Cross-modal Attention): 使用注意力机制允许模型计算一个模态的元素(如文本中的词)与另一个模态的元素(如图像中的区域或图像块)之间的相关性。例如,在图像描述生成中,解码器在生成文本词语时,可以通过注意力机制关注图像中最相关的区域。
▮▮▮▮▮▮▮▮❸ 序列到序列的转化: 许多跨模态任务可以被建模为将一个模态的序列转化为另一个模态的序列,这正是Transformer的强项。
③ 典型的跨模态应用
▮▮▮▮Transformer已被广泛应用于各种跨模态任务:
▮▮▮▮▮▮▮▮❶ 图像描述生成 (Image Captioning): 输入图像,输出描述图像内容的文本句子。通常使用CNN或ViT作为图像编码器,Transformer解码器生成文本,并使用交叉注意力连接两者。
▮▮▮▮▮▮▮▮❷ 视觉问答 (Visual Question Answering, VQA): 输入图像和关于图像的问题(文本),输出问题的答案(文本或选择)。模型需要理解图像内容和问题意图,并将二者关联起来找到答案。Transformer可以通过多模态融合模块(Multi-modal Fusion Module)结合图像和文本特征进行推理。
▮▮▮▮▮▮▮▮❸ 文本到图像生成 (Text-to-Image Generation): 输入文本描述,生成符合描述的图像。DALL-E、Stable Diffusion等模型中的许多组件都采用了Transformer或其变体,用于理解文本并指导图像的生成过程。
▮▮▮▮▮▮▮▮❹ 图像搜索与匹配: 输入图像查找相关文本,或输入文本查找相关图像。CLIP (Contrastive Language–Image Pre-training) 等模型通过在大量图像-文本对上进行对比学习,训练一个能够将图像和文本映射到同一嵌入空间的模型。CLIP使用Text Transformer和Vision Transformer分别编码文本和图像,并通过计算编码后的向量相似度来衡量图像与文本的相关性。
▮▮▮▮▮▮▮▮❺ 视频与文本相关任务: 例如视频字幕生成(Video Captioning)、视频问答(Video Question Answering)、文本到视频检索等。将视频帧序列和文本序列输入Transformer进行处理。
▮▮▮▮▮▮▮▮❻ 语音与文本相关任务: 例如语音翻译(Speech Translation,将一种语言的语音直接翻译成另一种语言的文本)。这可以被视为语音序列到文本序列的转化,使用Transformer Encoder-Decoder架构实现。
Transformer在跨模态学习领域的成功应用,极大地推动了构建能够理解世界多方面信息的通用AI模型的发展,也为未来更智能、更具感知能力的AI系统奠定了基础。
7. 实践指南:使用Transformer模型
本章旨在将前几章学习的理论知识转化为实际操作能力。我们将探讨如何在主流深度学习框架中构建和使用Transformer模型,特别是借助强大的Hugging Face Transformers库。此外,本章还将涵盖如何利用预训练模型进行微调,从头开始训练模型的流程,以及模型评估、分析和部署的关键实践。无论您是希望快速应用现有模型,还是深入理解模型训练的每一个环节,本章都将为您提供实用的指导和技术栈。
7.1 主流框架中的实现 (Implementations in Major Frameworks)
在深度学习领域,PyTorch和TensorFlow是目前最主流的两大框架。它们都提供了构建复杂神经网络的丰富工具和API,当然也包括实现Transformer模型所需的各种模块。理解如何在这些基础框架中手动构建Transformer的各个组件,有助于我们更深入地理解模型的工作原理,并为魔改(modification)或从零开始构建自定义架构打下基础。
要点:如何在PyTorch和TensorFlow中构建Transformer的核心组件:多头注意力、前馈网络、残差连接与层归一化、完整的编码器/解码器层。
7.1.1 使用PyTorch构建Transformer组件
PyTorch以其动态图特性和简洁的API深受研究者喜爱。它提供了torch.nn
模块,其中包含构建各种层和网络的基石。
① 多头自注意力 (Multi-Head Self-Attention):
PyTorch提供了torch.nn.MultiheadAttention
模块,可以直接实现多头注意力的功能。您只需要指定模型的维度(embed_dim
)和注意力头的数量(num_heads
)。
1
import torch
2
import torch.nn as nn
3
4
# 假设输入维度为 512,注意力头数量为 8
5
embed_dim = 512
6
num_heads = 8
7
batch_size = 32
8
seq_len = 100 # 序列长度
9
10
# 随机生成一个模拟输入,形状为 (序列长度, 批量大小, 特征维度)
11
# 注意:PyTorch的MultiheadAttention默认输入形状是 (SeqLen, BatchSize, EmbedDim)
12
dummy_input = torch.randn(seq_len, batch_size, embed_dim)
13
14
# 创建多头注意力层
15
# batch_first=False 是默认值,表示 (SeqLen, BatchSize, EmbedDim)
16
multihead_attn = nn.MultiheadAttention(embed_dim=embed_dim, num_heads=num_heads)
17
18
# 前向传播
19
# key_padding_mask 可以用于处理变长序列,这里忽略
20
attn_output, attn_weights = multihead_attn(dummy_input, dummy_input, dummy_input)
21
22
print("多头注意力输出形状:", attn_output.shape) # (seq_len, batch_size, embed_dim)
23
print("注意力权重形状:", attn_weights.shape) # (batch_size, seq_len, seq_len)
② 前馈网络 (Feed-Forward Network):
Transformer中的前馈网络通常是一个包含两个线性变换和一个ReLU激活函数的全连接网络。
1
# 通常的实现是一个两层的MLP
2
class PositionwiseFeedForward(nn.Module):
3
def __init__(self, d_model, d_ff, dropout=0.1):
4
super().__init__()
5
# 第一个线性层,维度从 d_model 扩展到 d_ff
6
self.w_1 = nn.Linear(d_model, d_ff)
7
# 第二个线性层,维度从 d_ff 恢复到 d_model
8
self.w_2 = nn.Linear(d_ff, d_model)
9
# Dropout 层用于正则化
10
self.dropout = nn.Dropout(dropout)
11
# 激活函数,通常是ReLU或GELU
12
self.relu = nn.ReLU()
13
14
def forward(self, x):
15
# x 形状通常是 (批量大小, 序列长度, d_model)
16
# PyTorch MultiheadAttention 的输出是 (SeqLen, BatchSize, EmbedDim),需要转置
17
if x.ndim == 3 and x.shape[0] == seq_len and x.shape[1] == batch_size: # 检查是否是 MultiheadAttention 的输出形状
18
x = x.transpose(0, 1) # 转置为 (BatchSize, SeqLen, EmbedDim)
19
20
# 前向传播
21
return self.w_2(self.dropout(self.relu(self.w_1(x))))
22
23
# 创建前馈网络实例
24
d_model = 512 # 模型维度
25
d_ff = 2048 # 前馈网络的中间层维度
26
ffn = PositionwiseFeedForward(d_model, d_ff)
27
28
# 模拟输入,形状为 (批量大小, 序列长度, 模型维度)
29
dummy_input_ffn = torch.randn(batch_size, seq_len, d_model)
30
31
# 前向传播
32
ffn_output = ffn(dummy_input_ffn)
33
print("FFN 输出形状:", ffn_output.shape) # (batch_size, seq_len, d_model)
③ 残差连接与层归一化 (Residual Connection and Layer Normalization):
Transformer中广泛使用残差连接 (x + sublayer_output
) 和层归一化 (LayerNorm
)。PyTorch提供了torch.nn.LayerNorm
。
1
# 模拟一个子层(可以是注意力或FFN)的输出
2
sublayer_output = torch.randn(batch_size, seq_len, embed_dim)
3
input_to_sublayer = torch.randn(batch_size, seq_len, embed_dim) # 子层的输入
4
5
# 残差连接
6
output_after_residual = input_to_sublayer + sublayer_output
7
8
# 层归一化
9
layer_norm = nn.LayerNorm(embed_dim)
10
output_after_norm = layer_norm(output_after_residual)
11
12
print("残差连接后形状:", output_after_residual.shape) # (batch_size, seq_len, embed_dim)
13
print("层归一化后形状:", output_after_norm.shape) # (batch_size, seq_len, embed_dim)
在Transformer的Add & Norm子层中,通常先进行残差连接,然后进行层归一化。
④ 完整的编码器/解码器层 (Encoder/Decoder Layer):
将上述组件组合起来,就可以构建一个完整的编码器层或解码器层。PyTorch的torch.nn.TransformerEncoderLayer
和torch.nn.TransformerDecoderLayer
提供了现成的实现。
1
# 编码器层
2
encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048)
3
# 输入形状 (序列长度, 批量大小, 特征维度)
4
src = torch.randn(seq_len, batch_size, embed_dim)
5
out_encoder = encoder_layer(src)
6
print("Encoder Layer 输出形状:", out_encoder.shape) # (seq_len, batch_size, embed_dim)
7
8
# 解码器层
9
decoder_layer = nn.TransformerDecoderLayer(d_model=512, nhead=8, dim_feedforward=2048)
10
# tgt 输入形状 (目标序列长度, 批量大小, 特征维度)
11
tgt = torch.randn(seq_len, batch_size, embed_dim)
12
# memory 输入形状 (编码器输出的序列长度, 批量大小, 特征维度)
13
memory = torch.randn(seq_len, batch_size, embed_dim) # 假设与编码器输出形状相同
14
out_decoder = decoder_layer(tgt, memory)
15
print("Decoder Layer 输出形状:", out_decoder.shape) # (seq_len, batch_size, embed_dim)
这些内置模块极大地简化了Transformer模型的搭建过程。
7.1.2 使用TensorFlow构建Transformer组件
TensorFlow,特别是其Keras API,也提供了构建Transformer的便利工具。Keras的 Sequential 或 Functional API 使得模型的组合非常直观。
① 多头自注意力 (Multi-Head Self-Attention):
TensorFlow Addons (tf-addons) 库曾提供了 MultiHeadAttention
层,现在 TensorFlow Core 库中的 tf.keras.layers.MultiHeadAttention
已成为官方推荐。
1
import tensorflow as tf
2
from tensorflow.keras.layers import Layer, Dense, Dropout, LayerNormalization, MultiHeadAttention
3
4
# 假设输入形状为 (批量大小, 序列长度, 特征维度)
5
batch_size = 32
6
seq_len = 100
7
embed_dim = 512
8
num_heads = 8
9
10
# 随机生成模拟输入
11
dummy_input = tf.random.normal((batch_size, seq_len, embed_dim))
12
13
# 创建多头注意力层
14
multihead_attn = MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim)
15
16
# 前向传播
17
# query, key, value 通常是相同的输入序列 for Self-Attention
18
attn_output = multihead_attn(query=dummy_input, value=dummy_input, key=dummy_input)
19
20
print("多头注意力输出形状:", attn_output.shape) # (batch_size, seq_len, embed_dim)
② 前馈网络 (Feed-Forward Network):
使用 Keras 的 Dense
层和 Dropout
层组合即可实现。
1
def feed_forward_network(d_model, d_ff, dropout=0.1):
2
# 使用 Sequential API 构建简单的 FFN
3
return tf.keras.Sequential([
4
Dense(d_ff, activation='relu'), # 或 'gelu'
5
Dropout(dropout),
6
Dense(d_model)
7
])
8
9
# 创建前馈网络实例
10
d_model = 512
11
d_ff = 2048
12
ffn = feed_forward_network(d_model, d_ff)
13
14
# 模拟输入
15
dummy_input_ffn = tf.random.normal((batch_size, seq_len, d_model))
16
17
# 前向传播
18
ffn_output = ffn(dummy_input_ffn)
19
print("FFN 输出形状:", ffn_output.shape) # (batch_size, seq_len, d_model)
③ 残差连接与层归一化 (Residual Connection and Layer Normalization):
Keras 提供了 Add
层用于残差连接,LayerNormalization
层用于层归一化。
1
# 模拟一个子层输出和其输入
2
sublayer_output = tf.random.normal((batch_size, seq_len, embed_dim))
3
input_to_sublayer = tf.random.normal((batch_size, seq_len, embed_dim))
4
5
# 残差连接
6
output_after_residual = tf.keras.layers.Add()([input_to_sublayer, sublayer_output])
7
8
# 层归一化
9
layer_norm = LayerNormalization(epsilon=1e-6) # 添加一个小的 epsilon 避免除以零
10
output_after_norm = layer_norm(output_after_residual)
11
12
print("残差连接后形状:", output_after_residual.shape) # (batch_size, seq_len, embed_dim)
13
print("层归一化后形状:", output_after_norm.shape) # (batch_size, seq_len, embed_dim)
在 Keras 中,Add & Norm 子层通常是将子层输出与输入相加,然后对结果应用层归一化。
④ 完整的编码器/解码器层 (Encoder/Decoder Layer):
可以通过组合上述构建的自定义层来构建,或者使用 TensorFlow Model Garden 中提供的实现作为参考。构建自定义 Keras Layer 是一个很好的实践方式。
1
class EncoderLayer(Layer):
2
def __init__(self, d_model, num_heads, d_ff, rate=0.1):
3
super().__init__()
4
self.mha = MultiHeadAttention(num_heads=num_heads, key_dim=d_model)
5
self.ffn = feed_forward_network(d_model, d_ff, rate) # 使用上面定义的 FFN 函数
6
7
self.layernorm1 = LayerNormalization(epsilon=1e-6)
8
self.layernorm2 = LayerNormalization(epsilon=1e-6)
9
10
self.dropout1 = Dropout(rate)
11
self.dropout2 = Dropout(rate)
12
13
def call(self, x, training, mask=None):
14
# 多头注意力
15
attn_output = self.mha(x, x, x, mask=mask)
16
attn_output = self.dropout1(attn_output, training=training)
17
# Add & Norm (残差连接 + 层归一化)
18
out1 = self.layernorm1(x + attn_output)
19
20
# 前馈网络
21
ffn_output = self.ffn(out1)
22
ffn_output = self.dropout2(ffn_output, training=training)
23
# Add & Norm
24
out2 = self.layernorm2(out1 + ffn_output)
25
26
return out2
27
28
# 创建编码器层实例
29
d_model = 512
30
num_heads = 8
31
d_ff = 2048
32
encoder_layer = EncoderLayer(d_model, num_heads, d_ff)
33
34
# 模拟输入,形状 (批量大小, 序列长度, 特征维度)
35
dummy_input_encoder = tf.random.normal((batch_size, seq_len, d_model))
36
37
# 前向传播 (需要指定 training 参数)
38
encoder_output = encoder_layer(dummy_input_encoder, training=False) # 或 training=True
39
print("Encoder Layer 输出形状:", encoder_output.shape) # (batch_size, seq_len, d_model)
构建完整的Transformer模型需要将多个编码器层和解码器层堆叠起来,并处理输入嵌入、位置编码、输出层等。虽然从头开始构建能加深理解,但在实际应用中,我们通常会依赖更高级的库。
7.2 拥抱Hugging Face Transformers库
对于绝大多数用户而言,从头开始构建和训练一个大规模的Transformer模型既不经济也不高效。Hugging Face的Transformers库应运而生,它是一个开源库,提供了数千种预训练模型(如BERT、GPT-2、GPT-3、T5、BART、ViT、DETR等)的实现、预训练权重、以及易于使用的API,极大地降低了使用Transformer模型的门槛。
要点:Hugging Face Transformers库的核心功能、模型加载、分词器、Pipeline API。
7.2.1 Hugging Face Transformers库概述
Hugging Face Transformers库支持PyTorch、TensorFlow和JAX等后端。它的主要优势在于:
⚝ 模型丰富: 提供了大量预训练模型,覆盖多种语言和任务。
⚝ 易于使用: 统一的API接口,加载和使用不同模型的方式相似。
⚝ 高效: 经过优化,支持分布式训练和模型并行。
⚝ 社区活跃: 强大的社区支持,不断有新的模型和功能加入。
核心组件:
⚝ Models: 各种模型架构的实现,例如BertModel
, GPT2Model
, T5ForConditionalGeneration
等。
⚝ Tokenizers: 各种模型对应的分词器,用于将原始文本转换为模型可理解的输入ID序列,例如BertTokenizer
, GPT2Tokenizer
等。
⚝ Pipelines: 高级API,将预处理、模型推理、后处理打包在一起,实现端到端任务。
7.2.2 模型与分词器加载
使用Hugging Face加载模型和分词器非常简单,通常只需要模型在Hugging Face Model Hub上的名称。AutoModel
和AutoTokenizer
是两个非常方便的类,它们可以根据指定的模型名称自动加载对应的模型类和分词器类。
1
# 确保已安装 transformers 库: pip install transformers
2
from transformers import AutoModel, AutoTokenizer
3
4
# 以 BERT Base 中文模型为例
5
model_name = "bert-base-chinese"
6
7
# 加载分词器 (Tokenizer)
8
# tokenizer 负责文本分词、转换为ID、添加特殊token等
9
tokenizer = AutoTokenizer.from_pretrained(model_name)
10
print(f"分词器 {model_name} 加载成功!")
11
12
# 加载模型 (Model)
13
# AutoModel 会加载模型的主体结构和预训练权重
14
model = AutoModel.from_pretrained(model_name)
15
print(f"模型 {model_name} 加载成功!")
16
17
# 也可以加载特定任务的模型,例如用于序列分类的 BERT
18
from transformers import AutoModelForSequenceClassification
19
model_for_classification = AutoModelForSequenceClassification.from_pretrained(model_name)
20
print(f"用于序列分类的模型 {model_name} 加载成功!")
21
22
# 加载模型通常需要网络连接以下载权重文件,它们会缓存到本地。
加载的模型是已经预训练好的模型主体。对于特定下游任务(如分类、问答),通常需要在模型主体之上添加一个任务特定的头部(head),AutoModelFor...
系列类就包含了这些任务头。
7.2.3 使用Pipeline API
Pipeline API是Hugging Face Transformers库中最简单易用的接口,它抽象了整个工作流程(预处理 -> 模型推理 -> 后处理),允许用户只需几行代码就能完成常见的NLP任务。
1
from transformers import pipeline
2
3
# 创建一个文本情感分类的 Pipeline
4
# 如果不指定模型,pipeline 会使用该任务的默认模型
5
classifier = pipeline("sentiment-analysis")
6
7
# 对一段文本进行情感分类
8
text1 = "这部电影太棒了,我非常喜欢!"
9
text2 = "会议的内容有点枯燥,希望能改进。"
10
11
result1 = classifier(text1)
12
result2 = classifier(text2)
13
14
print(f"文本 '{text1}' 的情感分析结果: {result1}")
15
print(f"文本 '{text2}' 的情感分析结果: {result2}")
16
17
# 也可以指定使用特定的模型,例如一个中文情感分析模型
18
# model_name_sentiment = "seara/bert-base-chinese-finetuned-sentiment" # 示例模型名
19
# classifier_zh = pipeline("sentiment-analysis", model=model_name_sentiment)
20
# result_zh = classifier_zh("这个产品还不错,值得推荐!")
21
# print(f"文本 '这个产品还不错,值得推荐!' 的情感分析结果: {result_zh}")
22
23
24
# 创建一个文本生成的 Pipeline (例如使用 GPT-2)
25
# generator = pipeline("text-generation", model="gpt2")
26
# generated_text = generator("Once upon a time,", max_length=50, num_return_sequences=1)
27
# print(f"生成的文本: {generated_text[0]['generated_text']}")
28
29
# 其他常用任务的 Pipeline 包括:
30
# "translation": 机器翻译
31
# "summarization": 文本摘要
32
# "question-answering": 问答
33
# "fill-mask": 完形填空
34
# "ner": 命名实体识别
35
# "zero-shot-classification": 零样本分类
Pipeline API 非常适合快速原型开发和验证模型能力,但也相对黑箱,不适合需要细粒度控制模型输入/输出或训练流程的场景。
7.3 使用预训练模型与微调 (Fine-tuning Pre-trained Models)
迁移学习(Transfer Learning)是深度学习领域的重要范式,而微调(Fine-tuning)是利用预训练模型进行迁移学习的常用方法。通过在大规模数据集上进行无监督或自监督预训练,模型学习到了通用的语言表示或图像特征。然后,我们可以使用相对较小的数据集针对特定下游任务(如文本分类、命名实体识别、问答等)对模型进行微调,使其适应新任务的需求。这比从头开始训练模型效率更高,并且在小数据集上也能取得更好的性能。```python
续接上一节的 PyTorch 或 TensorFlow 代码示例
1
要点:为何微调有效、微调的步骤、选择预训练模型、微调技巧。
2
3
#### 7.3.1 微调的概念与优势
4
① 微调(Fine-tuning):
5
微调是指在预训练模型的基础上,使用特定任务的数据集继续训练模型。在微调过程中,模型的原有权重会被作为初始值,并在新数据上进行少量或全部参数的更新。
6
7
② 为何微调有效?
8
大规模预训练模型(如BERT、GPT系列)在海量无标签数据上学习到了丰富的、具有通用性的特征表示。例如,BERT学会了理解词语在不同上下文中的含义(通过MLM任务),以及句子之间的关系(通过NSP任务)。这些通用知识对于许多下游任务都是有益的。通过微调,模型可以将这些通用知识迁移到特定任务上,从而在数据量有限的情况下也能取得很好的性能。
9
10
③ 微调的优势:
11
* **数据效率**: 在小数据集上也能表现良好,无需像从头训练那样需要海量数据。
12
* **训练速度**: 从预训练权重开始,收敛速度通常比随机初始化快。
13
* **性能提升**: 通常能达到比传统方法或从头训练更好的性能。
14
15
#### 7.3.2 微调的基本步骤
16
微调的过程通常包括以下几个核心步骤:
17
18
① **选择合适的预训练模型**:
19
根据你的任务类型和数据特点选择模型。
20
* 任务类型:文本分类通常选择BERT类(Encoder-only),文本生成通常选择GPT类(Decoder-only),序列到序列任务选择T5/BART类(Encoder-Decoder)。
21
* 数据语言:选择支持你的数据语言的模型(如BERT-base-chinese用于中文任务)。
22
* 模型规模:根据计算资源和性能需求选择模型大小(base, large等)。
23
24
② **准备任务数据集**:
25
收集并标注特定任务的数据集。将数据转换为模型期望的输入格式,这通常涉及到分词(Tokenization)和将文本/标签映射到模型能够处理的数字ID。
26
▮▮▮▮ⓐ 使用预训练模型对应的分词器处理原始文本,生成输入ID、注意力掩码(attention mask)、分段ID(segment ID,如BERT需要)。
27
▮▮▮▮ⓑ 将任务的标签(Label)转换为模型训练所需的格式(例如,分类任务的类别ID,序列标注任务的Token级别标签ID)。
28
29
③ **修改模型头部 (Modify Model Head)**:
30
预训练模型的顶部通常是用于预训练任务(如MLM、NSP)的特定头部。为了适应新的下游任务,需要移除原有的头部,并添加一个适合新任务的头部。
31
▮▮▮▮⚝ **文本分类**: 在Transformer编码器输出的`[CLS]`标记的隐藏状态之上添加一个全连接层(Dense layer)进行分类。
32
▮▮▮▮⚝ **序列标注**: 在Transformer编码器对每个Token的隐藏状态之上添加一个全连接层,输出每个Token对应的标签概率。
33
▮▮▮▮⚝ **问答**: 在Transformer编码器对问题和文本拼接输入后的隐藏状态之上,添加两个全连接层,分别预测答案开始位置和结束位置的概率。
34
▮▮▮▮⚝ **文本生成/序列到序列**: 使用Decoder-only或Encoder-Decoder模型的生成能力,可能需要调整输出层的词汇表大小。
35
36
Hugging Face库的`AutoModelFor...`系列类已经集成了这些任务头,加载时会自动添加并随机初始化任务头的参数,非常方便。例如,`AutoModelForSequenceClassification`加载BERT时会自动在顶部添加一个分类层。
37
38
④ **设置训练参数**:
39
配置优化器(Optimizer)、学习率调度策略(Learning Rate Scheduling)、损失函数(Loss Function)、批大小(Batch Size)、训练轮数(Epochs)等。
40
▮▮▮▮⚝ **优化器**: AdamW是常用的优化器,它结合了Adam的优点并加入了权重衰减(Weight Decay),对Transformer模型训练效果良好。
41
▮▮▮▮⚝ **学习率**: 微调的学习率通常设置得比预训练时小,以避免破坏预训练学到的通用特征。通常在 LaTex→→→5c,28,31,30,5e,7b,2d,35,7d,5c,29←←←LaTex 到 LaTex→→→5c,28,31,30,5e,7b,2d,34,7d,5c,29←←←LaTex 之间。可以采用随着训练进程逐渐衰减的学习率策略。
42
▮▮▮▮⚝ **损失函数**: 根据任务类型选择,如交叉熵损失(Cross-Entropy Loss)用于分类任务。
43
▮▮▮▮⚝ **训练轮数**: 微调通常只需要少量Epochs(如2-10个)就可以收敛,因为模型已经有很好的初始化。
44
45
⑤ **进行训练**:
46
使用准备好的数据集和设置的训练参数,通过反向传播更新模型的权重。训练过程中通常只更新任务头和部分Transformer层的参数,或者更新所有参数(Full Fine-tuning)。
47
48
⑥ **评估与调整**:
49
在验证集上监控模型性能,根据评估结果调整超参数或数据处理方式。在测试集上进行最终评估。
50
51
#### 7.3.3 微调技巧 (Fine-tuning Tips)
52
⚝ **学习率选择**: 较低的学习率对微调很重要。可以尝试不同的学习率或使用学习率预热和衰减策略。
53
⚝ **参数冻结 (Parameter Freezing)**: 有时为了在小数据集上避免过拟合,可以冻结底层的一部分或全部预训练层的参数,只训练新添加的任务头或高层参数。
54
⚝ **训练策略**:
55
▮▮▮▮⚝ 先冻结大部分层只训练头部和顶层,再解冻所有层进行全局微调。
56
▮▮▮▮⚝ 对不同层设置不同的学习率(Layer-wise Learning Rate Decay),底层用更小的学习率。
57
⚝ **数据增强 (Data Augmentation)**: 对文本数据进行数据增强(如同义词替换、随机删除/插入词等)可以增加数据多样性,提高模型泛化能力。
58
⚝ **多任务学习 (Multi-task Learning)**: 如果有相关的多个下游任务,可以尝试联合训练,让模型学习更鲁棒的表示。
59
⚝ **梯度累积 (Gradient Accumulation)**: 在GPU显存不足无法使用大Batch Size时,可以通过梯度累积来模拟大Batch Size的效果。
60
61
#### 7.3.4 使用Hugging Face Trainer API进行微调
62
Hugging Face库提供了`Trainer`类,它封装了标准的训练和评估循环,使得微调过程更加便捷。
63
64
```python
65
66
# 假设我们已经加载了模型和分词器,并且有了训练集和验证集数据
67
# 数据需要处理成模型期望的格式,通常是包含 input_ids, attention_mask, labels 的字典或 Dataset 对象
68
69
# from transformers import AutoModelForSequenceClassification, AutoTokenizer, Trainer, TrainingArguments
70
# from datasets import load_dataset # 示例使用 datasets 库加载数据
71
72
# # 加载模型和分词器 (以 BERT 进行分类为例)
73
# model_name = "bert-base-chinese"
74
# tokenizer = AutoTokenizer.from_pretrained(model_name)
75
# # 加载带有分类头的模型
76
# model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2) # 假设是二分类任务
77
78
# # 准备数据 (这里仅为概念性示例,实际数据处理会更复杂)
79
# # 假设 raw_datasets 是通过 load_dataset 加载的原始数据集对象
80
# def preprocess_function(examples):
81
# # 使用 tokenizer 处理文本
82
# # truncation=True 截断长序列, padding="max_length" 或 True 进行填充
83
# encodings = tokenizer(examples['text'], truncation=True, padding=True)
84
# # 将标签映射到 ID
85
# encodings['labels'] = examples['label']
86
# return encodings
87
88
# # processed_datasets = raw_datasets.map(preprocess_function, batched=True)
89
90
# # 定义训练参数
91
# training_args = TrainingArguments(
92
# output_dir="./results", # 输出目录
93
# num_train_epochs=3, # 训练的总轮数
94
# per_device_train_batch_size=8, # 每个设备的训练批量大小
95
# per_device_eval_batch_size=8, # 每个设备的评估批量大小
96
# warmup_steps=500, # 学习率预热步数
97
# weight_decay=0.01, # 权重衰减
98
# logging_dir="./logs", # 日志目录
99
# logging_steps=10,
100
# evaluation_strategy="epoch", # 每轮结束后进行评估
101
# save_strategy="epoch", # 每轮结束后保存检查点
102
# load_best_model_at_last_save=True, # 训练结束后加载最优模型
103
# metric_for_best_model="accuracy", # 用于选择最优模型的指标
104
# )
105
106
# # 定义评估指标函数 (例如计算准确率)
107
# # from datasets import load_metric
108
# # import numpy as np
109
# # metric = load_metric("accuracy")
110
111
# # def compute_metrics(eval_pred):
112
# # logits, labels = eval_pred
113
# # predictions = np.argmax(logits, axis=-1)
114
# # return metric.compute(predictions=predictions, references=labels)
115
116
# # 创建 Trainer 实例
117
# # trainer = Trainer(
118
# # model=model, # 要训练的模型
119
# # args=training_args, # 训练参数
120
# # train_dataset=processed_datasets["train"], # 训练数据集
121
# # eval_dataset=processed_datasets["validation"], # 评估数据集
122
# # compute_metrics=compute_metrics, # 评估指标函数 (可选)
123
# # )
124
125
# # 开始训练
126
# # trainer.train()
127
128
# # 训练完成后,最佳模型会保存在 output_dir 中
Trainer API 大幅简化了微调的代码实现,让研究者和开发者能够更专注于数据准备、模型选择和超参数调优。
7.4 从头开始训练Transformer模型 (Training Transformer Model from Scratch)
虽然微调是主流,但在某些情况下,从头开始训练Transformer模型是必要或更合适的:
⚝ 您拥有一个非常庞大且特定领域的数据集,预训练模型可能未能很好地覆盖该领域知识。
⚝ 您正在研究新的Transformer变体架构,还没有预训练的权重可用。
⚝ 您对模型的每一个细节都需要精细控制。
从头开始训练Transformer是一个资源密集型且复杂的任务。
要点:数据准备、模型构建、训练流程、挑战。
7.4.1 数据准备
训练一个Transformer模型,尤其是用于语言建模等任务,需要海量的训练数据。数据准备包括:
① 收集与清洗数据: 获取原始文本数据(如网页、书籍、对话语料等),进行必要的清洗(去除HTML标签、特殊字符、重复内容等)。
② 分词与构建词汇表 (Tokenization and Vocabulary): 选择合适的分词策略(如WordPiece, BPE),根据训练数据构建模型的词汇表(Vocabulary)。词汇表的大小会影响模型参数量和表示能力。
③ 数据格式化: 将文本序列转换为Token ID序列。需要添加特殊标记(如开始标记[CLS]
, 分隔标记[SEP]
, 结束标记[EOS]
, 填充标记[PAD]
, 未知标记[UNK]
等)。
④ 批处理与填充 (Batching and Padding): 将多个序列组成一个Batch,并使用填充标记[PAD]
将同一Batch内的序列填充到相同长度。需要生成注意力掩码(Attention Mask)来指示哪些是真实Token,哪些是填充Token,避免注意力机制关注到填充部分。
⑤ 位置编码 (Positional Encoding): 由于Transformer不具备顺序处理能力,需要计算并添加到Token嵌入中。
7.4.2 模型构建
按照Chapter 3介绍的结构,使用PyTorch或TensorFlow等框架从底层组件开始构建完整的Transformer模型。
⚝ 输入层: 词嵌入层(Token Embedding)和位置编码层(Positional Encoding)。
⚝ 编码器/解码器堆叠: 根据需要堆叠多个编码器层和/或解码器层。
⚝ 输出层: 对于语言建模,通常是一个线性层将Transformer输出的隐藏状态映射到词汇表大小的概率分布,然后接一个Softmax。
1
# 概念性代码结构 (PyTorch 示例)
2
# class TransformerModel(nn.Module):
3
# def __init__(self, vocab_size, d_model, nhead, num_encoder_layers,
4
# num_decoder_layers, dim_feedforward, dropout=0.1):
5
# super().__init__()
6
# self.embedding = nn.Embedding(vocab_size, d_model)
7
# self.positional_encoding = PositionalEncoding(d_model, dropout)
8
9
# encoder_layer = nn.TransformerEncoderLayer(d_model, nhead, dim_feedforward, dropout)
10
# self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_encoder_layers)
11
12
# # 如果是 Encoder-Decoder 模型
13
# # decoder_layer = nn.TransformerDecoderLayer(d_model, nhead, dim_feedforward, dropout)
14
# # self.transformer_decoder = nn.TransformerDecoder(decoder_layer, num_decoder_layers)
15
16
# self.fc_out = nn.Linear(d_model, vocab_size) # 输出层,映射到词汇表
17
18
# self._init_weights() # 初始化模型权重
19
20
# def _init_weights(self):
21
# # Transformer 论文通常建议使用 Glorot/Xavier 初始化
22
# for p in self.parameters():
23
# if p.dim() > 1:
24
# nn.init.xavier_uniform_(p)
25
26
# def forward(self, src, src_mask=None, src_key_padding_mask=None):
27
# # src shape: (seq_len, batch_size)
28
# src = self.embedding(src) * math.sqrt(self.d_model) # 嵌入并缩放
29
# src = self.positional_encoding(src)
30
# output = self.transformer_encoder(src, src_key_padding_mask=src_key_padding_mask)
31
32
# # 如果是 Encoder-Decoder 模型,还需要处理 tgt, tgt_mask, memory 等
33
# # output = self.transformer_decoder(tgt, memory, tgt_mask=tgt_mask, memory_mask=memory_mask, tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=memory_key_padding_mask)
34
35
# output = self.fc_out(output) # 形状: (seq_len, batch_size, vocab_size)
36
# return output
7.4.3 训练流程
从头训练需要一个完整的训练循环:
① 初始化模型与优化器: 随机初始化模型权重(使用合适的初始化方法如Xavier/Glorot),选择优化器(AdamW, Adam, SGD等)。
② 定义损失函数: 根据任务选择损失函数(如交叉熵损失)。
③ 学习率调度: 从头训练通常需要更复杂的学习率调度策略,例如先预热(Warm-up)到一个峰值,然后衰减(Decay)。这有助于训练的稳定性。
④ 训练循环: 迭代多个Epoch,在每个Batch上执行:
▮▮▮▮⚝ 前向传播:将输入数据送入模型得到预测结果。
▮▮▮▮⚝ 计算损失:根据预测结果和真实标签计算损失。
▮▮▮▮⚝ 反向传播:计算损失对模型参数的梯度。
▮▮▮▮⚝ 参数更新:使用优化器根据梯度更新模型参数。
▮▮▮▮⚝ (可选)梯度裁剪(Gradient Clipping):限制梯度的范数,防止梯度爆炸。
▮▮▮▮⚝ (可选)混合精度训练(Mixed Precision Training):使用FP16和FP32混合精度,可以加速训练并减少显存占用。
⑤ 评估: 定期在验证集上评估模型性能,保存最优模型检查点。
⑥ 分布式训练: 对于大规模模型和数据集,通常需要在多台机器、多个GPU上进行分布式训练(如使用PyTorch DDP, TensorFlow MirroredStrategy)。
7.4.4 挑战
从头训练Transformer模型面临的主要挑战:
⚝ 计算资源: 需要大量的计算资源(高性能GPU、分布式集群)和较长的训练时间。
⚝ 数据需求: 需要非常大的高质量数据集。
⚝ 超参数调优: 有大量的超参数(模型大小、层数、注意力头数、隐藏层维度、学习率、优化器参数、正则化参数等)需要仔细调优。
⚝ 训练稳定性: 大规模模型训练容易出现不稳定性,如梯度爆炸/消失、训练不收敛等,需要合适的初始化、归一化、学习率策略和正则化方法。
7.5 模型评估与分析 (Model Evaluation and Analysis)
训练完成后,我们需要对模型的性能进行量化评估,并尝试理解模型是如何工作的。
要点:常用评估指标、评估流程、模型行为分析。
7.5.1 常用评估指标
不同的任务类型有不同的标准评估指标:
⚝ 机器翻译 (Machine Translation):
▮▮▮▮⚝ BLEU (Bilingual Evaluation Understudy): 基于n-gram的精度,衡量机器翻译结果与参考译文的相似度。
▮▮▮▮⚝ ROUGE (Recall-Oriented Understudy for Gisting Evaluation): 主要用于文本摘要,基于n-gram的召回率。也可用于评估翻译。
▮▮▮▮⚝ METEOR (Metric for Evaluation of Translation With Explicit Ordering): 考虑了词形变化、同义词和词语顺序。
⚝ 文本分类 (Text Classification):
▮▮▮▮⚝ 准确率 (Accuracy): 正确分类样本数占总样本数的比例。
▮▮▮▮⚝ 精确率 (Precision), 召回率 (Recall), F1分数 (F1-Score): 特别适用于类别不平衡的数据集。
▮▮▮▮⚝ 宏平均 (Macro-average) / 微平均 (Micro-average): 处理多分类任务时,对指标进行平均的方式。
⚝ 序列标注 (Sequence Labeling - 如NER):
▮▮▮▮⚝ 通常使用基于实体的精确率、召回率和F1分数。
⚝ 问答 (Question Answering):
▮▮▮▮⚝ 精确匹配 (Exact Match, EM): 预测答案与参考答案完全一致的比例。
▮▮▮▮⚝ F1分数: 预测答案与参考答案之间的Token级别F1分数。
⚝ 文本生成 (Text Generation - 如语言模型):
▮▮▮▮⚝ 困惑度 (Perplexity): 衡量语言模型对样本序列分配概率的能力,越低越好。
▮▮▮▮⚝ 也可以使用BLEU、ROUGE等指标评估生成文本与参考文本的相似度。
⚝ 图像任务 (Image Tasks):
▮▮▮▮⚝ 图像分类: Top-1/Top-5 Accuracy。
▮▮▮▮⚝ 目标检测: Mean Average Precision (mAP)。
▮▮▮▮⚝ 图像分割: Mean Intersection over Union (mIoU)。
7.5.2 评估流程
① 划分数据集: 将数据划分为训练集(Training Set)、验证集(Validation Set)和测试集(Test Set)。训练集用于训练模型,验证集用于在训练过程中调整超参数和选择最优模型,测试集用于最终评估模型在新数据上的泛化能力。
② 加载最优模型: 使用验证集上性能最好的模型检查点进行评估。
③ 在测试集上进行推理: 将测试集的输入数据送入模型,获得预测结果。
④ 计算指标: 根据预测结果和测试集真实标签,使用相应的评估指标进行计算。
1
# Hugging Face Trainer 评估示例 (概念性)
2
# trainer.evaluate(processed_datasets["test"]) # Trainer 会自动在测试集上运行并计算 compute_metrics 定义的指标
8. 高级话题、理论分析与未来展望
本章将深入探讨注意力机制和Transformer模型的更深层次问题。在对它们的原理、结构和应用有了全面的理解之后,我们现在可以转向一些更具挑战性和前沿性的议题,包括模型成功的理论根源、如何尝试理解这些复杂“黑箱”的内部工作、它们当前面临的局限性,以及该领域的激动人心未来。本章旨在引发读者的思考,为那些希望进一步研究或应用这些技术的读者提供更广阔的视野。
8.1 注意力机制的理论解释
自注意力(Self-Attention)机制作为Transformer模型的核心,极大地提升了序列建模的能力。它允许模型在处理序列中的每一个元素时,都能考虑到序列中其他所有元素的信息,并根据相关性进行加权。那么,这种机制为何如此有效?它与人类的注意力过程又有何关联?
8.1.1 注意力机制为何如此有效?
注意力机制的有效性可以从多个角度进行解释:
① 捕捉长距离依赖(Long-Range Dependencies):
▮▮▮▮传统循环神经网络(RNN)通过隐藏状态(Hidden State) sequentially(顺序地)处理输入序列。这意味着信息需要一步一步地向前或向后传递,对于序列中相距较远的元素之间的依赖关系(即长距离依赖),信息可能会在传递过程中逐渐衰减,导致难以捕捉。
▮▮▮▮注意力机制,尤其是自注意力,通过一步到位的计算(Direct Calculation),直接计算序列中任意两个位置之间的关联度,克服了RNN的这个根本性问题。无论两个元素在序列中相距多远,它们之间的注意力权重计算只依赖于它们各自的向量表示,计算路径长度是常数(Constant),与序列长度无关。这使得模型能够有效地建模长距离依赖。
② 并行计算(Parallel Computation):
▮▮▮▮与RNN的序列性计算不同,注意力机制的计算是可以并行化的。在计算注意力权重时,每个 Query(查询)、Key(键)、Value(值)向量的点积以及后续的 softmax 和加权求和操作,可以同时对序列中的所有位置进行。
▮▮▮▮这种并行性使得Transformer模型能够充分利用现代硬件(如 GPU/TPU)的并行计算能力,从而可以在大规模数据集上训练更大、更深的模型。
③ 信息聚合与筛选(Information Aggregation and Filtering):
▮▮▮▮注意力机制本质上是一种带权重的平均。它允许模型从整个输入序列中“关注”到与当前处理位置最相关的部分,并将这些相关信息以加权的方式聚合起来。
▮▮▮▮这种机制相当于一个智能的信息筛选器,模型可以根据任务需求动态地调整对不同信息的关注程度,从而提取出最有用的信息进行后续处理。
④ 动态权重分配(Dynamic Weight Allocation):
▮▮▮▮传统的模型组件(如卷积核或固定权重的连接)的权重是静态的,一旦训练完成便固定下来。而注意力机制的权重是动态计算的,它取决于 Query 和 Key 向量的当前内容。
▮▮▮▮这意味着模型对输入的关注模式不是固定的,而是根据输入序列的内容实时变化的。这种动态性使得模型能够更好地适应输入数据的变化,提高了模型的灵活性和表达能力。
⑤ 多头机制(Multi-Head Mechanism):
▮▮▮▮多头注意力允许模型在不同的“表示子空间”(Representation Subspaces)中并行地学习多种不同的注意力模式。
▮▮▮▮这就像从多个不同的角度(不同的 Query/Key/Value 投影)去看待序列中的关系。不同的头(Head)可能关注到序列中不同的方面或不同类型的依赖关系,然后将这些信息综合起来,从而增强了模型的表示能力。
8.1.2 与人脑注意力的关联性
尽管神经网络模型是对生物神经系统的抽象和简化,但注意力机制在概念上与人类认知过程中的注意力具有一定的相似性。
⚝ 选择性关注(Selective Attention):人类在处理信息时,通常会选择性地关注那些与当前任务或目标最相关的信息,而忽略不相关的信息。这与注意力机制通过计算权重来突出重要信息、抑制不重要信息的行为相吻合。例如,当阅读一个句子时,我们会将注意力集中在当前词汇及其相关的上下文词汇上。
⚝ 动态调整焦点(Dynamic Focus Adjustment):人类的注意力焦点是可以动态调整的。当任务需求变化或环境中出现新的重要信息时,注意力会迅速转移。神经网络中的注意力权重也是动态计算的,依赖于当前的输入和上下文,允许模型灵活地调整其“关注点”。
⚝ 信息整合(Information Integration):人类的注意力不仅帮助我们选择信息,还能将分散的信息整合起来形成更全面的理解。自注意力机制通过加权求和的方式,将不同位置的信息整合到当前位置的表示中,实现了信息的有效整合。
然而,需要强调的是,这种关联性更多是概念层面的。深度学习模型中的注意力机制是一种数学计算过程,旨在提高模型在特定任务上的性能,它并不是对人脑注意力机制的精确生物学模拟。人脑的注意力是一个复杂的多尺度、多层级的认知过程,涉及神经回路、工作记忆等多种机制,远比当前的注意力模型复杂。将两者完全等同是不恰当的,但这种启发式的联系有助于我们理解为什么注意力机制在处理序列数据时表现出色。
8.2 Transformer模型的可解释性(Interpretability)
尽管Transformer模型取得了巨大的成功,但它仍然被认为是某种程度上的“黑箱”(Black Box)。理解模型内部是如何工作的,特别是它是如何基于输入做出特定决策的,对于模型的 Debugging(调试)、可靠性评估以及科学发现都至关重要。注意力权重提供了一种重要的视角来窥探Transformer的内部机制。
8.2.1 通过注意力权重理解模型
在Transformer模型中,自注意力层计算出的注意力权重矩阵直接反映了模型在处理一个 token(词元)时,对序列中其他 token 的关注程度。这些注意力权重可以被可视化,从而提供对模型行为的一种解释:
① 词汇之间的关联(Word-Word Relationships):
▮▮▮▮通过可视化注意力权重矩阵,我们可以看到模型在处理句子中的某个词时,哪些词对它施加了最多的“注意力”。
▮▮▮▮这可以揭示模型捕捉到的语法关系(如动词与其主语或宾语的关联)、语义关系(如同义词或相关概念的关联)、以及长距离依赖关系。
▮▮▮▮示例:在一个机器翻译模型中,当我们处理目标语言中的某个词时,其注意力可能集中在源语言句子中对应的词汇上,这直观地展示了模型的对齐(Alignment)能力。在一个问答系统中,模型在处理问题中的关键词时,其注意力可能集中在文档中包含答案信息的句子上。
② 结构信息(Structural Information):
▮▮▮▮一些研究表明,不同的注意力头(Head)会学习到捕捉不同类型的结构信息。有些头可能侧重于局部的依赖关系(类似卷积),有些可能捕捉句法结构(如主语-谓语,修饰语-被修饰语),还有些可能关注全局的上下文信息。
▮▮▮▮通过分析不同头的注意力模式,我们可以推断出模型学习到了哪些类型的语言或数据结构特征。
③ 多头注意力的作用(Role of Multi-Head Attention):
▮▮▮▮分析多头注意力可以发现,不同的头确实会学习到不同的注意力模式。例如,在一个头中,一个代词可能主要关注其指代的对象;而在另一个头中,同一个词可能关注与其在句法上相邻的词。
▮▮▮▮多头机制的强大之处在于它能够同时捕捉到输入序列中多种复杂的关系。
8.2.2 可解释性的挑战与局限
尽管注意力权重提供了一些洞察,但解释Transformer模型的挑战仍然巨大:
⚝ 多层堆叠的复杂性(Complexity of Multiple Layers):Transformer模型通常由多个编码器和解码器层堆叠而成。每一层都对输入表示进行转换,并且层与层之间存在复杂的交互。简单地查看最后一层的注意力权重可能不足以理解整个模型的工作流程,中间层的注意力模式也可能非常重要且难以解读。
⚝ 多头注意力的集成(Integration of Multi-Head Attention):每个层有多个注意力头,每个头有不同的权重模式。如何将这些不同头的注意力信息综合起来,形成一个统一、清晰的解释是一个挑战。不同头的贡献可能不同,甚至可能相互冲突。
⚝ 注意力不是全部(Attention is Not Everything):Transformer模型不仅仅包含注意力层。它还包括前馈网络、残差连接、层归一化等组件。这些组件共同作用于模型的输出。仅仅分析注意力权重而忽略其他组件的作用,可能会导致片面的解释。
⚝ 注意力权重的意义(Meaning of Attention Weights):注意力权重表示的是信息聚合时的权重,它可以被解读为“关注度”或“重要性”。但它是否等同于“原因”或“推理过程”,仍有争议。高注意力权重可能表示相关性,但不一定直接解释模型做出特定预测的因果链条。
⚝ 非线性变换(Non-linear Transformations):模型中的非线性激活函数和矩阵乘法使得信息在层间传递时发生复杂变换,这进一步增加了追踪信息流和理解决策路径的难度。
8.2.3 其他可解释性方法
除了分析注意力权重,研究者们还在探索其他方法来提高Transformer等深度模型的interpretability(可解释性):
⚝ 梯度方法(Gradient-based Methods):通过计算输出相对于输入的梯度,可以识别对输出影响最大的输入部分(如 Saliency Maps,显著性图)。
⚝ 探针任务(Probing Tasks):训练简单的分类器或回归器来预测模型内部表示(如特定层的输出)中包含的语言学或概念信息,以此了解模型学到了什么。
⚝ 原型学习(Prototype Learning):尝试找到输入空间的代表性样本(原型),这些原型在模型的决策过程中起着关键作用。
⚝ 因果干预(Causal Intervention):通过修改模型内部的某些部分(如注意力权重或特定神经元的激活),观察对输出的影响,从而推断这些部分的功能。
⚝ 模块化分析(Modularity Analysis):研究模型是否在内部形成了功能独立的模块,每个模块负责处理特定的任务或特征。
尽管面临挑战,提高Transformer的可解释性仍然是当前研究的重要方向,它有助于我们建立对这些强大模型的信任,并在安全、公平、可靠的应用中发挥作用。
8.3 Transformer的局限性与挑战
尽管Transformer模型及其变体在众多任务上取得了前所未有的成功,但它们并非完美无缺,仍然存在一些固有的局限性和挑战。
8.3.1 长序列处理的计算效率与内存消耗
① 计算复杂度(Computational Complexity):
▮▮▮▮标准的自注意力机制需要计算 Query 与 Key 之间的点积矩阵,其大小为 \( L \times L \),其中 \( L \) 是序列长度。这导致计算时间和内存消耗与序列长度的平方(\( O(L^2) \))成正比。
▮▮▮▮当序列长度非常大时(例如,长文档处理、高分辨率图像、长音频序列),平方级的增长会迅速导致计算成本过高和内存溢出,使得标准 Transformer 难以处理超长序列。
② 内存消耗(Memory Consumption):
▮▮▮▮除了计算注意力权重矩阵本身需要 \( O(L^2) \) 的内存外,存储 Query, Key, Value 矩阵以及反向传播所需的中间变量也需要大量内存。
▮▮▮▮这限制了模型能够处理的最大序列长度,尤其是在显存有限的设备上。
8.3.2 位置信息的处理
尽管位置编码(Positional Encoding)为模型提供了位置信息,但其表达方式(如正弦/余弦函数或可学习嵌入)与 RNN/CNN 基于结构的位置处理方式不同。对于某些对精确位置或相对位置非常敏感的任务,Transformer对位置信息的处理能力可能不如专门设计的结构。对于非常长的序列,位置编码的有效性也可能受到挑战。
8.3.3 缺乏归纳偏置(Lack of Inductive Bias)
① 局部性(Locality):
▮▮▮▮与 CNN 的卷积核强制学习局部特征不同,标准自注意力对序列中所有位置一视同仁,没有内置的局部性偏置。虽然注意力权重可能学到关注局部信息,但这并非结构强制的。
▮▮▮▮对于图像等具有强局部相关性的数据,缺乏局部归纳偏置可能意味着模型需要更多的数据或参数来学习有效的局部特征提取。
② 顺序性(Sequentiality):
▮▮▮▮与 RNN 的顺序处理方式不同,Transformer 是并行处理的,通过位置编码感知位置信息。虽然这带来了并行计算的优势,但也意味着模型不像 RNN 那样自然地编码序列的严格顺序或时序信息。
8.3.4 记忆与泛化能力
① 外部知识的集成(Integration of External Knowledge):
▮▮▮▮标准的 Transformer 模型主要通过大规模数据预训练来获取知识,这些知识存储在模型的参数中。然而,对于需要访问和推理海量外部知识(如知识图谱、数据库)的任务,Transformer模型的参数容量有限,难以存储所有这些信息,且难以进行实时的、符号式的知识检索和推理。
② 泛化到未知或分布外数据(Generalization to Unseen/Out-of-Distribution Data):
▮▮▮▮像所有数据驱动的模型一样,Transformer在面对与训练数据分布差异较大的数据时,其泛化能力可能受到影响。其强大的记忆能力可能导致对训练数据的过度拟合(Overfitting)。
8.3.5 推理与规划能力
尽管大型语言模型(Large Language Models, LLMs)展示了惊人的文本生成和一些初步的推理能力,但它们在需要复杂多步推理、逻辑规划或准确数学计算的任务上仍有局限。它们的输出有时可能包含事实性错误(Hallucinations)或不连贯的逻辑。这可能与Transformer主要是一个模式匹配器而非符号推理引擎的本质有关。
8.3.6 计算成本与能耗
训练和部署大型 Transformer 模型需要巨大的计算资源和能源消耗,这带来了经济和环境方面的挑战。
8.3.7 可解释性与可信度
如前所述,Transformer模型的复杂性使得其内部工作机制难以完全理解,这影响了模型在对可信度要求高的领域的应用,例如医疗诊断、法律判决等。
这些局限性正是当前研究努力的方向,许多 Transformer 变体和新的架构(如高效 Transformer、结合检索的模型、符号神经模型等)的出现正是为了解决这些问题。
8.4 与符号主义AI的结合
深度学习(以连接主义为代表)和符号主义人工智能(Symbolic AI)是AI领域的两个主要范式。深度学习擅长从大数据中学习模式、处理感知任务(如图像识别、语音识别)和生成复杂序列(如文本生成),但其推理过程通常是隐式的、难以解释的,且在处理需要精确逻辑和结构化知识的任务时面临挑战。符号主义AI则侧重于使用符号表示(如逻辑规则、知识图谱)和推理算法来模拟人类的逻辑思维过程,擅长处理知识表示、推理、规划等任务,但其获取和处理大规模、非结构化感知数据的能力较弱。
将 Transformer 模型强大的模式学习能力与符号主义AI的逻辑推理和知识表示能力相结合,被认为是构建更通用、更智能AI系统的一个有前景的方向。
8.4.1 结合的需求与优势
⚝ 弥补Transformer的不足:符号推理可以帮助 Transformer 模型克服在复杂推理、规划、以及访问和利用结构化知识方面的局限。例如,对于需要多步逻辑推导或利用背景知识来回答的问题,结合符号推理可能比纯粹依赖 Transformer 的模式匹配更可靠和准确。
⚝ 增强可解释性:符号主义AI的推理过程通常是显式的和可解释的。将 Transformer 的输出(如提取的关键信息)馈送给符号推理系统,或使用符号结构来指导 Transformer 的学习,可能有助于提高整个系统的可解释性。
⚝ 处理结构化数据:符号主义AI天然适合处理结构化数据(如数据库、知识图谱)。结合可以使 Transformer 模型更好地利用这些结构化信息。
⚝ 改进规划与决策:符号推理和规划算法可以为 Transformer 模型提供更强的决策能力,特别是在需要考虑一系列动作及其后果的复杂环境中。
8.4.2 结合的策略与方法
研究者们探索了多种策略将深度学习与符号主义AI相结合,其中一些可以应用于 Transformer 模型:
① 神经符号模型(Neuro-Symbolic Models):
▮▮▮▮端到端模型:构建一个单一的、可端到端训练的模型,其中包含神经网络模块(如 Transformer 用于处理感知输入和提取特征)和符号推理模块(用于执行逻辑推理)。两者之间设计接口进行信息交换。例如,神经网络输出可以被解析为逻辑事实或查询,输入给符号推理引擎;推理结果也可以反馈给神经网络。
▮▮▮▮模块化系统:构建一个由独立模块组成的系统,其中 Transformer 作为一个或多个模块(如自然语言理解模块、图像理解模块),其输出作为输入传递给符号推理系统,或者符号推理系统的输出指导 Transformer 的行为。
② 结构化注意力(Structured Attention):
▮▮▮▮修改 Transformer 的注意力机制,使其不仅仅关注 token 之间的表面相关性,而是能够感知和利用输入数据的内在结构(如句法树、图结构)。例如,通过在计算注意力时引入结构偏置或使用图神经网络(Graph Neural Networks, GNNs)来处理结构信息。
③ 知识注入(Knowledge Injection):
▮▮▮▮将外部知识库(如知识图谱)中的信息以嵌入(Embedding)或符号表示的形式注入到 Transformer 模型中,从而增强模型对知识的理解和利用能力。这可以通过额外的注意力机制来查询知识图谱,或将知识表示与 token 嵌入融合。
④ 可微逻辑与规划(Differentiable Logic and Planning):
▮▮▮▮研究如何将逻辑推理和规划过程以可微的方式实现,使得这些过程可以融入到基于梯度的端到端训练框架中,与 Transformer 等神经网络协同优化。
8.4.3 面临的挑战
结合神经与符号范式并非易事:
⚝ 表示鸿沟(Representation Gap):神经网络使用连续的向量表示,而符号主义使用离散的符号表示。如何有效地在两种表示之间转换和交互是一个核心挑战。
⚝ 系统复杂性(System Complexity):结合系统往往比单一范式系统更复杂,设计、实现和调试都更困难。
⚝ 端到端训练的难度:如何实现神经模块和符号模块之间的端到端、联合优化是一个技术难题,尤其是当符号推理过程不可微时。
⚝ 如何平衡学习与推理:如何在从数据中学习模式(神经网络擅长)和执行精确推理(符号主义擅长)之间找到平衡,避免学习过程破坏推理的准确性或推理过程限制学习的灵活性。
尽管存在挑战,神经符号AI是当前AI研究的热点之一,有望克服纯粹数据驱动模型的某些根本性局限,构建出更健壮、透明且具有更强泛化和推理能力的智能系统。将 Transformer 这一强大的神经网络架构融入其中,无疑将是未来研究的重要方向。
8.5 未来研究方向
注意力机制和Transformer模型已经深刻地改变了人工智能领域,但研究仍在不断深入。未来的研究将继续在多个方向上探索,以解决现有模型的局限性,拓展其能力边界,并应对实际应用中的挑战。
⚝ 更高效的Transformer架构(More Efficient Transformer Architectures):
▮▮▮▮解决 \( O(L^2) \) 计算复杂度是当前最紧迫的问题之一。未来的研究将继续探索各种高效注意力机制,例如基于稀疏注意力(Sparse Attention)、核方法(Kernel Methods)、线性注意力(Linear Attention)、或者分块处理(Block-wise Processing)的方法,以降低计算量和内存消耗,使得模型能够处理更长的序列。
▮▮▮▮研究更紧凑的模型结构、参数共享机制以及硬件友好的计算模式,以提高训练和推理效率,降低部署成本。
⚝ 更强的泛化能力与鲁棒性(Stronger Generalization and Robustness):
▮▮▮▮提高模型在小样本(Few-Shot)/零样本(Zero-Shot)场景下的泛化能力,减少对大规模标注数据的依赖。
▮▮▮▮增强模型对对抗样本(Adversarial Examples)、噪声和分布外(Out-of-Distribution, OOD)数据的鲁棒性。
▮▮▮▮探索元学习(Meta-Learning)和领域适应(Domain Adaptation)技术与 Transformer 的结合。
⚝ 多模态融合与跨模态理解的深入(Deeper Multimodal Fusion and Cross-modal Understanding):
▮▮▮▮当前多模态模型(如 CLIP, DALL-E, Flamingo)已取得显著进展,未来将继续探索更深层次的多模态信息融合机制,使得模型能够更好地理解和推理不同模态数据之间的复杂关系,实现更自然的跨模态交互和生成。
▮▮▮▮将 Transformer 应用于更多模态(如时间序列、图数据、传感器数据等)以及模态之间的任意组合。
⚝ 更强的推理与规划能力(Enhanced Reasoning and Planning):
▮▮▮▮继续探索神经符号AI方法,或开发新的神经网络结构和训练方法,以赋予模型更强大的符号推理、逻辑推导和规划能力,克服当前模型在这些方面的不足。
▮▮▮▮研究如何让模型能够访问、整合和利用外部知识库进行推理。
⚝ 模型的理解与可解释性(Model Understanding and Interpretability):
▮▮▮▮开发更先进的工具和理论框架来分析和理解 Transformer 模型的内部工作机制,特别是其注意力模式和各层的功能。
▮▮▮▮提高模型决策的透明度和可解释性,特别是在高风险应用领域。
⚝ 负责任的AI(Responsible AI):
▮▮▮▮研究如何减轻大型 Transformer 模型可能带来的偏见(Bias)、歧视和不公平性问题。
▮▮▮▮探索模型的安全性和可靠性,防止恶意使用。
▮▮▮▮解决隐私保护问题,例如如何在不暴露敏感训练数据的情况下共享和使用大型预训练模型。
⚝ 持续学习与适应(Continual Learning and Adaptation):
▮▮▮▮开发能够持续学习新知识、适应新任务和环境的 Transformer 模型,而不会遗忘旧的知识(灾难性遗忘,Catastrophic Forgetting)。
⚝ 更先进的自监督与自训练方法(More Advanced Self-supervised and Self-training Methods):
▮▮▮▮探索新的预训练任务和自监督信号,使得模型能够从海量无标注数据中学习更丰富、更通用的表示。
▮▮▮▮利用自训练技术,结合少量标注数据和大量无标注数据,进一步提升模型性能。
⚝ 与硬件的协同优化(Co-design with Hardware):
▮▮▮▮未来的 Transformer 研究将越来越关注与专用硬件加速器(如 ASIC, FPGA)的协同设计,以实现更高的计算效率和更低的能耗。
总之,注意力机制和Transformer模型为构建下一代人工智能系统奠定了坚实的基础。未来的研究将围绕效率、能力、可靠性和责任这几个核心维度展开,不断推动AI技术的进步,解决更复杂、更具挑战性的实际问题。对于读者而言,紧密关注这些前沿方向,并在自己的实践中不断探索和创新,将是在这个快速发展的领域保持竞争力的关键。
9. 结论
本书旨在系统而深入地解析注意力机制(Attention Mechanism)和Transformer模型,从它们提出的背景、核心原理到广泛的应用和未来的发展。注意力机制的出现为序列建模带来了新的曙光,而Transformer模型凭借其独特的架构和强大的并行计算能力,彻底改变了深度学习领域,尤其是在自然语言处理(NLP)中取得了里程碑式的成就,并迅速扩展到计算机视觉(Computer Vision)、语音处理(Speech Processing)、生物信息学(Bioinformatics)等众多领域,成为现代人工智能(Artificial Intelligence, AI)最重要的基石之一。
本章将对全书内容进行总结,回顾核心知识点,探讨在“Transformer时代”所面临的机遇与挑战,并为读者未来的学习和实践提供一些建议,希望能帮助读者更好地理解和把握这一关键技术,在各自的领域中取得成功。
9.1 本书核心知识点回顾
在过去的章节中,我们循序渐进地探讨了注意力机制和Transformer模型的方方面面。回首这些内容,我们主要掌握了以下核心知识点:
① 人工智能模型的演进与挑战: 我们回顾了传统神经网络(Neural Networks)、循环神经网络(Recurrent Neural Networks, RNN)和卷积神经网络(Convolutional Neural Networks, CNN)在处理序列数据时的局限性,特别是RNN/LSTM在处理长距离依赖(Long-Range Dependencies)时的瓶颈以及难以并行化的问题。
② 注意力机制的核心原理: 我们深入理解了注意力机制的基本思想——从大量信息中选择性地关注与当前任务最相关的信息,并学习了其数学表达和不同类型,包括:
▮▮▮▮ⓑ 加性注意力 (Additive Attention):通过一个前馈网络计算注意力权重。
▮▮▮▮ⓒ 点积注意力 (Dot-Product Attention):通过查询(Query, Q)和键(Key, K)的点积计算相似度。
▮▮▮▮ⓓ 缩放点积注意力 (Scaled Dot-Product Attention):在点积注意力基础上引入缩放因子 \( 1/\sqrt{d_k} \) 来稳定梯度。
▮▮▮▮特别是自注意力机制 (Self-Attention),它允许模型计算序列内部任意两个位置之间的关联度,极大地增强了模型捕捉长距离依赖的能力。
③ Transformer模型的精妙架构: 我们详细剖析了Transformer模型的完整结构,其核心在于完全摒弃了循环和卷积,仅依赖于注意力机制,这使得模型可以高度并行化训练。我们了解了其主要组成部分:
▮▮▮▮ⓑ 编码器 (Encoder):负责将输入序列映射到连续的表示空间,由多层相同的子层堆叠而成。
▮▮▮▮ⓒ 解码器 (Decoder):负责根据编码器输出和已生成的目标序列生成下一个词汇,同样由多层相同的子层堆叠而成。
▮▮▮▮ⓓ 输入嵌入与位置编码 (Input Embedding and Positional Encoding):将离散词汇转换为连续向量表示,并引入序列中词汇的位置信息。
▮▮▮▮ⓔ 多头自注意力 (Multi-Head Self-Attention):通过并行运行多个注意力头,从不同角度关注信息,增强模型的表达能力。
▮▮▮▮ⓕ 带掩码的多头自注意力 (Masked Multi-Head Self-Attention):在解码器中应用,确保生成当前词时不会“看到”未来的信息。
▮▮▮▮⚝ 编码器-解码器注意力 (Encoder-Decoder Attention):在解码器中应用,允许解码器关注编码器的输出。
▮▮▮▮⚝ 前馈神经网络 (Feed-Forward Network):为模型引入非线性变换能力。
▮▮▮▮⚝ 残差连接与层归一化 (Residual Connection and Layer Normalization): Add & Norm 子层,用于帮助训练更深的网络,缓解梯度消失/爆炸问题。
④ Transformer模型的训练与优化: 我们学习了训练Transformer模型的一些关键实践,包括损失函数的选择(如交叉熵)、优化器(如 Adam)、重要的学习率调度策略(如 Warm-up)以及正则化技术(如 Dropout)。此外,我们也了解了推理阶段的生成策略(如 Beam Search)。
⑤ 丰富的Transformer模型家族: 我们探索了基于Transformer架构衍生出的各种强大的预训练语言模型(Pre-trained Language Models, PLMs),它们极大地推动了NLP及相关领域的发展:
▮▮▮▮ⓑ 仅编码器模型 (Encoder-only Models):以BERT为代表,适用于理解型任务(如文本分类、命名实体识别)。
▮▮▮▮ⓒ 仅解码器模型 (Decoder-only Models):以GPT系列为代表,适用于生成型任务(如文本生成、对话)。
▮▮▮▮ⓓ 编码器-解码器模型 (Encoder-Decoder Models):以T5、BART为代表,适用于序列到序列任务(如机器翻译、文本摘要)。
▮▮▮▮ⓔ 高效Transformer (Efficient Transformers):针对计算效率和长序列处理进行的改进模型。
⑥ 跨领域的广泛应用: 我们看到Transformer强大的通用性,它不仅在NLP的各种任务中取得了最佳性能(State-of-the-Art, SOTA),还成功迁移并革新了其他领域,如计算机视觉(Vision Transformer, ViT)、语音处理、生物信息学(如 AlphaFold)以及跨模态学习(Cross-modal Learning),成为了构建通用人工智能模型的重要基石。
⑦ 实践工具与技巧: 我们介绍了如何在主流深度学习框架(TensorFlow, PyTorch)中实现Transformer模型,重点学习了如何利用 Hugging Face Transformers 库这一强大的工具,以及如何加载、使用和微调预训练模型,以及从零开始训练模型和模型部署优化的一些基本考虑。
通过对这些知识点的学习,我们应该对注意力机制和Transformer模型有了全面而深入的理解,并具备了在实践中应用这些技术的基础。
9.2 Transformer时代的机遇与挑战
我们正处于一个由Transformer技术深刻影响的时代。掌握这一技术,无疑带来了巨大的机遇,但也伴随着不容忽视的挑战。
机遇 (Opportunities) ✨:
① 性能突破与新应用: Transformer模型及其衍生的预训练大模型(Large Language Models, LLMs)在众多任务上显著提升了性能上限,使得过去难以实现的应用成为可能,例如高质量的机器翻译、流畅自然的文本生成、强大的代码助手、复杂的逻辑推理辅助等等。
② 降低下游任务门槛: 预训练模型的出现使得在特定任务上不再需要从零开始训练巨大的模型,只需在少量任务数据上进行微调(Fine-tuning),极大地降低了AI应用的开发成本和数据需求,加速了技术的普及。
③ 推动跨领域与多模态研究: Transformer的序列处理通用性使其能够轻松地处理图像、语音、视频等不同模态的数据,只要能将它们转换为序列表示。这极大地促进了跨模态学习和通用AI模型的研究,打破了过去领域间的壁垒。
④ 新的产业生态: 围绕大型预训练模型,正在形成一个全新的技术和产业生态,包括模型提供商、模型API服务、垂直领域模型定制、模型部署优化等,为技术人员和企业提供了广阔的发展空间。
挑战 (Challenges) 🚧:
① 巨大的计算资源消耗: Transformer模型特别是大型预训练模型的训练需要天文数字般的计算资源(GPU/TPU集群、电力),这限制了个人和小型机构从零开始训练大规模模型的能力。
② 数据饥渴: 尽管预训练阶段利用了海量数据,但在某些特定领域的微调仍然需要高质量的标注数据,数据的获取和处理成本依然存在。
③ 可解释性与可靠性: Transformer模型内部复杂,其决策过程往往是“黑箱”,难以解释。同时,大模型可能产生幻觉(Hallucinations)、偏见(Bias)甚至错误信息,其可靠性和安全性是实际应用中的重要问题。
④ 长序列处理限制: 标准的自注意力机制在处理超长序列(超过几千甚至几万个tokens)时,计算和内存复杂度呈平方增长,这限制了其在需要理解全文或长文档的场景下的直接应用。高效Transformer变体正在尝试缓解这一问题。
⑤ 推理与部署成本: 即使是推理阶段,大型Transformer模型也需要显著的计算资源,如何高效地部署到资源受限的环境(如边缘设备)仍然是一个挑战。
⑥ 伦理与社会影响: 大模型带来的强大生成能力可能被用于生成虚假信息、深度伪造(Deepfakes)等,其广泛应用也可能对就业结构、社会认知等产生深远影响,需要我们审慎对待和负责任地发展与使用。
9.3 持续学习与探索的建议
注意力机制和Transformer领域是一个充满活力且快速发展的领域。本书为你构建了坚实的理论和实践基础,但这仅仅是开始。为了在这个领域持续进步并做出贡献,我们建议你:
① 保持好奇心,追踪前沿: 关注顶级的学术会议(如 NeurIPS, ICML, ICLR, ACL, EMNLP, CVPR等)和预印本网站(如 arXiv)上的最新研究论文。很多重要的思想和模型变体都在这里首次出现。
② 深入理解核心原理: 不要仅仅停留在模型的使用层面。尝试深入理解模型背后的数学原理、计算流程和设计哲学。只有理解了“为什么”,才能更好地进行模型的改进、调优和应用。
③ 动手实践,以练促学: 代码是理解模型的最佳方式之一。利用 Hugging Face Transformers 等库,动手加载不同的预训练模型,尝试在不同的下游任务上进行微调。甚至可以尝试实现Transformer的某个关键模块,加深理解。
④ 参与开源社区: 许多重要的Transformer模型和工具都是开源的。参与到开源社区中,可以学习到工业级的代码实现、了解实际应用中的挑战,甚至有机会贡献自己的力量。
⑤ 结合具体问题进行探索: 将Transformer技术应用于你感兴趣或你所在领域的实际问题。通过解决具体问题,你会更深刻地体会到模型的优势与局限性,并可能发现新的研究方向或应用机会。
⑥ 关注高效与负责任的AI: 随着模型规模越来越大,如何提高模型的计算效率(量化、剪枝、新的架构设计等)以及如何构建更负责任(公平、可信、安全)的AI系统将变得越来越重要。
⑦ 构建系统性知识: 注意力机制和Transformer是深度学习体系中的重要组成部分。建议结合对深度学习基础、其他模型(CNN, RNN)、优化方法、数据集处理等知识的学习,形成更全面的理解。
Transformer模型无疑是当前AI浪潮的核心驱动力之一。掌握这一技术,意味着你站在了人工智能发展的前沿。希望本书能为你打开这扇大门,引领你踏上持续学习和探索的旅程。祝你在注意力机制和Transformer的广阔世界中取得丰硕的成果!🚀
Appendix A: 术语表 (Glossary)
Appendix A.1: 核心术语解释 (Explanation of Core Terms)
⚝ 注意力机制 (Attention Mechanism): 一种模仿人类认知系统选择性关注重要信息的技术。在神经网络中,它允许模型在处理序列数据时,对输入序列的不同部分赋予不同的权重,从而更好地捕捉依赖关系。
⚝ BERT (Bidirectional Encoder Representations from Transformers): 一种基于 Transformer 编码器的预训练语言模型。其核心特点是采用双向的 Masked Language Model (掩码语言模型) 和 Next Sentence Prediction (下一句预测) 任务进行预训练,使其能理解文本的双向上下文。
⚝ Beam Search (集束搜索): 在序列生成任务(如机器翻译、文本摘要)中,一种非贪婪的搜索策略。它在每一步保留 \(k\) 个概率最高的候选序列(\(k\) 为集束宽度),而不是只保留当前最有可能的一个,以提高找到全局最优序列的概率。
⚝ CNN (Convolutional Neural Network): 卷积神经网络。一种主要用于处理具有网格状拓扑结构数据(如图像、音频波形)的神经网络,通过卷积层、池化层等提取特征。
⚝ 计算机视觉 (Computer Vision): 人工智能领域的一个分支,旨在使计算机能够“看到”并理解图像和视频的内容。Transformer 模型已被广泛应用于该领域。
⚝ 交叉熵损失 (Cross-Entropy Loss): 在分类或概率预测任务中常用的损失函数,衡量模型预测的概率分布与真实标签的概率分布之间的差异。对于序列生成,通常计算每个时间步预测词汇的交叉熵之和。
\[ H(p, q) = - \sum_{i} p(x_i) \log q(x_i) \]
其中 \(p\) 是真实分布,\(q\) 是模型预测分布。
⚝ Query (查询), Key (键), Value (值): 注意力机制中的三个核心概念。Query 代表当前要计算注意力的元素,用它去“查询”序列中其他元素的 Key。Query 和 Key 的匹配度(通常通过点积计算)决定了 Value 的权重,加权平均的 Value 构成了注意力机制的输出。
⚝ 解码器 (Decoder): 在 Encoder-Decoder 架构中,负责根据编码器输出的上下文信息和已生成的部分序列,逐个生成目标序列元素的模块。Transformer 解码器通常包含 Masked Self-Attention 和 Encoder-Decoder Attention 层。
⚝ DETR: Detection Transformer 的缩写。第一个成功地将 Transformer 模型应用于目标检测任务的模型,将目标检测视为一个集合预测问题。
⚝ 点积注意力 (Dot-Product Attention): 一种简单的注意力计算方式,通过 Query 向量和 Key 向量的点积来衡量它们之间的相似度或相关性,从而得到注意力权重。
\[ \text{Score}(Q, K_i) = Q \cdot K_i \]
⚝ DropConnect: 一种正则化技术,在全连接层中随机将连接权重设置为零,而不是像 Dropout 那样随机将神经元输出设置为零。
⚝ Dropout: 一种常用的正则化技术,在训练过程中随机地“关闭”(即输出设置为零)一部分神经元,以减少模型的过拟合。
⚝ Encoder-Decoder Attention (编码器-解码器注意力): 在 Transformer 解码器中,一种允许解码器在生成当前输出时,通过注意力机制关注编码器最终输出(Key 和 Value)的机制。这里的 Query 来自解码器自身的输出。
⚝ 编码器 (Encoder): 在 Encoder-Decoder 架构中,负责将输入序列转换为一个包含其语义信息的上下文表示的模块。Transformer 编码器由多个相同的层堆叠而成,每层包含 Multi-Head Self-Attention 和前馈网络。
⚝ 前馈神经网络 (Feed-Forward Network): 在 Transformer 编码器和解码器中,位于注意力层之后的一个全连接前馈网络。它独立地应用于序列中的每一个位置 (position),增加模型的表达能力。
⚝ 微调 (Fine-tuning): 使用在一个大规模数据集上预训练好的模型,在一个较小、特定任务的数据集上继续训练,以适应新任务的过程。通常只需调整模型的顶层或所有层的参数。
⚝ GPT (Generative Pre-trained Transformer): 一系列基于 Transformer 解码器的预训练语言模型。它们采用自回归 (Autoregressive) 的方式进行预训练(预测序列中的下一个词),擅长文本生成任务。
⚝ Greedy Decoding (贪婪解码): 在序列生成任务中,一种简单的搜索策略。在每一步,模型只选择当前概率最高的词作为输出,直到生成结束标记。这种方法计算效率高,但不保证得到最优的序列。
⚝ Hugging Face Transformers库: 一个广泛使用的开源库,提供了大量预训练的 Transformer 模型及其相关的工具,极大地简化了 Transformer 模型的使用、微调和部署。
⚝ 输入嵌入 (Input Embedding): 将离散的输入单元(如词汇、字符)转换为连续的向量表示的过程。这些向量捕捉了输入单元的语义信息。在 Transformer 中,通常与位置编码相加作为模型输入。
⚝ 可解释性 (Interpretability): 关于模型如何做出决策或预测的理解程度。对于 Transformer 模型,分析注意力权重通常是研究其可解释性的一种手段。
⚝ Key (键): 参见 Query (查询), Key (键), Value (值)。
⚝ 层归一化 (Layer Normalization): 一种归一化技术,对同一层神经网络中单个样本的所有神经元的激活值进行归一化,使其均值为0、方差为1。在 Transformer 中常用于残差连接之后,有助于稳定训练。
⚝ 学习率调度 (Learning Rate Scheduling): 在模型训练过程中,根据预设的策略动态调整学习率的过程。常见的策略包括步长衰减、指数衰减、余弦退火以及 Transformer 论文中使用的预热 (Warm-up) 后衰减。
⚝ 长距离依赖 (Long-Range Dependencies): 序列中相距较远的元素之间的依赖关系。传统序列模型(如标准 RNN)在捕捉长距离依赖方面存在困难,而注意力机制和 Transformer 能更好地处理这一问题。
⚝ LSTM (Long Short-Term Memory): 长短期记忆网络。一种特殊的循环神经网络 (RNN),通过引入门控机制(输入门、遗忘门、输出门)来缓解 RNN 在处理长序列时遇到的梯度消失或爆炸问题,能更好地捕捉长距离依赖。
⚝ 掩码 (Masking): 在 Transformer 模型中,一种用来屏蔽某些信息的技术。例如,在解码器的自注意力层中,使用掩码阻止模型看到当前时间步之后的信息(未来信息),确保生成过程的顺序性;在 Masked Language Model 任务中,掩码用来隐藏输入序列中的部分词汇。
⚝ 多头注意力 (Multi-Head Attention): 注意力机制的一种扩展。通过并行地运行多个注意力“头”,每个头独立学习 Query、Key、Value 的线性变换,并计算注意力。然后将多个头的输出拼接并再次线性变换,以整合来自不同表示空间的信息,增强模型的表达能力。
⚝ 自然语言处理 (Natural Language Processing, NLP): 人工智能领域的一个分支,研究如何使计算机能够理解、解释、生成和操作人类语言。注意力机制和 Transformer 模型在 NLP 领域取得了巨大成功。
⚝ 优化器 (Optimizer): 在模型训练中,用于更新模型参数以最小化损失函数的算法。常见的优化器包括 SGD、Adam、Adagrad 等。Adam 优化器在 Transformer 模型训练中被广泛使用。
⚝ 位置编码 (Positional Encoding): 在 Transformer 模型中,由于自注意力机制不包含序列的顺序信息,需要引入位置编码将序列中元素的位置信息注入到输入嵌入中。常用的位置编码是基于正弦和余弦函数的周期信号。
⚝ 预训练模型 (Pre-trained Model): 在一个大规模数据集(通常是无监督或自监督任务)上预先训练好的模型。这些模型学习到了通用的语言表示或视觉表示,可以作为基础模型用于各种下游任务,通常只需要进行微调。
⚝ Query (查询): 参见 Query (查询), Key (键), Value (值)。
⚝ 残差连接 (Residual Connection): 一种常用的神经网络结构。它将某一层的输入直接加到该层的输出上。在深层网络中,残差连接有助于缓解梯度消失问题,使得训练更深的模型成为可能。在 Transformer 中,每个子层(自注意力、前馈网络)的输出都通过残差连接与输入相加。
⚝ RNN (Recurrent Neural Network): 循环神经网络。一种擅长处理序列数据的神经网络,通过隐藏状态在时间步之间传递信息,理论上可以处理任意长度的序列,但在处理长序列时存在梯度消失/爆炸、计算并行性差等问题。
⚝ 缩放点积注意力 (Scaled Dot-Product Attention): Transformer 模型中使用的注意力形式。它是点积注意力的一种改进,在计算点积后除以 Query 和 Key 向量维度的平方根 \( \sqrt{d_k} \)。这样做是为了防止点积结果过大,导致 Softmax 函数的梯度过小,从而稳定训练。
\[ \text{Attention}(Q, K, V) = \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V \]
⚝ 自注意力机制 (Self-Attention): 注意力机制的一种特殊形式,其中 Query、Key 和 Value 都来自于同一个序列。它允许模型计算序列中任意两个位置之间的依赖关系,无论它们距离多远。这是 Transformer 模型的核心组成部分。
⚝ 序列建模 (Sequence Modeling): 处理输入或输出为序列数据(如文本、时间序列、基因序列)的任务。RNN、LSTM、CNN 和 Transformer 都是重要的序列建模技术。
⚝ T5 (Text-to-Text Transfer Transformer): 一种基于 Encoder-Decoder 架构的预训练 Transformer 模型。其特点是将所有NLP任务都统一表示为“文本到文本”的格式,例如机器翻译、问答、摘要等都被视为输入一段文本,输出另一段文本。
⚝ 文本分类 (Text Classification): 自然语言处理中的一项任务,旨在将一段文本分到预定义的类别中。Encoder-only Transformer 模型(如 BERT)在该任务上表现优异。
⚝ Transformer: 一种完全基于注意力机制的序列模型架构,由 Vaswani 等人于 2017 年提出。它摒弃了传统的循环结构,极大地提高了模型训练的并行性,并在各种序列任务中取得了巨大的成功,成为现代AI模型的基石。
⚝ Value (值): 参见 Query (查询), Key (键), Value (值)。
⚝ Vision Transformer (ViT): 第一批成功地将 Transformer 模型直接应用于图像分类任务的模型之一。它将图像分割成小块 (patch),并将每个块视为序列中的一个“词”,然后使用标准的 Transformer 编码器进行处理。
⚝ 预热 (Warm-up): 在模型训练初期,将学习率从一个很小的值逐渐增加到预设的最大值的策略。这有助于训练的稳定,尤其是在使用 Adam 等自适应学习率优化器时。在 Transformer 模型训练中常用。
Appendix B: 参考文献 (References)
本附录列出了本书在阐述注意力机制和 Transformer 模型及其应用时所参考或引用的重要学术论文、书籍和技术报告。这些文献是构建相关理论基础和推动技术发展的重要基石,对于希望深入研究该领域的读者具有极高的价值。
① Bahdanau, D., Cho, K., & Bengio, Y. (2015). Neural Machine Translation by Jointly Learning to Align and Translate. International Conference on Learning Representations (ICLR).
▮▮▮▮⚝ 这是最早将注意力机制引入神经机器翻译(Neural Machine Translation, NMT)的开创性工作之一,提出了加性注意力(Additive Attention)。
② Luong, M. T., Pham, H., & Manning, C. D. (2015). Effective Approaches to Attention-based Neural Machine Translation. Empirical Methods in Natural Language Processing (EMNLP).
▮▮▮▮⚝ 提出了多种基于注意力的 NMT 架构,包括常用的点积注意力(Dot-Product Attention)。
③ Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., ... & Polosukhin, I. (2017). Attention Is All You Need. Advances in Neural Information Processing Systems (NeurIPS), 30.
▮▮▮▮⚝ 提出了革命性的 Transformer 模型,完全基于自注意力(Self-Attention)机制,抛弃了传统的循环神经网络(Recurrent Neural Network, RNN)和卷积神经网络(Convolutional Neural Network, CNN),奠定了现代序列建模的基础。
④ Devlin, J., Chang, M. W., Lee, K., & Toutanova, K. (2018). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. North American Chapter of the Association for Computational Linguistics (NAACL).
▮▮▮▮⚝ 提出了 BERT (Bidirectional Encoder Representations from Transformers),通过大规模无监督预训练(Pre-training)在下游任务上取得了巨大成功,开启了预训练语言模型(Pre-trained Language Model, PLM)的新时代。BERT 是典型的仅编码器(Encoder-only)模型。
⑤ Radford, A., Narasimhan, K., Salimans, T., & Sutskever, I. (2018). Improving Language Understanding by Generative Pre-Training. OpenAI blog.
▮▮▮▮⚝ 提出了 GPT-1 (Generative Pre-trained Transformer 1),展示了通过在大量文本数据上进行自回归预训练可以学习到强大的语言表示,是仅解码器(Decoder-only)模型的早期重要工作。
⑥ Radford, A., Wu, J., Child, R., Luan, D., Amodei, D., & Sutskever, I. (2019). Language Models are Unsupervised Multitask Learners. OpenAI blog.
▮▮▮▮⚝ 提出了 GPT-2 (Generative Pre-trained Transformer 2),拥有更多的参数和更强的生成能力,进一步强调了大规模语言模型在无监督学习下的多任务能力。
⑦ Brown, T. B., Mann, B., Ryder, N., Subbiah, M., Kaplan, J., Dhariwal, P., ... & Amodei, D. (2020). Language Models are Few-Shot Learners. Advances in Neural Information Processing Systems (NeurIPS), 33.
▮▮▮▮⚝ 提出了 GPT-3 (Generative Pre-trained Transformer 3),拥有 1750 亿参数,展示了超大规模模型在少样本学习(Few-shot Learning)上的惊人表现。
⑧ Raffel, C., Shazeer, N., Roberts, A., Lee, K., Narang, S., Matena, M., ... & Liu, P. J. (2019). Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer. Journal of Machine Learning Research (JMLR), 21(140), 1-67.
▮▮▮▮⚝ 提出了 T5 (Text-to-Text Transfer Transformer),将各种文本处理任务统一到文本到文本(Text-to-Text)的框架下,并发布了新的大规模数据集 C4。T5 是典型的编码器-解码器(Encoder-Decoder)模型。
⑨ Lewis, M., Liu, Y., Goyal, N., Ghazvininejad, A., Mohamed, A., Levy, O., ... & Zettlemoyer, L. (2019). BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension. Association for Computational Linguistics (ACL).
▮▮▮▮⚝ 提出了 BART (Bidirectional and Auto-Regressive Transformer),一个用于文本生成、翻译和理解的去噪自编码(Denoising Autoencoder)预训练模型,也是编码器-解码器结构。
⑩ Dosovitskiy, A., Beyer, L., Kolesnikov, A., Xu, D., Weissenborn, M., Zhai, X., ... & Houlsby, N. (2020). An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. International Conference on Learning Representations (ICLR).
▮▮▮▮⚝ 提出了 Vision Transformer (ViT),将 Transformer 模型成功应用于计算机视觉(Computer Vision)领域的图像分类任务,证明了 Transformer 在非序列数据上的潜力。
⑪ Carion, N., Massa, F., Synnaeve, G., Usunier, N., Kirillov, A., & Zagoruyko, S. (2020). End-to-End Object Detection with Transformers. European Conference on Computer Vision (ECCV).
▮▮▮▮⚝ 提出了 DETR (DEtection TRansformer),第一个端到端(End-to-End)使用 Transformer 进行目标检测(Object Detection)的模型。
⑫ Jumper, J., Evans, R., Pritzel, A., Green, T., Jones, N., Thornton, A., ... & Hassabis, D. (2021). Highly accurate protein structure prediction with AlphaFold. Nature, 596(7873), 583-589.
▮▮▮▮⚝ 介绍了 AlphaFold,该模型使用了基于 Transformer 的架构来预测蛋白质结构,在生物信息学(Bioinformatics)领域取得了突破性进展。
⑬ Dale, R. (2021). GPT-3: What’s It Good For?. Natural Language Engineering, 27(3), 361-366.
▮▮▮▮⚝ 一篇对 GPT-3 能力和局限性的讨论文章。
⑭ Liu, Z., Lin, Y., Cao, Y., Hu, H., Wei, Y., Zhang, Z., ... & Guo, B. (2021). Swin Transformer: Hierarchical Vision Transformer using Shifted Windows. International Conference on Computer Vision (ICCV).
▮▮▮▮⚝ 提出了一种更高效的 Vision Transformer 变体,通过分层结构和移位窗口(Shifted Windows)降低了计算复杂度。
Appendix C: 常用资源与工具 (Resources and Tools)
掌握注意力机制(Attention Mechanism)和Transformer模型是当前深度学习领域最重要的技能之一。除了阅读本书深入理解理论知识外,充分利用现有的学习资源和工具库能够极大地加速学习进程和实践能力。本附录旨在为您推荐一些广受认可的在线课程、开源代码库、常用数据集以及其他学习辅助工具,帮助您更好地踏上探索和应用Transformer技术的旅程。
Appendix C1: 在线课程与教程 (Online Courses and Tutorials)
通过结构化的在线课程和深入的教程,可以系统地学习注意力机制和Transformer的原理及应用。
① Coursera / deeplearning.ai 的“自然语言处理专业课程” (Natural Language Processing Specialization)
▮▮▮▮ⓑ 特点:由深度学习领域的领军人物 Andrew Ng 教授团队打造,包含多门课程,其中部分章节详细讲解了注意力机制和Transformer在序列模型和机器翻译中的应用。
▮▮▮▮ⓒ 目标:适合对NLP和序列模型有一定基础,希望系统学习现代NLP技术的学习者。
② 哈佛大学 CS224N:“自然语言处理与深度学习” (Natural Language Processing with Deep Learning)
▮▮▮▮ⓑ 特点:该课程提供了非常深入的理论讲解和实践作业,其在线课程资料(讲义、视频)是学习Attention和Transformer的宝贵资源。
▮▮▮▮ⓒ 目标:适合有较强数学和编程基础,希望深入理解NLP模型原理和最新进展的学习者。
③ 斯坦福大学 CS231n:“卷积神经网络在视觉识别中的应用” (Convolutional Neural Networks for Visual Recognition)
▮▮▮▮ⓑ 特点:虽然课程主题是CNN,但在后期章节中会介绍Transformer在计算机视觉(Computer Vision)领域的应用,如Vision Transformer (ViT) 等。
▮▮▮▮ⓒ 目标:适合希望了解Transformer在CV领域应用的学习者。
④ Transformer 论文官方博客 / Distill.pub 文章
▮▮▮▮ⓑ 特点:《Attention Is All You Need》原论文是基石,而 accompanying blog post (配套博客文章) 提供了直观的可视化解释。Distill.pub 上也有一些关于Attention和Transformer可视化理解的优秀文章。
▮▮▮▮ⓒ 目标:适合希望从第一性原理出发,结合可视化深入理解模型工作原理的学习者。
⑤ YouTube / B站 等视频平台上的技术讲解
▮▮▮▮ⓑ 特点:搜索“注意力机制”、“Transformer原理”、“BERT”、“GPT”等关键词,可以找到大量个人或机构制作的讲解视频,质量参差不齐,但部分内容通俗易懂,适合入门。
▮▮▮▮ⓒ 目标:适合偏好视频学习方式,希望快速建立概念的学习者。
Appendix C2: 开源库与框架 (Open Source Libraries and Frameworks)
实践是掌握知识的最好方式。使用主流的深度学习框架和专门的库可以高效地构建、训练和使用注意力机制与Transformer模型。
① Hugging Face Transformers ✨🏆
▮▮▮▮ⓑ 特点:这是目前最流行、最全面的Transformer模型库,提供了海量预训练模型和用于各种下游任务的接口。支持 PyTorch、TensorFlow 和 JAX。
▮▮▮▮ⓒ 功能:
▮▮▮▮▮▮▮▮❹ 包含 BERT, GPT-2, GPT-3, T5, BART 等几乎所有主流 Transformer 模型。
▮▮▮▮▮▮▮▮❺ 提供方便的 AutoModel
, AutoTokenizer
类,可以轻松加载不同模型和对应的分词器(Tokenizer)。
▮▮▮▮▮▮▮▮❻ 丰富的文本处理工具和 pipeline (流水线) API,用于快速实现常见任务。
▮▮▮▮▮▮▮▮❼ 活跃的社区和详细的文档。
▮▮▮▮ⓗ 学习资源:官方文档、示例代码、以及其维护者开设的课程 (如 NLP Course by Hugging Face)。
▮▮▮▮ⓘ 目标:所有希望在实际项目中使用 Transformer 模型的学习者都应优先学习和掌握 Hugging Face Transformers 库。
② PyTorch
▮▮▮▮ⓑ 特点:一个灵活且功能强大的深度学习框架。Hugging Face Transformers 库底层主要基于 PyTorch 或 TensorFlow。
▮▮▮▮ⓒ 功能:提供了构建神经网络的基本模块,包括线性层(Linear Layer)、激活函数(Activation Functions)、损失函数(Loss Functions)、优化器(Optimizers)等。torch.nn.Transformer
模块提供了 Transformer 的标准 Encoder-Decoder 实现。
▮▮▮▮ⓓ 学习资源:官方教程、文档,以及大量基于 PyTorch 的开源项目。
▮▮▮▮ⓔ 目标:适合希望深入理解模型实现细节,或者需要自定义模型结构的学习者。
③ TensorFlow
▮▮▮▮ⓑ 特点:另一个广泛使用的深度学习框架,由 Google 开发。同样支持构建复杂的神经网络模型。
▮▮▮▮ⓒ 功能:与 PyTorch 类似,提供丰富的神经网络构建模块。Keras API (现在是 TensorFlow 的核心高层 API) 提供了 TransformerEncoder
和 TransformerDecoder
等组件。
▮▮▮▮ⓓ 学习资源:官方教程、文档。
▮▮▮▮ⓔ 目标:适合习惯使用 TensorFlow 生态系统,或者需要部署到特定 Google 云平台环境的学习者。
④ JAX / Flax / Haiku
▮▮▮▮ⓑ 特点:由 Google 开发,以其高效的自动微分和函数变换(如 JIT 编译、vmap 向量化)而闻名,特别适合大规模模型的研究和训练。Flax 和 Haiku 是构建神经网络的高层库。
▮▮▮▮ⓒ 功能:虽然不像 PyTorch/TensorFlow 那样普及,但在前沿研究和训练超大模型(如 PaLM)中扮演重要角色。Hugging Face Transformers 也支持 JAX 后端。
▮▮▮▮ⓓ 目标:适合对高性能计算和最新深度学习框架感兴趣的研究人员或工程师。
Appendix C3: 数据集 (Datasets)
选择合适的数据集对于训练、评估和应用注意力机制及Transformer模型至关重要。
① 自然语言处理 (NLP) 数据集
▮▮▮▮ⓑ 机器翻译 (Machine Translation):
▮▮▮▮▮▮▮▮❸ WMT (Workshop on Machine Translation): 提供多种语言对的大规模平行语料库(Parallel Corpus)。
▮▮▮▮▮▮▮▮❹ OPUS: 另一个平行语料库的集合,数据量巨大且多样。
▮▮▮▮ⓔ 文本分类 (Text Classification):
▮▮▮▮▮▮▮▮❻ AG News: 新闻主题分类数据集。
▮▮▮▮▮▮▮▮❼ SST-2 (Stanford Sentiment Treebank): 情感分析数据集,属于 GLUE benchmark。
▮▮▮▮ⓗ 问答系统 (Question Answering):
▮▮▮▮▮▮▮▮❾ SQuAD (Stanford Question Answering Dataset): 阅读理解式问答数据集。
▮▮▮▮▮▮▮▮❿ Natural Questions: 来自 Google 搜索数据的真实问答对。
▮▮▮▮ⓚ 文本摘要 (Text Summarization):
▮▮▮▮▮▮▮▮❶ CNN/Daily Mail: 新闻文章及其摘要的数据集。
▮▮▮▮▮▮▮▮❷ XSum: 更具挑战性的单句摘要数据集。
▮▮▮▮ⓝ 通用语言理解评估 (General Language Understanding Evaluation):
▮▮▮▮▮▮▮▮❶ GLUE benchmark: 包含多种 NLP 任务的集合,用于评估模型在广泛任务上的泛化能力。
▮▮▮▮▮▮▮▮❷ SuperGLUE benchmark: GLUE 的升级版,包含更具挑战性的任务。
② 计算机视觉 (Computer Vision) 数据集
▮▮▮▮ⓑ 图像分类 (Image Classification):
▮▮▮▮▮▮▮▮❸ ImageNet: 视觉领域最著名的大规模图像数据集,常用于预训练 Vision Transformer (ViT)。
▮▮▮▮▮▮▮▮❹ CIFAR-10 / CIFAR-100: 中小型图像分类数据集,适合快速实验。
▮▮▮▮ⓔ 目标检测 (Object Detection):
▮▮▮▮▮▮▮▮❻ COCO (Common Objects in Context): 广泛用于目标检测、分割、关键点检测等任务。DETR (Detection Transformer) 模型就是基于此数据集进行评估。
▮▮▮▮ⓖ 图像生成 (Image Generation):
▮▮▮▮▮▮▮▮❽ LSUN (Large-scale Scene Understanding): 包含多种场景类别的数据集。
▮▮▮▮▮▮▮▮❾ CelebA: 人脸属性数据集。
③ 语音处理 (Speech Processing) 数据集
▮▮▮▮ⓑ LibriSpeech: 大规模英文语音识别数据集。
▮▮▮▮ⓒ LJSpeech: 英文文本到语音(Text-to-Speech, TTS)数据集。
Appendix C4: 研究论文与博客 (Research Papers and Blogs)
关注该领域的经典论文和前沿研究进展是保持知识更新的关键。
① 经典论文
▮▮▮▮ⓑ "Attention Is All You Need" (Vaswani et al., 2017): Transformer 模型的奠基之作,必读!
▮▮▮▮ⓒ "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding" (Devlin et al., 2018): BERT 模型论文,开创了预训练语言模型的新时代。
▮▮▮▮ⓓ "Language Models are Unsupervised Multitask Learners" (Radford et al., 2019): GPT-2 论文,展示了大规模语言模型的零样本(Zero-Shot)学习能力。
▮▮▮▮ⓔ "An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale" (Dosovitskiy et al., 2020): Vision Transformer (ViT) 论文,将 Transformer 引入图像分类领域。
② 重要博客与网站
▮▮▮▮ⓑ Jay Alammar 的博客: 提供了很多关于 Attention、Transformer、BERT 等模型的直观、高质量的可视化解释文章,如 "The Illustrated Transformer"。
▮▮▮▮ⓒ Distill.pub: 专注于机器学习可解释性(Interpretability)的在线期刊,包含一些关于 Attention 和 Transformer 的精彩可视化研究。
▮▮▮▮ⓓ 各大研究机构和高校的博客: 如 Google AI Blog, Facebook AI Blog, OpenAI Blog 等,经常发布最新的研究成果和技术讲解。
Appendix C5: 开发工具与平台 (Development Tools and Platforms)
高效的开发环境和计算资源是进行模型实验和训练的保障。
① 在线开发环境
▮▮▮▮ⓑ Google Colaboratory (Colab): 提供免费的 GPU/TPU 计算资源,非常适合学习、实验和原型开发。
▮▮▮▮ⓒ Kaggle Kernels: 类似于 Colab,也提供免费计算资源,并且是参与 Kaggle 竞赛的平台。
② 云计算平台
▮▮▮▮ⓑ Amazon Web Services (AWS): 提供 EC2 (弹性计算云) 实例,可以租用带有高性能 GPU 的虚拟机。SageMaker 提供了机器学习的全托管服务。
▮▮▮▮ⓒ Google Cloud Platform (GCP): 提供 Compute Engine (计算引擎) 实例,以及用于训练的 TPU (张量处理单元)。AI Platform 提供了托管的机器学习服务。
▮▮▮▮ⓓ Microsoft Azure: 提供虚拟机和 Azure Machine Learning 服务。
③ 可视化工具
▮▮▮▮ⓑ TensorBoard: TensorFlow 和 PyTorch 都支持的训练过程可视化工具,可以查看损失曲线、指标、计算图、模型权重分布等,有助于调试和理解训练过程。
▮▮▮▮ⓒ ExBERT (BERTology): 一些专门针对 BERT 等模型的可解释性工具,可以可视化 Attention 权重等。
④ 其他辅助工具
▮▮▮▮ⓑ Git: 版本控制工具,管理代码必备。
▮▮▮▮ⓒ Docker: 容器化技术,方便构建和部署一致的开发环境。
▮▮▮▮ⓓ Jupyter Notebook / JupyterLab: 交互式编程环境,适合探索性开发和展示代码。
充分利用这些资源,结合本书的理论讲解和实践指导,相信您一定能在注意力机制和Transformer的世界中取得显著的进步!加油!💪
Appendix D: 代码示例 (Code Examples)
Appendix D1: 引言 (Introduction)
理解注意力机制(Attention Mechanism)和 Transformer 模型最好的方式之一就是通过代码实践。本附录提供一些使用主流深度学习框架 PyTorch 实现的简化代码示例,帮助读者将抽象的理论概念转化为具体的计算流程。这些示例旨在展示核心机制,并非生产级代码,但在学习和理解阶段非常有用。
Appendix D2: 缩放点积注意力 (Scaled Dot-Product Attention) 的实现
缩放点积注意力(Scaled Dot-Product Attention)是 Transformer 模型中最基础的注意力形式。它的输入是查询(Query, Q)、键(Key, K)和值(Value, V)三个向量序列。其计算过程包括:计算 Q 和 K 的点积得到注意力得分(Attention Score),将得分除以 \(\sqrt{d_k}\) 进行缩放(Scaling),对缩放后的得分应用 Softmax 函数得到注意力权重(Attention Weight),最后将权重与 V 相乘得到最终的输出。
数学表达式为:
\[ \text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V \]
其中 \(d_k\) 是键向量 K 的维度。
下面是使用 PyTorch 实现这个核心机制的代码:
1
import torch
2
import torch.nn.functional as F
3
4
def scaled_dot_product_attention(q, k, v, mask=None):
5
"""
6
计算缩放点积注意力 (Scaled Dot-Product Attention)。
7
8
参数:
9
q (torch.Tensor): 查询张量 (Query tensor),形状如 (..., seq_len_q, d_k)。
10
k (torch.Tensor): 键张量 (Key tensor),形状如 (..., seq_len_k, d_k)。
11
v (torch.Tensor): 值张量 (Value tensor),形状如 (..., seq_len_v, d_v)。
12
注意: seq_len_k 必须等于 seq_len_v。
13
mask (torch.Tensor, optional): 掩码张量 (Mask tensor),形状与 (..., seq_len_q, seq_len_k) 兼容。
14
用于遮盖某些连接,通常设为负无穷。
15
16
返回:
17
tuple: (输出张量 (Output tensor), 注意力权重张量 (Attention weights tensor))。
18
输出形状如 (..., seq_len_q, d_v)。
19
注意力权重形状如 (..., seq_len_q, seq_len_k)。
20
"""
21
# 确保 K 和 V 在序列长度维度上一致
22
assert k.size(-2) == v.size(-2), "Key and Value sequences must have the same length"
23
24
# 获取 d_k,即键向量的最后一维大小
25
d_k = k.size(-1)
26
27
# ① 计算 Q 和 K 的点积 (QK^T)
28
# 形状: (..., seq_len_q, seq_len_k)
29
scores = torch.matmul(q, k.transpose(-2, -1))
30
31
# ② 缩放 (Scaling)
32
# 除以 sqrt(d_k)
33
scores = scores / torch.sqrt(torch.tensor(d_k, dtype=torch.float32))
34
35
# ③ 应用掩码 (Apply mask),如果提供的话
36
# 掩码中的 True 或 1 会被替换为负无穷,从而在 Softmax 后变为接近0的权重
37
if mask is not None:
38
scores = scores.masked_fill(mask == 0, float('-inf')) # PyTorch的掩码习惯,0表示需要掩盖
39
40
# ④ 计算注意力权重 (Softmax)
41
# 形状: (..., seq_len_q, seq_len_k)
42
weights = F.softmax(scores, dim=-1)
43
44
# ⑤ 将权重与 V 相乘 (Attention * V)
45
# 形状: (..., seq_len_q, d_v)
46
output = torch.matmul(weights, v)
47
48
return output, weights
49
50
# --- 示例用法 ---
51
# 假设输入批量大小 (batch_size) 为 2,序列长度 (sequence_length) 为 3,特征维度 (d_model) 为 4
52
# 在这个简化例子中,Q, K, V 可以来自同一个输入序列
53
batch_size = 2
54
seq_len = 3
55
d_k = 4 # Key/Query dimension
56
d_v = 5 # Value dimension (可以与 d_k 不同,但通常在Transformer中 d_k = d_v = d_model / num_heads)
57
58
# 模拟输入 Q, K, V 张量
59
# 在实际 Self-Attention 中,Q, K, V 会通过线性层从输入 X 投影得到
60
q_example = torch.randn(batch_size, seq_len, d_k)
61
k_example = torch.randn(batch_size, seq_len, d_k)
62
v_example = torch.randn(batch_size, seq_len, d_v)
63
64
# 调用注意力函数
65
output_example, weights_example = scaled_dot_product_attention(q_example, k_example, v_example)
66
67
print("--- Scaled Dot-Product Attention 示例 ---")
68
print(f"输入 Query 形状: {q_example.shape}")
69
print(f"输入 Key 形状: {k_example.shape}")
70
print(f"输入 Value 形状: {v_example.shape}")
71
print(f"输出 Output 形状: {output_example.shape}")
72
print(f"注意力权重 Weights 形状: {weights_example.shape}")
73
74
# --- 带掩码的示例 (例如,用于 Decoder 的自注意力) ---
75
# 假设我们想计算第一个位置的注意力,它只能关注自己。第二个位置可以关注第一个和自己,以此类推。
76
# 这对应于一个下三角掩码。
77
mask_example = torch.tril(torch.ones(seq_len, seq_len)).unsqueeze(0).unsqueeze(0) # 形状: (1, 1, seq_len, seq_len)
78
# 将需要掩盖的位置 (下三角矩阵中值为0的位置) 设为0,对应 masked_fill(mask == 0, float('-inf')) 的逻辑
79
mask_example[mask_example == 0] = 0
80
mask_example[mask_example == 1] = 1 # 确保是0/1掩码
81
82
print("\n--- Scaled Dot-Product Attention 带掩码示例 ---")
83
print(f"使用的掩码形状: {mask_example.shape}")
84
print("使用的掩码内容:")
85
print(mask_example.squeeze()) # 打印更直观的2D掩码
86
output_masked_example, weights_masked_example = scaled_dot_product_attention(q_example, k_example, v_example, mask=mask_example)
87
88
print(f"带掩码的输出 Output 形状: {output_masked_example.shape}")
89
print(f"带掩码的注意力权重 Weights 形状: {weights_masked_example.shape}")
90
print("带掩码的注意力权重 (注意被掩码位置的权重应接近0):")
91
print(weights_masked_example)
这段代码清晰地展示了缩放点积注意力的五个核心步骤:计算得分、缩放、应用掩码(可选)、计算权重、加权求和。读者可以通过运行这段代码,观察输入输出张量的形状变化,加深对计算流程的理解。
Appendix D3: 简单的自注意力层 (Simple Self-Attention Layer) 的实现
自注意力层(Self-Attention Layer)是 Transformer 编码器和解码器中的关键组件。它接收一个输入序列 \(X\),通过三个线性变换(Linear Transformation)将其分别投影到查询(Q)、键(K)和值(V)空间。然后,对这些 Q, K, V 使用上述缩放点积注意力函数进行计算,最后可能再通过一个线性层进行最终输出投影。
\[ \text{SelfAttention}(X) = \text{Linear}_O(\text{Attention}(\text{Linear}_Q(X), \text{Linear}_K(X), \text{Linear}_V(X))) \]
下面是使用 PyTorch 实现一个简单的自注意力模块的代码:
1
import torch
2
import torch.nn as nn
3
import torch.nn.functional as F
4
5
# 重用上面定义的缩放点积注意力函数
6
# def scaled_dot_product_attention(q, k, v, mask=None): ...
7
8
class SimpleSelfAttention(nn.Module):
9
"""
10
简单的自注意力层 (Simple Self-Attention Layer)。
11
不包含多头 (Multi-Head) 或残差连接 (Residual Connection) 等,仅展示核心的自注意力计算。
12
"""
13
def __init__(self, embed_dim, d_k, d_v):
14
"""
15
初始化自注意力层。
16
17
参数:
18
embed_dim (int): 输入特征的维度 (Embedding dimension)。
19
d_k (int): 查询和键向量的维度 (Dimension of Queries and Keys)。
20
d_v (int): 值向量的维度 (Dimension of Values)。
21
"""
22
super().__init__()
23
self.embed_dim = embed_dim
24
self.d_k = d_k
25
self.d_v = d_v
26
27
# 定义线性层用于将输入投影到 Q, K, V 空间
28
self.linear_q = nn.Linear(embed_dim, d_k)
29
self.linear_k = nn.Linear(embed_dim, d_k)
30
self.linear_v = nn.Linear(embed_dim, d_v)
31
32
# 最终的输出线性层 (可选,但在标准Transformer中通常有)
33
# 这里假设输出维度与输入维度相同,以便后续处理
34
self.linear_out = nn.Linear(d_v, embed_dim)
35
36
37
def forward(self, x, mask=None):
38
"""
39
前向传播。
40
41
参数:
42
x (torch.Tensor): 输入张量,形状如 (batch_size, seq_len, embed_dim)。
43
mask (torch.Tensor, optional): 注意力掩码。
44
45
返回:
46
torch.Tensor: 输出张量,形状如 (batch_size, seq_len, embed_dim)。
47
"""
48
batch_size, seq_len, _ = x.size()
49
50
# ① 通过线性层计算 Q, K, V
51
# 形状: (batch_size, seq_len, d_k) 或 (batch_size, seq_len, d_v)
52
q = self.linear_q(x)
53
k = self.linear_k(x)
54
v = self.linear_v(x)
55
56
# ② 调用之前实现的缩放点积注意力函数
57
# 注意力函数期望 Q, K, V 的形状是 (..., seq_len, dim),这里已经满足 batch_size 这个额外的维度
58
attn_output, attn_weights = scaled_dot_product_attention(q, k, v, mask=mask)
59
60
# ③ 通过输出线性层进行投影
61
# 形状: (batch_size, seq_len, embed_dim)
62
output = self.linear_out(attn_output)
63
64
return output # 在实际Transformer层中,通常也会返回 attn_weights 用于分析
65
66
# --- 示例用法 ---
67
batch_size = 2
68
seq_len = 3
69
embed_dim = 64 # 输入特征维度
70
d_k = 64 # Q, K 维度 (简化起见,通常是 embed_dim / num_heads)
71
d_v = 64 # V 维度 (简化起见,通常是 embed_dim / num_heads)
72
73
# 创建一个简单的自注意力层实例
74
simple_self_attn_layer = SimpleSelfAttention(embed_dim, d_k, d_v)
75
76
# 模拟输入张量 (例如,词嵌入 + 位置编码后的表示)
77
input_tensor = torch.randn(batch_size, seq_len, embed_dim)
78
79
# 调用前向传播
80
output_tensor = simple_self_attn_layer(input_tensor)
81
82
print("\n--- Simple Self-Attention Layer 示例 ---")
83
print(f"输入张量形状: {input_tensor.shape}")
84
print(f"输出张量形状: {output_tensor.shape}")
85
86
# --- 带掩码的示例 ---
87
# 假设是 Decoder 的自注意力,需要未来的信息进行掩码
88
# 生成下三角掩码
89
mask_example = torch.tril(torch.ones(seq_len, seq_len)).unsqueeze(0).unsqueeze(0) # 形状: (1, 1, seq_len, seq_len)
90
mask_example[mask_example == 0] = 0 # 0表示需要掩盖
91
mask_example[mask_example == 1] = 1 # 1表示不掩盖
92
93
print("\n--- Simple Self-Attention Layer 带掩码示例 ---")
94
output_masked_tensor = simple_self_attn_layer(input_tensor, mask=mask_example)
95
print(f"带掩码的输出张量形状: {output_masked_tensor.shape}")