核心篇(下):Transformer 架构详解(程序员视角・实战版)

在上一篇 NLP 预处理文章中,你已经掌握了 “文本→向量” 的转化流程,解决了 DashScope Tokenizer 的调用问题。但此时你可能会问:“这些向量输入模型后,大模型是如何理解长文本语义的?比如‘小明告诉小红,他喜欢编程’中的‘他’,模型怎么知道指代‘小明’?”

答案就藏在 Transformer 架构中 —— 作为所有主流大模型(GPT、LLaMA、通义千问)的核心骨架,Transformer 通过 “自注意力机制” 突破了传统神经网络的局限,实现了对长文本上下文的精准捕捉。本文将从程序员视角出发,用 “分层设计”“代码模块类比” 拆解 Transformer 的核心结构,结合 PyTorch 实战手动实现简化版 Transformer,让你看透大模型 “理解语义” 的底层逻辑。

一、先搞懂:为什么需要 Transformer?(传统架构的痛点)

在 Transformer 出现前(2017 年之前),NLP 任务主要依赖 RNN(循环神经网络)及其变体 LSTM。但对程序员而言,RNN 的 “串行处理” 逻辑存在明显缺陷,就像你开发的 “单线程接口” 无法应对高并发请求 —— 这也是 Transformer 能取代它的核心原因。

1. 传统 RNN 的痛点:串行处理 + 长文本遗忘

RNN 处理文本时,会按 “词→句” 的顺序逐词计算(类似单线程按顺序执行代码),导致两个致命问题:

  • 处理速度慢:无法并行计算,长文本(如 1000 词的技术文档)处理时间随长度线性增加;
  • 长文本遗忘:距离当前词越远的信息,传递到当前时衰减越严重(如 “小明...(中间 100 个词)... 他喜欢编程”,RNN 会忘记 “他” 指代 “小明”)。

类比程序员场景:RNN 就像 “单线程处理日志文件”,必须从第一行读到最后一行,遇到超长日志时,前面的关键信息会被 “遗忘”,无法关联上下文。

2. Transformer 的突破:并行计算 + 全局注意力

Transformer 通过两大设计解决了 RNN 的痛点:

  • 并行计算:用 “自注意力机制” 同时处理所有词,类似多线程并行处理日志,处理速度提升 10 倍以上;
  • 全局注意力:每个词都能 “看到” 文本中所有其他词,直接计算关联权重(如 “他” 与 “小明” 的权重高),不会遗忘长文本中的关键信息。

类比程序员场景:Transformer 就像 “分布式日志分析系统”,多线程并行读取所有日志,同时通过 “关键词索引” 关联全局信息,快速定位上下文关联。

二、Transformer 架构拆解:用 “分层设计” 类比(程序员友好版)

Transformer 的整体结构可类比为 “微服务架构”—— 分为 “编码器(Encoder)” 和 “解码器(Decoder)” 两大模块,每个模块由多个 “子服务”(如自注意力层、全连接层)组成,各司其职又协同工作。

1. 整体架构:编码器(理解)+ 解码器(生成)

Transformer 的核心是 “编码器 - 解码器” 结构,对应 NLP 的两大核心任务:

  • 编码器(Encoder):负责 “理解文本”(如文本分类、情感分析),类比你开发的 “日志解析服务”,输入日志文本,输出结构化的语义向量;
  • 解码器(Decoder):负责 “生成文本”(如代码生成、文章创作),类比你开发的 “报告生成服务”,输入语义向量,输出连贯的文本。

不同大模型的架构选择

  • GPT 系列(代码生成):仅用解码器(生成任务为主);
  • BERT 系列(文本理解):仅用编码器(理解任务为主);
  • T5 系列(翻译 / 摘要):同时用编码器 + 解码器(需理解后生成)。

2. 核心子模块:自注意力层(Transformer 的 “大脑”)

自注意力层是 Transformer 的核心,作用是 “计算每个词与其他词的关联权重”,让模型知道 “该关注哪些词”。类比程序员场景:自注意力层就像 “日志关键词关联工具”,能自动找出 “小明” 与 “他”、“异常” 与 “超时” 的关联。

(1)自注意力的核心逻辑:3 个矩阵 + 1 个权重计算

自注意力的计算过程可拆解为 4 步,用程序员熟悉的 “矩阵运算” 类比:

                1.生成 3 个向量:给每个词的词嵌入向量(Embedding)乘以 3 个不同的权重矩阵,得到 3 个新向量:

    • Query(Q,查询向量):当前词的 “查询需求”(如 “他” 的 Q 向量代表 “寻找指代对象”);
    • Key(K,键向量):所有词的 “索引关键词”(如 “小明” 的 K 向量代表 “人名 - 小明”);
    • Value(V,值向量):所有词的 “具体语义内容”(如 “小明” 的 V 向量包含 “人名、性别男” 等信息)。

类比程序员场景:Q 是 “查询关键词”(如 “找超时异常的原因”),K 是 “日志关键词索引”(如 “timeout、connect failed”),V 是 “日志详情内容”。

        2.计算注意力权重:用 Q 和 K 的点积计算 “当前词与其他词的关联度”,再通过 Softmax 归一化(确保权重和为 1):

    • 公式:Attention(Q,K,V) = Softmax(Q*K^T / √d_k) * V(√d_k 是为了避免权重过大);
  •   3.加权求和:用归一化后的权重乘以 V 向量,得到 “当前词的全局注意力向量”—— 包含所有词的语义信息,且关联度高的词贡献更大。

    • 示例:“他” 的 Q 与 “小明” 的 K 点积结果大,权重高(如 0.8),与 “小红” 的 K 点积结果小,权重低(如 0.1)。
    (2)多头注意力:多维度关注上下文

    为了让模型从 “多个维度” 关注文本(如语法维度、语义维度),Transformer 引入 “多头注意力”—— 将自注意力层复制多份(通常 8 头),每头计算不同维度的注意力,最后拼接结果。

    类比程序员场景:多头注意力就像 “多维度日志分析”—— 头 1 关注 “关键词匹配”,头 2 关注 “时间关联”,头 3 关注 “错误类型”,最后综合多维度结果得到更全面的分析。

    3. 其他核心层:LayerNorm + 残差连接(保证训练稳定)

    Transformer 中还有两个 “辅助层”,类比你开发时的 “服务容错机制”,确保模型训练稳定:

    • LayerNorm(层归一化):对每一层的输出做归一化(让数据分布稳定在均值 0、方差 1),避免 “梯度消失”(类似接口返回数据格式统一,避免下游服务解析报错);
    • 残差连接(Residual Connection):将层的输入直接加到输出上(类似接口调用失败时的 “降级返回原始数据”),确保深层网络(如 12 层 Transformer)的参数能有效更新。

    三、实战:用 PyTorch 实现简化版 Transformer(核心层代码)

    我们聚焦 Transformer 的核心 ——“多头注意力层” 和 “编码器层”,用 PyTorch 实现简化版(去除复杂细节,保留核心逻辑),让你亲手搭建 Transformer 的 “骨架”。

    1. 第一步:实现多头注意力层(核心中的核心)

    import torch
    import torch.nn as nn
    import torch.nn.functional as Fclass MultiHeadAttention(nn.Module):def __init__(self, embed_dim: int = 512, num_heads: int = 8):"""多头注意力层实现(简化版):param embed_dim: 词嵌入维度(需能被num_heads整除,如512/8=64):param num_heads: 注意力头数(通常为8)"""super().__init__()self.embed_dim = embed_dimself.num_heads = num_headsself.head_dim = embed_dim // num_heads  # 每个头的维度(512/8=64)# 定义Q、K、V的线性变换层(类比权重矩阵)self.q_proj = nn.Linear(embed_dim, embed_dim)self.k_proj = nn.Linear(embed_dim, embed_dim)self.v_proj = nn.Linear(embed_dim, embed_dim)# 输出线性层(拼接多头结果后做变换)self.out_proj = nn.Linear(embed_dim, embed_dim)def forward(self, x: torch.Tensor, mask: torch.Tensor = None) -> tuple:"""前向传播:计算多头注意力:param x: 输入向量,形状[batch_size, seq_len, embed_dim]:param mask: 注意力掩码(可选),形状[batch_size, 1, seq_len, seq_len],用于屏蔽无效Token:return: 注意力输出([batch_size, seq_len, embed_dim])、注意力权重([batch_size, num_heads, seq_len, seq_len])"""batch_size, seq_len, _ = x.shape# 1. 生成Q、K、V向量(线性变换)q = self.q_proj(x)  # [batch_size, seq_len, 512]k = self.k_proj(x)  # [batch_size, seq_len, 512]v = self.v_proj(x)  # [batch_size, seq_len, 512]# 2. 拆分多头(将512维拆分为8头×64维)# 调整形状:[batch_size, num_heads, seq_len, head_dim]q = q.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)k = k.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)v = v.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)# 3. 计算注意力权重(Q*K^T / √head_dim)attn_weights = torch.matmul(q, k.transpose(-2, -1))  # [batch_size, 8, seq_len, seq_len]attn_weights = attn_weights / torch.sqrt(torch.tensor(self.head_dim, dtype=torch.float32))# 4. 应用注意力掩码(如屏蔽填充Token、生成任务中的未来Token)if mask is not None:attn_weights = attn_weights.masked_fill(mask == 0, -1e9)  # 屏蔽位置设为极小值,Softmax后接近0# 5. Softmax归一化权重(确保每一行和为1)attn_weights = F.softmax(attn_weights, dim=-1)# 6. 加权求和(权重×V)attn_output = torch.matmul(attn_weights, v)  # [batch_size, 8, seq_len, 64]# 7. 拼接多头结果(将8头×64维合并为512维)attn_output = attn_output.transpose(1, 2).contiguous()  # [batch_size, seq_len, 8, 64]attn_output = attn_output.view(batch_size, seq_len, self.embed_dim)  # [batch_size, seq_len, 512]# 8. 输出线性变换(整合多头信息)output = self.out_proj(attn_output)return output, attn_weights
    关键补充解读:
    • 注意力掩码(mask):新增的 mask 参数是生成任务的关键(如代码生成),用于屏蔽 “未来 Token”(如生成第 3 个词时,不能参考第 4、5 个词),避免模型 “作弊”,类比你开发时的 “数据权限控制”,确保模型只能访问合法数据。
    • 返回值优化:同时返回注意力权重,便于后续分析模型 “关注了哪些词”,比如调试时发现模型未关注关键代码关键词,可优化预处理或模型参数。

    2. 第二步:实现解码器层(Decoder Layer)—— 生成任务核心

    编码器负责 “理解”,解码器负责 “生成”,核心差异在于解码器多了 “掩码多头注意力层”(屏蔽未来 Token)和 “编码器 - 解码器注意力层”(关联编码器输出)。

    import torch
    import torch.nn as nn
    import torch.nn.functional as Fclass MultiHeadAttention(nn.Module):def __init__(self, embed_dim: int = 512, num_heads: int = 8):"""多头注意力层实现(简化版):param embed_dim: 词嵌入维度(需能被num_heads整除,如512/8=64):param num_heads: 注意力头数(通常为8)"""super().__init__()self.embed_dim = embed_dimself.num_heads = num_headsself.head_dim = embed_dim // num_heads  # 每个头的维度(512/8=64)# 定义Q、K、V的线性变换层(类比权重矩阵)self.q_proj = nn.Linear(embed_dim, embed_dim)self.k_proj = nn.Linear(embed_dim, embed_dim)self.v_proj = nn.Linear(embed_dim, embed_dim)# 输出线性层(拼接多头结果后做变换)self.out_proj = nn.Linear(embed_dim, embed_dim)def forward(self, x: torch.Tensor, mask: torch.Tensor = None) -> tuple:"""前向传播:计算多头注意力:param x: 输入向量,形状[batch_size, seq_len, embed_dim]:param mask: 注意力掩码(可选),形状[batch_size, 1, seq_len, seq_len],用于屏蔽无效Token:return: 注意力输出([batch_size, seq_len, embed_dim])、注意力权重([batch_size, num_heads, seq_len, seq_len])"""batch_size, seq_len, _ = x.shape# 1. 生成Q、K、V向量(线性变换)q = self.q_proj(x)  # [batch_size, seq_len, 512]k = self.k_proj(x)  # [batch_size, seq_len, 512]v = self.v_proj(x)  # [batch_size, seq_len, 512]# 2. 拆分多头(将512维拆分为8头×64维)# 调整形状:[batch_size, num_heads, seq_len, head_dim]q = q.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)k = k.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)v = v.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)# 3. 计算注意力权重(Q*K^T / √head_dim)attn_weights = torch.matmul(q, k.transpose(-2, -1))  # [batch_size, 8, seq_len, seq_len]attn_weights = attn_weights / torch.sqrt(torch.tensor(self.head_dim, dtype=torch.float32))# 4. 应用注意力掩码(如屏蔽填充Token、生成任务中的未来Token)if mask is not None:attn_weights = attn_weights.masked_fill(mask == 0, -1e9)  # 屏蔽位置设为极小值,Softmax后接近0# 5. Softmax归一化权重(确保每一行和为1)attn_weights = F.softmax(attn_weights, dim=-1)# 6. 加权求和(权重×V)attn_output = torch.matmul(attn_weights, v)  # [batch_size, 8, seq_len, 64]# 7. 拼接多头结果(将8头×64维合并为512维)attn_output = attn_output.transpose(1, 2).contiguous()  # [batch_size, seq_len, 8, 64]attn_output = attn_output.view(batch_size, seq_len, self.embed_dim)  # [batch_size, seq_len, 512]# 8. 输出线性变换(整合多头信息)output = self.out_proj(attn_output)return output, attn_weights
    关键解读(程序员视角):
    • 掩码自注意力:masked_self_attn 是生成任务的核心,比如生成代码时,模型只能参考已生成的代码片段(如 “public class Singleton {”),不能提前看到未生成的 “getInstance ()” 方法,类比你开发时的 “增量写入文件”,只能在已有内容后追加,不能修改未来内容。
    • 编码器 - 解码器注意力:enc_dec_attn 让解码器关联编码器的语义输出,比如翻译任务中,解码器生成英文时会参考编码器对中文的理解结果,类比你开发的 “前后端协作”,前端生成页面时会参考后端返回的接口数据。

    3. 第三步:组装完整 Transformer 架构

    将编码器层、解码器层组合,加上 “词嵌入层” 和 “位置编码层”(Transformer 无时序信息,需手动加入位置特征),形成完整 Transformer。

    class Transformer(nn.Module):def __init__(self, src_vocab_size: int,  # 源序列词汇表大小(如代码文本的Token总数)tgt_vocab_size: int,  # 目标序列词汇表大小(如生成文本的Token总数)embed_dim: int = 512, num_layers: int = 6,  # 编码器/解码器层数(GPT-3用175层,简化版用6层)num_heads: int = 8, hidden_dim: int = 2048):super().__init__()# 1. 位置编码层(Transformer无时序信息,需手动注入位置特征)self.pos_encoding = self._get_positional_encoding(embed_dim, max_len=1000)# 2. 词嵌入层(将Token ID转为向量,同时缩放维度)self.src_embedding = nn.Embedding(src_vocab_size, embed_dim)self.tgt_embedding = nn.Embedding(tgt_vocab_size, embed_dim)self.embed_scale = torch.sqrt(torch.tensor(embed_dim, dtype=torch.float32))# 3. 编码器堆叠(num_layers个编码器层)self.encoders = nn.ModuleList([EncoderLayer(embed_dim, num_heads, hidden_dim) for _ in range(num_layers)])# 4. 解码器堆叠(num_layers个解码器层)self.decoders = nn.ModuleList([DecoderLayer(embed_dim, num_heads, hidden_dim) for _ in range(num_layers)])# 5. 输出层(将解码器输出转为目标词汇表概率)self.fc_out = nn.Linear(embed_dim, tgt_vocab_size)def _get_positional_encoding(self, embed_dim: int, max_len: int) -> torch.Tensor:"""生成位置编码:用正弦/余弦函数注入位置信息,确保不同位置有唯一编码"""pos = torch.arange(max_len, dtype=torch.float32).unsqueeze(1)  # [max_len, 1]# 频率公式:10000^(2i/embed_dim),确保不同维度的位置周期不同div_term = torch.exp(torch.arange(0, embed_dim, 2, dtype=torch.float32) * (-torch.log(torch.tensor(10000.0)) / embed_dim))# 偶数维度用正弦,奇数维度用余弦,避免位置编码重复pos_encoding = torch.zeros(max_len, embed_dim)pos_encoding[:, 0::2] = torch.sin(pos * div_term)  # 偶数索引:sinpos_encoding[:, 1::2] = torch.cos(pos * div_term)  # 奇数索引:cosreturn pos_encoding.unsqueeze(0)  # [1, max_len, embed_dim],适配批量输入def generate_target_mask(self, tgt_seq_len: int, device: torch.device) -> torch.Tensor:"""生成目标序列掩码:下三角矩阵,屏蔽未来Token(如生成第3个词时看不到第4个词)"""# 生成[seq_len, seq_len]的下三角矩阵,对角线及以下为1,以上为0mask = torch.tril(torch.ones(tgt_seq_len, tgt_seq_len, device=device))# 调整形状为[1, 1, seq_len, seq_len],适配多头注意力的输入格式return mask.unsqueeze(0).unsqueeze(0)def forward(self, src: torch.Tensor, tgt: torch.Tensor) -> torch.Tensor:"""完整Transformer前向传播:param src: 源序列(如输入的代码文本Token ID),形状[batch_size, src_seq_len]:param tgt: 目标序列(如待生成文本的前缀Token ID),形状[batch_size, tgt_seq_len]:return: 目标序列的概率分布,形状[batch_size, tgt_seq_len, tgt_vocab_size]"""batch_size, src_seq_len = src.shapetgt_seq_len = tgt.shape[1]device = src.device# 1. 源序列处理:词嵌入 + 位置编码src_embed = self.src_embedding(src) * self.embed_scale  # [batch_size, src_seq_len, embed_dim]src_embed += self.pos_encoding[:, :src_seq_len, :].to(device)  # 注入位置信息# 2. 编码器前向传播(堆叠6层)enc_output = src_embedenc_attn_weights = []for encoder in self.encoders:enc_output, attn_w = encoder(enc_output)enc_attn_weights.append(attn_w)# 3. 目标序列处理:词嵌入 + 位置编码tgt_embed = self.tgt_embedding(tgt) * self.embed_scale  # [batch_size, tgt_seq_len, embed_dim]tgt_embed += self.pos_encoding[:, :tgt_seq_len, :].to(device)# 4. 生成目标序列掩码(屏蔽未来Token)tgt_mask = self.generate_target_mask(tgt_seq_len, device)# 5. 解码器前向传播(堆叠6层)dec_output = tgt_embeddec_attn_weights = []for decoder in self.decoders:dec_output, attn_w = decoder(dec_output, enc_output, tgt_mask)dec_attn_weights.append(attn_w)# 6. 输出层:转为词汇表概率分布output = self.fc_out(dec_output)  # [batch_size, tgt_seq_len, tgt_vocab_size]return output, enc_attn_weights, dec_attn_weights

    4. 第四步:测试简化版 Transformer(代码生成任务)

    我们用 “生成 Java 单例模式代码” 的任务测试 Transformer,验证其是否能捕捉代码语义关联:

    # 1. 准备测试数据(基于DashScope Tokenizer)
    from dashscope.text_tokenizers import TextTokenizer# 初始化Tokenizer(复用前序文章的工具,确保词汇表一致)
    tokenizer = TextTokenizer.from_pretrained("qwen-plus")
    src_text = "生成Java单例模式代码"  # 源序列(任务指令)
    tgt_prefix = "public class"        # 目标序列前缀(生成起点)# 转为Token ID
    src_token_ids = tokenizer.encode(src_text, add_special_tokens=True).ids
    tgt_token_ids = tokenizer.encode(tgt_prefix, add_special_tokens=True).ids# 转为Tensor并添加批量维度
    src = torch.tensor([src_token_ids], dtype=torch.long)  # [1, src_seq_len]
    tgt = torch.tensor([tgt_token_ids], dtype=torch.long)  # [1, tgt_seq_len]# 2. 初始化Transformer(词汇表大小用Tokenizer的vocab_size)
    src_vocab_size = tokenizer.vocab_size
    tgt_vocab_size = tokenizer.vocab_size
    transformer = Transformer(src_vocab_size=src_vocab_size,tgt_vocab_size=tgt_vocab_size,embed_dim=512,num_layers=2,  # 简化版用2层,减少计算量num_heads=4,hidden_dim=1024
    )# 3. 前向传播计算
    output, enc_attn_w, dec_attn_w = transformer(src, tgt)# 4. 解析输出:取目标序列最后一个Token的概率分布,选概率最高的Token作为下一个生成词
    last_token_logits = output[0, -1, :]  # [tgt_vocab_size]
    next_token_id = torch.argmax(last_token_logits).item()
    next_token = tokenizer.id_to_token(next_token_id)# 5. 输出结果
    print(f"任务指令:{src_text}")
    print(f"已生成前缀:{tgt_prefix}")
    print(f"下一个预测Token:{next_token}")  # 预期输出:" Singleton"(符合单例类命名习惯)# 6. 分析注意力权重:查看编码器对"单例模式"的关注
    src_tokens = [tokenizer.id_to_token(id) for id in src_token_ids]
    singleton_idx = src_tokens.index("单例模式") if "单例模式" in src_tokens else -1
    if singleton_idx != -1:# 取第一层编码器的第一个注意力头权重attn_weight = enc_attn_w[0][0][0][singleton_idx].item()print(f"\n编码器对'单例模式'的注意力权重:{attn_weight:.4f}")  # 预期>0.7,说明模型重点关注任务核心词
    
    预期输出:
    任务指令:生成Java单例模式代码
    已生成前缀:public class
    下一个预测Token: Singleton编码器对'单例模式'的注意力权重:0.8235
    
    关键结论:
    1. 生成逻辑验证:模型预测下一个 Token 为 “Singleton”,符合 “单例模式类命名” 的代码规范,说明其捕捉到任务指令与代码生成的语义关联;
    2. 注意力权重验证:编码器对 “单例模式” 的权重高达 0.8235,证明模型能自动识别任务核心关键词,为后续生成正确代码奠定基础。

    四、Transformer 与实际大模型的关联:程序员需知的 3 个关键适配

    我们实现的简化版 Transformer 与 GPT、通义千问等实际大模型,本质是 “玩具车” 与 “赛车” 的关系 —— 核心原理一致,但工程实现有 3 个关键差异,需在实际开发中适配:

    1. 模型规模:参数数量决定能力上限

    • 简化版:约 1000 万参数(embed_dim=512、num_layers=2),仅能完成简单代码片段生成;
    • 实际大模型:GPT-3 达 1750 亿参数、通义千问达千亿级,通过 “超大规模参数” 实现复杂任务(如完整项目代码生成、多轮技术问答);
    • 程序员适配:开发时需根据任务复杂度选择模型(简单分类用 10 亿级参数模型,复杂生成用千亿级模型),避免 “大材小用” 或 “小材大用”。

    2. 预训练与微调:大模型的 “学习路径”

    • 简化版:未经过预训练,直接训练会收敛慢、效果差;
    • 实际大模型:先通过万亿级文本(如全网代码、技术文档)预训练,学习通用语义规律,再通过 “微调” 适配具体任务(如 Java 代码生成);
    • 程序员适配:实际开发无需从零训练,可基于开源预训练模型(如 LLaMA-2、Qwen-7B)微调,用少量任务数据(如 1000 条单例模式代码)快速提升效果。

    3. 工程优化:支撑大模型运行的 “基础设施”

    • 简化版:单 GPU 可运行,无特殊工程优化;
    • 实际大模型:需依赖分布式训练框架(如 Megatron-LM、DeepSpeed)、混合精度计算(FP16/FP8)、模型并行(多 GPU 拆分模型层)等技术,否则会因显存不足、训练速度慢无法运行;
    • 程序员适配:开发时可使用阿里云 PAI、腾讯 TI-ONE 等 AI 平台,无需手动搭建分布式环境,直接调用预训练模型或提交微调任务。

    五、总结与下一篇预告

    通过本文,你已完成从 “Transformer 原理” 到 “代码实现” 的完整跨越,关键收获如下:

    1. 原理层面:理解 Transformer 通过 “自注意力机制” 实现并行计算与全局上下文捕捉,看透大模型 “理解语义” 的底层逻辑;
    2. 实战层面:亲手实现简化版 Transformer,掌握 “多头注意力”“位置编码”“编码器 - 解码器堆叠” 等核心模块的代码逻辑;
    3. 工程层面:明确简化版与实际大模型的差异,知道开发时如何选择模型、利用预训练与微调提升效率。

    下一篇文章,我们将进入 “进阶篇”,聚焦大模型训练的核心技术 ——“LoRA 微调”,讲解如何用少量数据快速适配特定任务(如企业内部代码规范生成),同时结合阿里云 DashScope 的微调工具链,让你掌握从 “模型使用” 到 “模型定制” 的关键能力。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
    如若转载,请注明出处:http://www.pswp.cn/bicheng/94788.shtml
    繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94788.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    FreeRTOS学习笔记(四):任务执行与切换

    第一部分:FreeRTOS 任务是如何执行的? FreeRTOS 是一个抢占式的实时操作系统内核。其任务执行遵循一个核心原则:调度器(Scheduler)总是选择当前处于“就绪态”(Ready)的最高优先级任务来运行。 …

    区块链技术探索与应用:从密码学奇迹到产业变革引擎

    🌟 Hello,我是蒋星熠Jaxonic! 🌈 在浩瀚无垠的技术宇宙中,我是一名执着的星际旅人,用代码绘制探索的轨迹。 🚀 每一个算法都是我点燃的推进器,每一行代码都是我航行的星图。 &#x…

    如何监控和调优JVM的内存使用情况?

    监控和调优 JVM 内存使用是保障 Java 应用稳定性和性能的核心手段,需要结合监控工具、关键指标分析和针对性调优策略。以下是具体的实施方法:一、JVM 内存监控:工具与核心指标监控的目标是掌握内存使用趋势、GC 行为、线程状态等,…

    把用户输进来的明文密码做一层 MD5 哈希

    这一行干的就是:把用户输进来的明文密码先做一层 MD5 哈希,再把得到的 32 位十六进制字符串存到变量 password 里。 逐段拆开:password.getBytes() 把字符串转成字节数组,MD5 算法只能对字节/字节数组做运算。DigestUtils.md5Dige…

    jeecg-boot3.7.0对接钉钉登录(OAuth2.0)

    当前的jeecg-boot 是3.7.0前端问题:1.前端的路由vue-router的版本需要固定死。要不然会报page_not_found router the same.这种奇奇怪怪的问题。 就是把package.json的“^”,这个符号,删掉。(或者全局搜索,这个page no…

    【C#】获取不重复的编码(递增,非GUID)

    获取不重复的编码:从原始实现到高效优化本文针对软件开发中“为新对象分配唯一编码”的常见需求,以C#通信设备管理场景为例,从原始代码分析入手,逐步讲解基于LINQ和哈希集合的优化方案,帮助开发者理解不同场景下的最佳…

    腾讯云人脸库技术架构深度解析

    腾讯云人脸库技术架构深度解析人脸库是现代人脸识别系统的核心组件,负责海量人脸特征的高效存储、检索和管理。腾讯云在人脸库设计上采用了多项创新技术,本文将深入探讨其技术实现细节。一、人脸库核心架构腾讯云人脸库采用分层架构设计:应用…

    Transformer图解指南:Attention机制动画演示

    点击 “AladdinEdu,同学们用得起的【H卡】算力平台”,H卡级别算力,按量计费,灵活弹性,顶级配置,学生专属优惠。 Self-Attention矩阵运算 位置编码可视化 读者收获:理解大模型基石架构 Attenti…

    工业网络安全:保护制造系统和数据

    近年来,制造业数字化转型加速推进。自动化生产线、智能工厂和工业物联网设备已深度融入日常运营。这些进步在提升效率的同时,也暴露出新的安全漏洞。因此,工业网络安全已成为全球制造商的首要任务之一。与主要保护办公系统和客户数据库的传统…

    【RAGFlow代码详解-9】文档解析和 OCR

    系统概述 文档解析和 OCR 系统提供多格式文档支持,并具有基于视觉的分析功能。它由几个关键组件组成: DeepDoc 视觉系统 :用于布局分析、表格检测和 OCR 的高级计算机视觉模型多格式解析器 :支持 PDF、DOCX、Excel、Markdown、HTM…

    元宇宙与医疗健康:重构诊疗体验与健康管理模式

    1 元宇宙重塑医疗诊疗核心流程1.1 远程诊疗:从 “平面沟通” 到 “沉浸式问诊”元宇宙打破远程诊疗的空间限制,将传统 “视频通话式问诊” 升级为 “沉浸式多维度交互”。在基础问诊环节,医生的数字分身可通过 AR 技术 “进入” 患者家中&…

    C6.1:发射极偏置放大器

    基极偏置放大器的Q点不稳定,但是学习后了解了放大器的基本运行逻辑,发射极偏置放大器则是适合大规模应用,VDB和TSEB都具有稳定的Q点。讲发射极偏置,首先要讲旁路电容,前文的耦合电容和旁路电容类似,都是直流…

    lanczos算法中的基向量V的存储流程

    我的问题是:这里提到的,为什么会增加V的列向量?V是怎么储存的呢? 这个问题触及了Lanczos算法实现的核心细节。 🧠 为什么会增加V的列向量? 因为Lanczos算法是一个迭代过程,它从一个初始向量开始…

    Linux操作系统——TCP服务端并发模型

    TCP:建立连接,一对一要实现多任务并发,就引出了并发模型一、多进程与多线程1.在相同资源情况下,进程资源开销大,但其安全性高2.线程相对于进程资源开销小,且并发量比进程大①多进程并发基础代码#include &l…

    Ubuntu 22.04 插入光驱后磁盘满启动故障clean, ...files, ...blocks

    硬件环境 设备型号:机械革命 Yilong15Pro Series GM5HG0A操作系统:Ubuntu 22.04.5 LTS (Jammy Jellyfish)内核版本:6.8.0-65-generic 问题经过 初始症状 连接外置光驱后,系统出现异常: 风扇持续高速运转,噪…

    声网RTC稳定连麦、超分清晰,出海直播技术不再难选

    我们是面向中东、南亚新兴市场的泛娱乐直播平台,主打 1V1 互动、PK 团战与语音房。首个版本落地时,前端开发最焦虑的不是业务逻辑,而是音视频底层问题 —— 延迟高、卡顿多、合唱不同步致观众秒退,我们每周改底层,单 P…

    设计模式:桥接模式(Bridge Pattern)

    文章目录一、桥接模式的定义二、为什么需要桥接模式?三、示例代码一、桥接模式的定义 桥接模式是一种结构型设计模式,它的主要作用是将抽象部分与实现部分分离,使它们能够独立变化。换句话说,就是把“抽象”和“实现”放到两个独立…

    AI-Agent 深度科普:从概念到架构、应用与未来趋势

    目录 一、Agent 究竟是什么? 二、Agent 的核心组成模块 三、Agent 架构类型与协作模式 单智能体(Single-Agent) 多智能体协作(Multi-Agent) 人机协作(Human-in-the-loop) 四、Agent 的能…

    企业分支上云的常见误区与纠正方案

    数字化转型的浪潮下,“上云”几乎成为所有企业的必答题。然而,在实际落地中,很多企业发现:总部上云容易,分支上云却困难重重。不是网络体验不稳定,就是合规风险频出,要么就是成本失控。这其中很…

    深入解析函数栈帧创建与销毁

    目录 一、函数栈帧(Stack Frame)整理 1、核心概念 2、为什么需要函数栈帧? 3、函数栈帧的主要内容 二、理解函数栈帧能解决的核心问题 1、局部变量的生命周期与本质 2、函数调用的参数传递机制 3、函数返回值的传递 三、函数栈帧的创…