FEATURED · 精选文章

Transformer架构解析与PyTorch从零实现

发布时间 / 2026/8/30 23:16:33
来源 / 创域科博编辑部
栏目 / 资讯中心
Transformer架构解析与PyTorch从零实现 大家平时聊到大模型、ChatGPT、GPT-4、Llama 这些名词时总会听到一个绕不开的架构名字Transformer。而提到 Transformer就不能不提它的核心作者之一 Ashish Vaswani。网上对他的称呼很多“AI 领域封神的男人”“Transformer 架构的开山鼻祖”“现代大模型的奠基人”。这些头衔并没有夸大因为 2017 年发表的论文《Attention Is All You Need》确实重塑了整个自然语言处理乃至深度学习的走向。但作为开发者我们仅仅记住一个名字没有意义。真正值得我们关注的是Transformer 架构到底解决了什么问题它和 RNN、LSTM 这类经典序列模型有什么本质区别为什么 Google、Meta、OpenAI 后来发布的模型几乎全部采用 Transformer 路线如果我们要自己动手实现一个最小可运行的 Transformer代码应该怎么组织这篇文章就围绕这些疑问展开。我会先梳理 Transformer 出现的背景和技术动机再从注意力机制、多头注意力、位置编码、残差连接等核心部件逐层拆解架构原理最后用 PyTorch 从零实现一个极简版 Transformer并用于字符级文本生成演示。文章末尾还会整理高频报错、训练不稳定等实战问题以及大模型时代值得关注的最佳实践。不管你是刚接触深度学习的新手还是已经在做模型训练和推理部署的工程师这篇文章都能提供一套可以照着跑、照着改的完整思路。1. 为什么是 Transformer从 RNN 到注意力机制的演进1.1 序列建模的老问题RNN/LSTM 的瓶颈在 Transformer 出现之前自然语言处理领域最主流的结构是 RNN循环神经网络和它的改进版本 LSTM、GRU。RNN 的基本思想是按时间步逐个处理输入每一步都维护一个隐状态 vector把过去的信息逐步向后传递。这种“递归”式的设计天然适合序列数据但存在几个绕不开的痛点长距离依赖难以捕捉。信息要跨越很多时间步才能从序列开头传到结尾中间经过多次非线性变换后早期信息会被严重稀释梯度也容易消失或爆炸。计算无法并行。RNN 的当前时间步依赖上一个时间步的输出只能逐个 token 顺序计算这对 GPU 并行非常不友好。模型一深、序列一长训练时间就会成倍拉长。位置之间的交互距离有限。虽然 LSTM 用门控机制缓解了长期遗忘问题但仍然没有彻底改变“逐步传递”的路径依赖。所以在 Transformer 出现之前做机器翻译、文本分类这类任务大家通常要在“效果”和“训练性能”之间做取舍。1.2 Attention Is All You Need 的破局思路2017 年Ashish Vaswani 等人在论文《Attention Is All You Need》中提出一个激进的想法既然注意力机制可以让模型在计算每个位置时直接“看到”所有其他位置那为什么不彻底放弃循环结构只用注意力来搭建整个模型这就是 Transformer 的核心思想输入序列的任意两个位置之间都可以通过注意力计算直接建立联系。距离不再是阻碍路径长度被压缩为一步同时所有位置的注意力计算可以并行执行训练效率大幅提升。这篇论文发布后很快成为自然语言处理领域的分水岭。后来的 BERT、GPT、T5、GPT-3、Llama、ChatGPT 等模型基本都延续了 Transformer 的架构路线。可以说Ashish Vaswani 的这项研究不仅解决了当时的序列建模难题也为后来大模型的爆发提供了最基础的结构底座。1.3 适合阅读本文的读者如果你属于下面几类人这篇文章会比较适合你刚入门深度学习想知道 Transformer 和 LSTM、注意力机制之间有什么关系。已经会调用 Hugging Face 的 transformer 库但想了解底层实现方便后续微调和改结构。需要自己实现或改造注意力结构想找到一份可以直接跑通的最小示例。准备学习大模型部署、模型压缩需要先理解 Transformer 各组件的数据流。接下来我们从模型结构入手先搞清楚每一个组件的职责再上代码。2. Transformer 架构的核心组件拆解2.1 宏观结构编码器-解码器与 Decoder-only原始 Transformer 是一个典型的 Encoder-Decoder 架构。Encoder 负责把源序列编码为一组上下文表示Decoder 负责根据编码结果和已生成内容逐步产生目标序列。这种结构非常适合机器翻译、文本摘要等序列到序列任务。但到了大模型时代GPT 系列采用了一种更简洁的设计只保留 Decoder 部分通过自回归方式一个 token 一个 token 地生成文本。这也叫 Decoder-only 架构。它的输入是当前已经生成的所有 token输出是下一个 token 的概率分布。现在的 ChatGPT、Llama、Qwen、DeepSeek 等模型基本都是这种结构。为了让你既能理解原始论文的地位又和现代大模型接轨本文实战部分会实现一个极简的 Decoder-only Transformer它保留了 Transformer 的注意力、前馈网络、残差连接、LayerNorm 等核心模块但结构上更接近 GPT 的生成方式。2.2 Token Embedding把文字变成向量神经网络无法直接处理字符串所以第一步要把文本转换成数字向量。常见做法是建立一个词表把每个 token单词或字符映射到一个整数 id。通过 Embedding 层把 id 映射成一个可学习的向量。在 PyTorch 中nn.Embedding(vocab_size, d_model)就能完成这个操作。d_model是模型的隐藏维度比如 512、768 或 1024。一般来说d_model越大模型容量越大训练成本也越高。2.3 位置编码让模型知道顺序自注意力本身是“无序”的。如果不做任何处理模型会把序列当成一个词袋即使把句子里的词换一下顺序计算出来的表示也完全一样。这对语言理解显然是致命的所以必须引入位置信息。原始 Transformer 使用正弦余弦位置编码公式如下PE(pos, 2i) sin(pos / 10000^(2i / d_model)) PE(pos, 2i1) cos(pos / 10000^(2i / d_model))这个公式的特点是用不同频率的正弦波来表示不同位置。后来很多模型也直接使用可学习的位置 embedding效果差别不大。本文为了代码清晰使用nn.Embedding(max_len, d_model)来实现可学习位置编码。2.4 自注意力机制核心中的核心自注意力机制的作用是让序列中的每个 token 根据自己的“查询”Query去匹配其他 token 的“键”Key然后从“值”Value中提取信息。权重越高说明这个 token 认为另一个 token 对它越重要。单头注意力的计算可以分为 4 步输入 X 分别通过三个线性层得到 Q、K、V。计算 Q 和 K 的点积再除以 sqrt(d_k) 缩放。使用 softmax 把分数转为权重。用权重对 V 求加权和。用公式表示就是Attention(Q, K, V) softmax(Q * K^T / sqrt(d_k)) * V除以 sqrt(d_k) 的原因是当维度很高时点积数值会变得很大softmax 的梯度容易趋向极小值导致训练不稳定。缩放可以把数值拉回到一个合理的区间。2.5 多头注意力从多个视角观察信息单头注意力只能学习一种“关系模式”。但语言中的关系是复杂的比如一个词可能同时和主语、宾语、修饰语产生关系。多头注意力就是把输入投影到多组 Q、K、V每组独立计算注意力最后把结果拼接起来再过一次线性层。例如有 8 个头每个头的维度是 64那么 h8 个头可以分别关注语法关系、指代关系、局部搭配、远距离依赖等不同信息。多头机制显著增强了模型表达能力。2.6 前馈网络FFN与非线性变换多头注意力输出的本质是“带权重的信息聚合”本质上仍是线性变换的组合。为了让模型具备更强的非线性表达能力Transformer 在每个注意力层后接一个逐位置的前馈网络。经典 FFN 包含两个线性层和一个 ReLU 激活FFN(x) max(0, x * W1 b1) * W2 b2通常中间隐藏层维度是d_model的 4 倍。这个模块对每个 token 独立计算不跨 token 交互因此可以很好地并行。2.7 残差连接与 LayerNormTransformer 的另一个关键设计是“残差连接 LayerNorm”。残差连接让梯度可以直接从输出回传到输入避免深层网络出现梯度消失同时也让模型在层数加深时仍然能保持稳定训练。LayerNorm 则负责把每一层的输出归一化到均值为 0、方差为 1 的分布缓解训练过程中的内部协变量偏移。在原始论文中LayerNorm 被放在残差连接之后也就是LayerNorm(x Sublayer(x))。后来很多实现使用 Pre-LN即先归一化再进入子层这种方式在大模型训练中更稳定本文实战部分会采用 Pre-LN。3. 环境准备与项目结构3.1 运行环境本文示例以 Python 3.9 以上版本为例深度学习框架使用 PyTorch。版本不需要完全一致但建议保持较新的版本。如果电脑没有 GPU使用 CPU 也可以跑通只是训练会慢一些。推荐环境如下Python 3.9 PyTorch 2.0 CUDA 11.7如果有 NVIDIA GPU如果没有 GPU可以把训练轮数和数据量调小重点先理解结构和流程。3.2 安装依赖在终端执行以下命令pip install torch numpy如果国内网络下载慢可以增加-i https://pypi.tuna.tsinghua.edu.cn/simple镜像参数。3.3 项目文件结构为方便阅读我们把代码拆成几个文件min_transformer/ |-- data.py # 构造数据集和 token 映射 |-- model.py # Transformer 核心模型 |-- train.py # 训练脚本 |-- generate.py # 文本生成脚本下面从数据准备开始完整实现一个可以运行的字符级 Transformer。4. 实战用 PyTorch 从零实现一个最小 Transformer4.1 准备字符级数据集小规模实验最常见的数据集是《莎士比亚全集》这类英文文本。我们这里为了演示直接用一段小文本作为语料。字符级模型以单个字符为 token好处是词表小、实现简单适合教学。在data.py中实现字符集构建和训练样本切分# 文件路径min_transformer/data.py import torch def build_vocab(text): 根据输入文本构建字符 - id 和 id - 字符 的映射。 chars sorted(list(set(text))) stoi {ch: i for i, ch in enumerate(chars)} itos {i: ch for i, ch in enumerate(chars)} return chars, stoi, itos def encode(text, stoi): 把字符串转换为 id 列表 return [stoi[ch] for ch in text] def decode(ids, itos): 把 id 列表转换为字符串 return .join([itos[i] for i in ids]) def get_batch(data, block_size, batch_size, device): 随机采样一个 batch 的训练数据。 data: 完整文本的 id 列表 block_size: 每个样本的序列长度 ix torch.randint(len(data) - block_size, (batch_size,)) x torch.stack([torch.tensor(data[i:iblock_size]) for i in ix]) y torch.stack([torch.tensor(data[i1:iblock_size1]) for i in ix]) return x.to(device), y.to(device)这里x是输入序列y是目标序列。第 i 个位置的y就是第 i1 个位置的x这正是自回归语言模型的训练方式。4.2 实现缩放点积注意力与多头注意力先写最核心的注意力模块。# 文件路径min_transformer/model.py import torch import torch.nn as nn import torch.nn.functional as F class CausalSelfAttention(nn.Module): 带因果掩码的多头自注意力。 因果掩码保证生成时只能看到当前位置之前的信息。 def __init__(self, d_model, n_head, dropout0.1): super().__init__() assert d_model % n_head 0 self.d_model d_model self.n_head n_head self.head_dim d_model // n_head self.qkv nn.Linear(d_model, 3 * d_model) self.proj nn.Linear(d_model, d_model) self.dropout nn.Dropout(dropout) def forward(self, x): B, T, C x.shape # batch size, 序列长度, 隐藏维度 qkv self.qkv(x) # (B, T, 3*C) q, k, v qkv.chunk(3, dim-1) # 拆分为多头: (B, n_head, T, head_dim) q q.view(B, T, self.n_head, self.head_dim).transpose(1, 2) k k.view(B, T, self.n_head, self.head_dim).transpose(1, 2) v v.view(B, T, self.n_head, self.head_dim).transpose(1, 2) # 缩放点积注意力 att (q k.transpose(-2, -1)) / (self.head_dim ** 0.5) # 因果掩码 mask torch.tril(torch.ones(T, T, devicex.device)).view(1, 1, T, T) att att.masked_fill(mask 0, float(-inf)) att F.softmax(att, dim-1) att self.dropout(att) y att v # (B, n_head, T, head_dim) y y.transpose(1, 2).contiguous().view(B, T, C) return self.proj(y)代码说明qkv.chunk(3, dim-1)把线性层输出切成 Q、K、V 三份这是一种常见的优化写法。mask用torch.tril生成下三角矩阵使第 t 个位置只能关注 0 到 t 的位置。整个计算全部使用矩阵乘法因此可以并行执行。4.3 实现前馈网络与 Transformer Block前馈网络已经介绍过下面是完整实现。# 文件路径min_transformer/model.py class FeedForward(nn.Module): 逐位置前馈网络用 GELU 激活函数。 def __init__(self, d_model, d_ff, dropout0.1): super().__init__() self.fc1 nn.Linear(d_model, d_ff) self.fc2 nn.Linear(d_ff, d_model) self.dropout nn.Dropout(dropout) def forward(self, x): return self.fc2(self.dropout(F.gelu(self.fc1(x)))) class TransformerBlock(nn.Module): 一个完整的 Transformer Decoder 层 注意力 前馈网络 残差连接 LayerNormPre-LN 风格 def __init__(self, d_model, n_head, d_ff, dropout0.1): super().__init__() self.ln1 nn.LayerNorm(d_model) self.attn CausalSelfAttention(d_model, n_head, dropout) self.ln2 nn.LayerNorm(d_model) self.ffn FeedForward(d_model, d_ff, dropout) def forward(self, x): # Pre-LN 结构 x x self.attn(self.ln1(x)) x x self.ffn(self.ln2(x)) return x这里采用 Pre-LN 的原因是在大模型训练中Pre-LN 能让梯度更稳定避免深层堆叠时出现梯度消失问题。虽然原始论文用的是 Post-LN但现代实现普遍倾向 Pre-LN。4.4 组合完整模型有了 Token Embedding、位置编码和 TransformerBlock就可以组装完整的 Decoder-only 模型了。# 文件路径min_transformer/model.py class MinTransformer(nn.Module): 极简 Decoder-only Transformer。 输入 token id 序列输出下一个 token 的 logits。 def __init__(self, vocab_size, d_model128, n_head4, n_layer2, d_ff512, max_len128, dropout0.1): super().__init__() self.token_embedding nn.Embedding(vocab_size, d_model) self.position_embedding nn.Embedding(max_len, d_model) self.blocks nn.Sequential(*[ TransformerBlock(d_model, n_head, d_ff, dropout) for _ in range(n_layer) ]) self.ln_f nn.LayerNorm(d_model) self.lm_head nn.Linear(d_model, vocab_size) def forward(self, idx): B, T idx.shape tok_emb self.token_embedding(idx) # (B, T, d_model) pos torch.arange(T, deviceidx.device).unsqueeze(0) # (1, T) pos_emb self.position_embedding(pos) # (1, T, d_model) x tok_emb pos_emb x self.blocks(x) x self.ln_f(x) logits self.lm_head(x) # (B, T, vocab_size) return logits def generate(self, idx, max_new_tokens, temperature1.0): 自回归生成。 idx: 初始上下文 token id 列表形状 (1, T) for _ in range(max_new_tokens): idx_cond idx[:, -self.position_embedding.num_embeddings:] logits self.forward(idx_cond) # (1, T, vocab_size) logits logits[:, -1, :] / temperature # 只看最后一个位置 probs F.softmax(logits, dim-1) next_token torch.multinomial(probs, num_samples1) idx torch.cat([idx, next_token], dim-1) return idx模型结构说明n_layer控制 Transformer 层数层数越多模型越深但训练难度也越大。max_len是位置编码的最大长度超过这个长度的序列需要截断。generate方法使用torch.multinomial按概率采样因此生成的文本具有多样性。temperature越大输出越随机越接近 0输出越确定。4.5 训练脚本训练过程包含标准的前向传播、损失计算、反向传播和参数更新。# 文件路径min_transformer/train.py import torch import torch.nn as nn from torch.optim import AdamW from data import build_vocab, encode, decode, get_batch from model import MinTransformer # 1. 准备数据 text hello transformer. this is a simple character level language model. the model learns to predict the next character from the previous characters. attention is all you need, but here we build a tiny one. chars, stoi, itos build_vocab(text) vocab_size len(chars) data encode(text, stoi) device cuda if torch.cuda.is_available() else cpu print(f使用设备: {device}, 词表大小: {vocab_size}) # 2. 初始化模型 model MinTransformer( vocab_sizevocab_size, d_model128, n_head4, n_layer2, d_ff512, max_len128, dropout0.1 ).to(device) optimizer AdamW(model.parameters(), lr3e-4) criterion nn.CrossEntropyLoss() batch_size 16 block_size 32 steps 500 # 3. 训练循环 model.train() for step in range(steps): x, y get_batch(data, block_size, batch_size, device) logits model(x) B, T, C logits.shape loss criterion(logits.view(B*T, C), y.view(B*T)) optimizer.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) # 梯度裁剪 optimizer.step() if step % 50 0: print(fstep {step}, loss: {loss.item():.4f}) # 4. 保存模型 torch.save(model.state_dict(), min_transformer.pt) print(训练完成模型已保存。)训练时用了梯度裁剪防止梯度爆炸。对于小模型这保证了训练的稳定性。4.6 文本生成脚本训练完成后我们可以加载模型给定一个起始字符串让它继续生成。# 文件路径min_transformer/generate.py import torch from data import build_vocab, encode, decode from model import MinTransformer # 文本需要和训练时保持一致 text hello transformer. this is a simple character level language model. the model learns to predict the next character from the previous characters. attention is all you need, but here we build a tiny one. chars, stoi, itos build_vocab(text) vocab_size len(chars) model MinTransformer(vocab_sizevocab_size, d_model128, n_head4, n_layer2, d_ff512, max_len128, dropout0.1) model.load_state_dict(torch.load(min_transformer.pt, map_locationcpu)) model.eval() # 给定起始内容 context transformer idx torch.tensor([encode(context, stoi)]).unsqueeze(0) # 形状 (1, 1) 或 (1, len) # 如果 encode 返回 list需要手动转成 (1, T) idx torch.tensor([encode(context, stoi)]) generated model.generate(idx.cpu(), max_new_tokens80, temperature0.8) print(decode(generated[0].tolist(), itos))4.7 运行与预期结果依次执行python train.py python generate.pytrain.py会输出类似内容使用设备: cpu, 词表大小: 27 step 0, loss: 3.2964 step 50, loss: 1.8842 step 100, loss: 1.7321 step 150, loss: 1.6510 step 200, loss: 1.5898 step 250, loss: 1.5333 step 300, loss: 1.4920 step 350, loss: 1.4551 step 400, loss: 1.4267 step 450, loss: 1.4022 训练完成模型已保存。generate.py会输出一个由模型自回归生成的字符串。由于语料很小生成结果不会非常“智能”但你已经可以通过它直观感受注意力机制是如何一步步预测下一个字符的。如果你希望效果更好可以换一个更大的英文语料例如小型莎士比亚文本调大n_layer和d_model并延长steps。同时建议设置随机种子方便复现。4.8 关于注意力可视化在真实项目中我们通常会可视化注意力权重矩阵来观察模型到底关注了哪些 token。这个操作对理解模型非常有效但不是训练过程必须的部分。你可以在每个CausalSelfAttention层里把注意力权重att保存下来然后分析它的分布。5. 常见问题与排查思路从零实现 Transformer 时新手容易遇到下面这些问题。我把它们整理成表格方便遇到报错时快速定位。问题现象常见原因解决思路输入到模型时报维度错误token id 列表没有转换成 (B, T) 的 Tensor使用torch.tensor(...).unsqueeze(0)增加 batch 维度损失不下降或下降很慢学习率过大/过小或没有做梯度裁剪尝试 1e-4 到 3e-4 的 AdamW 学习率并添加梯度裁剪生成结果重复严重序列过长但语料太小或 temperature 过低提高 temperature或增大训练数据量GPU 显存不足序列长度和 batch_size 过大调低 block_size、batch_size或减小 d_model注意力分数为 NaNsoftmax 输入中包含 inf或数据中存在 NaN检查 mask 使用并减少学习率训练速度很慢没有利用 GPU 或模型维度太大torch.cuda.is_available()检查或减小模型位置编码越界输入序列长度超过max_len对输入做截断或扩大max_len其中维度错误是最高频的问题。原因通常是torch.arange(T)生成的 Tensor 没有 batch 维度或者view操作后的形状和预期不一致。排查时可以在模型 forward 函数里打印每个关键张量的.shape。另一个非常隐蔽的问题是位置编码没有.unsqueeze(0)。如果pos形状是(T,)而tok_emb形状是(B, T, d_model)PyTorch 的广播机制会把位置编码的每个位置和 batch 维度的每个样本共享虽然在某些实现里能广播成功但在严格维度检查时容易出现偏差。建议统一处理为(1, T, d_model)。6. 最佳实践与工程建议6.1 模型设计层面优先使用 Pre-LN。原始论文里的 Post-LN 在深层模型和梯度累积场景下更容易出现训练震荡。现代开源大模型大多采用 Pre-LN。注意力头数n_head建议能整除d_model。例如d_model128时可以取n_head4或8每个头的维度是 32 或 16。前馈网络隐藏层d_ff通常取4 * d_model左右。这个比例并非绝对但在大多数模型里都有不错的表现。正则化手段不要堆太多。Dropout、Weight Decay 等策略要相互平衡。小模型可以适当降低 dropout大模型需要更强的正则。6.2 训练层面使用学习率预热Warmup。Transformer 在训练初期对学习率很敏感推荐先让学习率从 0 线性增长到目标值再按余弦或线性衰减。梯度裁剪是标配。设置max_norm1.0可以有效避免梯度爆炸。混合精度训练可以提速。PyTorch 自带torch.cuda.amp或新版torch.amp可以在 GPU 上明显提升训练速度同时减少显存占用。定期保存 checkpoint。训练过程中每隔一定步数保存一次模型方便中断后恢复避免一次训练失败全部重来。6.3 生产与部署层面推理时可以使用 KV Cache 缓存历史注意力结果。在 Decoder 自回归生成时每个新 token 都需要重新计算之前所有 token 的 K、V。KV Cache 可以避免重复计算是 GPT 类模型加速的重要手段。部署大模型要关注显存和延迟。实际部署时可以对模型做量化如 INT8、INT4和蒸馏也可以使用 vLLM、TensorRT-LLM 等推理框架。数据与版权安全。训练或微调模型时要确认数据来源合法符合相关平台和开源协议要求。合法合规使用。涉及模型部署、内容生成、接口调用时务必遵守所在地区和平台的安全要求不传播违法违规内容不绕过安全限制。6.4 从一个小模型走向大模型的路径当你已经能跑通上面的最小 Transformer下一步比较自然的学习路线是替换更大的语料例如 TinyShakespeare、WikiText-2观察训练曲线变化。把单机单卡扩展到多卡训练熟悉DistributedDataParallel和梯度累积。加入 KV Cache改造generate方法提升生成速度。了解 Flash Attention理解它为什么能在不损失精度的前提下大幅减少显存和计算量。尝试微调一个开源大模型例如基于 Hugging Face Transformers 对 Llama、Qwen 做 LoRA 微调。这条路径走完后你对大模型的原理和工程实践都会有一个更完整的认知。7. 总结与学习路线回到开头的问题为什么 Ashish Vaswani 被称作“AI 领域封神的男人”因为他和团队提出的 Transformer 架构以注意力机制为核心彻底替换了循环结构让序列建模可以并行、可以捕捉长距离依赖也为后来 GPT、BERT 等大模型的发展奠定了结构基础。技术世界里一个关键论文改变整个领域走向的例子并不多Transformer 是其中最典型的一个。通过本文你应该已经掌握Transformer 出现之前 RNN/LSTM 的核心瓶颈。自注意力、多头注意力、位置编码、前馈网络、残差连接和 LayerNorm 各自的作用。用 PyTorch 从零编写一个最小 Decoder-only Transformer 的完整流程。训练和生成阶段常见的坑点以及对应的解决方案。从实验模型走向大模型训练与部署的工程建议。如果你现在能顺利运行上面的代码说明你已经跨过了“只会调用现成库”的阶段。接下来可以尝试把语料换大、层数加深或者把模型改成 Encoder-Decoder用来做翻译任务。你会发现很多所谓的“新模型”本质都是在这个基础结构上做改进。想动手的读者建议先改一个最不起眼的参数比如把d_model从 128 改成 256再观察训练时间、显存占用和 loss 下降速度的变化。这种亲手实验带来的理解比单纯看论文要深刻得多。如果这篇文章对你有帮助欢迎收藏备用遇到问题也可以在评论区交流。后续有时间我会继续更新关于 GPT 源码阅读、KV Cache 推导和 LoRA 微调的实战文章。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻