《Attention is all you need》论文阅读与代码实战文章目录1. 模型架构与模块分解1.1 模型架构图1.2 缩放点积注意力1.3 多头自注意力1.4 嵌入层1.5 位置编码1.6 前馈神经网络FFN2. 数据流如何通过模型3. 代码实战实现完整的Encoder-Decoder Transformer3.1 Encoder-only的Transformer block3.2 完整可训练的Transformer3.3 手撕实现千问3Dense实现对话功能。学习他人的开源项目Transformer的核心动机是解决传统模型并行性差、长距离依赖建模能力弱的问题适用于Seq2Seq的任务比如机器翻译、文本生成。核心组件是输入层Embedding 位置编码将离散 token 转为带位置信息的稠密向量编码器栈N 层原论文 N6相同的 Encoder Block负责编码输入序列的全局上下文解码器栈N 层原论文 N6相同的 Decoder Block负责自回归生成输出序列输出层线性层 Softmax将解码器输出映射为词表概率分布。1. 模型架构与模块分解1.1 模型架构图由Embedding层、位置编码、TransformerBlockDecoder和Encoder多头自注意力残差连接归一化FNN前馈层最后有一个线性层作用是把d_model长度的特征映射为vocab_size长度的向量再经softmax层得到下一个token对应vocab_size大小的词表中的概率。1.2 缩放点积注意力通俗来说就是输入一段序列序列经过自注意力之后序列中的各个token能够根据自己的目标(Query)重点关注序列和自己最相关的其他token。自注意力的核心目标是给输入序列里的每一个token都生成一个融合了整个序列所有上下文信息的新向量。1.3 多头自注意力使用多头注意力来建模序列内各token之间的多维度关系比如动宾关系、主谓关系等等具体做法是把注意力计算拆成h个独立的「头」按特征维度拆分每个头都是一个完整的「单头缩放点积注意力」每个头专门学习一种类型的语义 / 语法依赖最后把所有头的结果汇总模型的表达能力直接翻倍。1.4 嵌入层就是一个字典可学习的查找表。将离散的 token如单词、子词转化为模型可计算的固定维度稠密向量维度记为d_model原论文取 512解决离散符号无法直接参与数值计算的问题。同时输出端的 Embedding 层可与输入端共享权重原论文优化策略减少参数总量。假设词表大小为vocab_size则嵌入层参数为vocab_size × d_model的矩阵手撕embedding:importtorchimporttorch.nnasnnclassTokenEmbedding(nn.Module):def__init__(self,vocab_size:int,d_model:int):super().__init__()self.embeddingnn.Embedding(vocab_size,d_model)self.d_modeld_model# 缩放因子与位置编码对齐defforward(self,x:torch.Tensor)-torch.Tensor:# x: [batch_size, seq_len]输入为token的索引序列# 输出: [batch_size, seq_len, d_model]returnself.embedding(x)*torch.sqrt(torch.tensor(self.d_model,dtypetorch.float32))1.5 位置编码Transformer 无循环 / 卷积结构无法天然感知序列中 token 的位置信息比如 “我爱你” 和 “你爱我” 语义不同仅靠 Embedding 无法区分因此需要显式注入位置信息。实现方式正弦 / 余弦位置编码。位置编码的维度与 Embedding 一致d_model。与传统方案直接将位置向量加在Embeeding上不同RoPE通过旋转矩阵改变Q和K的方向将位置信息编码进点积运算中。B站up“这就是小c”的RoPE讲解非常好。这部分不手撕代码。1.6 前馈神经网络FFN对每个 token 的向量做独立的非线性变换提炼高阶语义特征注意力层负责上下文融合FFN 负责特征映射。先升维再降维。提取高阶语义特征。注意力层负责上下文融合FFN负责特征映射把零散的上下文信号合并成更高阶的寓意概念。2. 数据流如何通过模型一、先看整体架构总览这张图完全对应《Attention Is All You Need》的标准Transformer结构分为两大核心部分左半部分编码器Encoder负责「理解输入文本」把输入序列转化为带全局上下文的语义编码。右半部分解码器Decoder负责「生成输出文本」基于编码器的语义编码自回归地逐token生成目标序列。图中N×代表该模块会重复堆叠N次原论文默认N6即编码器、解码器各堆叠6层。二、左半部分编码器Encoder全拆解对应你之前学的编码器自注意力层我们从下到上跟着箭头走通每一步编码器输入预处理层最底部Inputs → Input Embedding → 【Positional Encoding】 → 输入编码器堆叠层Inputs输入的原始文本序列比如机器翻译的源语言句子会先拆成一个个token。Input Embedding嵌入层把离散的token转化为固定维度的稠密向量让文本变成模型可计算的数值。Positional Encoding位置编码和嵌入向量直接相加为token注入序列位置信息Transformer没有循环结构无法天然感知顺序。编码器单层结构N次堆叠的核心同样每个子模块都标配残差连接Add Norm3个子模块从下到上依次是① 第一个子模块Masked Multi-Head Attention → 【解码器掩码自注意力层】这就是带因果掩码的自注意力完全对应Q、K、V的来源全部来自解码器上一层的输出三者同源也是自注意力。掩码设计核心的因果掩码在Softmax计算前把得分矩阵的上三角当前位置之后的token全部设为-∞Softmax后权重为0。效果解码器的每个token只能关注到当前位置及之前已经生成的token完全看不到未来的内容严格保证自回归生成的合理性。核心作用给已生成的输出序列做上下文融合同时杜绝信息泄露。② 第二个子模块Multi-Head Attention → 【编码器-解码器交叉注意力层】这就是交叉注意力是连接编码器和解码器的核心桥梁完全对应Q、K、V的来源Q查询来自解码器上一层也就是下面Masked Attention的输出K键、V值全部来自左边编码器的最终输出。掩码设计无掩码解码器的每个位置都能关注到输入序列的所有位置。核心作用让解码器生成每一个token时都能动态关注输入序列里最相关的内容。比如翻译时生成中文「苹果」会重点关注英文输入里的apples。③ 第三个子模块Feed Forward → 前馈神经网络和编码器里的前馈层完全一致对每个token的向量做独立的非线性变换提炼特征同样标配残差连接Add Norm。3. 编码器的最终输出堆叠N层后的解码器输出向上进入最终的预测环节解码器输出 → Linear → Softmax → Output ProbabilitiesLinear线性层把解码器输出的高维语义向量映射到和目标词表大小一致的维度。Softmax归一化层把线性层的输出转化为词表中每个token的生成概率概率最高的token就是当前步的预测输出。Output Probabilities最终的输出概率就是模型生成的目标序列。四、三种注意力层与图的精准对应表五、一句话走通完整数据流以机器翻译为例输入英文I love apples目标输出中文我爱苹果整个流程在图里的走向是英文输入进入左半部分编码器经过嵌入位置编码再通过6层编码器的自注意力前馈层得到英文句子的完整语义编码解码器先接收已生成的内容初始是句子开始符经过嵌入位置编码进入6层解码器先过掩码自注意力融合已生成的内容且不偷看未来再过交叉注意力用当前生成的特征去匹配编码器的英文语义编码找到最相关的内容最后过前馈层提炼特征解码器输出经过LinearSoftmax预测出下一个token比如第一个预测出「我」把「我」加入解码器的输入重复上述步骤依次预测出「爱」「苹果」直到生成句子结束符完成整个生成过程。3. 代码实战实现完整的Encoder-Decoder Transformer3.1 Encoder-only的Transformer block这是很容易实现的架构为x ──┬──────────────────────► () ─► LayerNorm ──┬────────────────► () ─► LayerNorm ─► y │ ▲ │ ▲ │ │ │ │ └──► Multi-Head Attention ─┘ └──► FeedForward ───┘仓库中提交了上述架构的代码https://github.com/QiZhang603/Mini-Transformer-Block/commit/45fac77efe1972e319c26602f70178c535dc1976。3.2 完整可训练的Transformer在 Encoder-only的Transformer block的基础上需要做“在 mini_Transformer.py 中添加 Token Embedding 与正弦/可学习位置编码输出 shape 与 d_model 对齐并在 forward 中相加后加 dropout。”“实现 padding mask 与 look-ahead mask 生成函数返回可直接喂给 MultiheadAttention(手动实现而不是调用nn.MultiheadAttention) 的 attn_mask 和 key_padding_mask。”“新增 DecoderBlockmasked self-attn、cross-attn、FFN、LayerNorm残差Pre-LN支持返回注意力权重。”“创建完整 Transformer 类持有嵌入、Encoder、Decoder前向接受 src/tgt 及掩码输出 logits可选权重共享。”“添加输出投影到 vocab_size 的线性层提供最小训练脚手架CE loss、optimizer 占位、梯度裁剪、lr 调度钩子与简单自测形状、掩码、tiny 过拟合。”代码在仓库链接https://github.com/QiZhang603/Mini-Transformer-Block/commit/945e30181f61c91fa27f125625dfcbd6308c92bc。该版本并没有对数据集进行编码、分词、训练与输出。仍有瑕疵。3.3 手撕实现千问3Dense实现对话功能。学习他人的开源项目数据集为TinyStory。是一位博主的开源项目目前已经阅读完了源码成功训练了分词器、并对TinyStory数据集进行分词。还差租服务器训练模型看结果与模型对话。项目地址https://github.com/Siyuan-Harry/llm-from-scratch。