tokenizer special tokens

特殊标记设计:从 [CLS] 到 ChatML 的 Prompt 格式演化

1. 特殊标记的角色与意义 特殊标记(Special Tokens)是 Tokenizer 词表中预留的、具有特定语义功能的标记。它们不属于自然语言,却承担着结构化组织模型输入输出的关键职责。 特殊标记的核心功能: 1. 序列边界标记: [BOS] [EOS] - 标识序列开始/结束 2. 任务分隔标记: [SEP] - 分隔不同输入段 3. 分类聚合标记: [CLS] - 聚合全局语义 4. 填充对齐标记: [PAD] - 批处理中对齐长度 5. 未知词标记: [UNK] - 处理未登录词 6. 掩码标记: [MASK] - 遮蔽语言模型训练 7. 角色标记: <|im_start|> - 标识对话角色 8. 系统标记: <|system|> - 系统指令 1.1 特殊标记的 Token ID 约定 # 不同模型系列的特殊标记 ID 对比 special_token_ids = { "BERT": { "[PAD]": 0, "[UNK]": 1, "[CLS]": 2, "[SEP]": 3, "[MASK]": 103, }, "GPT-2": { "<|endoftext|>": 50256, # 单一结束标记 }, "LLaMA": { "<unk>": 0, "<s>": 1, "</s>": 2, "<pad>": 32000, }, "Llama-3": { "<|begin_of_text|>": 128000, "<|end_of_text|>": 128001, "<|start_header_id|>": 128006, "<|end_header_id|>": 128007, "<|eot_id|>": 128009, }, "ChatML (OpenAI)": { "<|im_start|>": 100264, "<|im_end|>": 100265, "<|endoftext|>": 100257, }, } 2. BERT 时代:分类与分隔 2.1 [CLS] 和 [SEP] 的设计 BERT 使用 [CLS] 和 [SEP] 来组织输入格式: ...

2026-06-25 · 7 min · 1429 words · 硅基 AGI 探索者
speculative decoding explained

投机解码深度解析:LLM 推理速度翻倍的秘密

自回归解码的瓶颈 标准 LLM 推理是自回归的:每次只生成一个 token,然后把它拼回输入再生成下一个。这意味着: # 标准自回归生成 for step in range(max_tokens): # 前向传播:计算整个序列 logits = model(input_ids) # O(N) 计算 next_token = sample(logits[:, -1]) # 只用最后一个位置 input_ids = concat(input_ids, next_token) 问题在于解码阶段的 GPU 利用率极低。即使 batch_size=1,生成单个 token 也需要加载全部模型权重,但只产生 1 个 token 的输出。这就是所谓的 memory-bound(内存带宽瓶颈)。 模型规模 参数量 生成1 token需读取 实际计算量 利用率 7B 7B ~14 GB ~14 GFLOP <5% 70B 70B ~140 GB ~140 GFLOP <3% 405B 405B ~810 GB ~810 GFLOP <2% 核心洞察:大模型推理时,大部分时间花在搬权重,而不是做计算。如果能一次性预测多个 token,就能摊薄权重加载成本。 ...

2026-06-25 · 5 min · 917 words · 硅基 AGI 探索者
positional encoding

位置编码深度解析:从绝对位置到 RoPE 与 ALiBi

1. 为什么需要位置编码 Transformer 的 Self-Attention 机制是置换不变(permutation invariant)的:打乱输入序列的顺序,注意力输出不变。这意味着 Transformer 本身没有序列顺序的概念。 位置编码的使命就是:为模型注入位置信息。 没有位置编码: Attention("猫追狗") == Attention("狗追猫") # 灾难! 有位置编码: Attention("猫追狗") ≠ Attention("狗追猫") # 位置区分了主语和宾语 位置编码的设计需要满足几个理想特性: 唯一性:每个位置应有唯一的编码 相对性:能表达位置间的相对距离 外推性:能处理比训练时更长的序列 周期性:能捕捉位置的模式规律 2. 绝对位置编码 2.1 Sinusoidal(正弦余弦)位置编码 Vaswani 等人 (2017) 提出的正弦余弦位置编码: $$PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d}}\right)$$ $$PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d}}\right)$$ import torch import torch.nn as nn import math class SinusoidalPositionalEncoding(nn.Module): def __init__(self, d_model=512, max_len=5000): super().__init__() pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) # 频率: 1 / (10000^(2i/d)) div_term = torch.exp( torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model) ) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) pe = pe.unsqueeze(0) # (1, max_len, d_model) self.register_buffer('pe', pe) def forward(self, x): # x: (batch, seq_len, d_model) return x + self.pe[:, :x.size(1), :] 关键性质:对于固定的偏移 $k$,$PE_{pos+k}$ 可以表示为 $PE_{pos}$ 的线性函数: ...

2026-06-25 · 8 min · 1683 words · 硅基 AGI 探索者
attention mechanism evolution

注意力机制演进史:从 Bahdanau 到 Flash Attention 3

1. 注意力机制的起源:Bahdanau Attention (2014) 注意力机制的故事始于机器翻译。2014 年,Bahdanau 等人提出了 Additive Attention,解决了 seq2seq 模型中固定长度编码瓶颈的问题。 核心思想:解码器的每一步不再只依赖一个固定的上下文向量,而是"关注"源序列的不同部分。 # Bahdanau Additive Attention 的 PyTorch 实现 class BahdanauAttention(nn.Module): def __init__(self, hidden_size): super().__init__() self.W_query = nn.Linear(hidden_size, hidden_size, bias=False) self.W_key = nn.Linear(hidden_size, hidden_size, bias=False) self.V = nn.Linear(hidden_size, 1, bias=False) def forward(self, query, keys, values): """ query: (batch, hidden) - 解码器当前状态 keys: (batch, src_len, hidden) - 编码器所有隐状态 values: 同 keys """ # 扩展 query 以与 keys 对齐 query_expanded = query.unsqueeze(1) # (batch, 1, hidden) # 加性注意力: score = V^T * tanh(W_q * q + W_k * k) scores = self.V( torch.tanh( self.W_query(query_expanded) + self.W_key(keys) ) ) # (batch, src_len, 1) scores = scores.squeeze(-1) # (batch, src_len) # 注意力权重 attn_weights = F.softmax(scores, dim=-1) # (batch, src_len) # 加权求和 context = torch.bmm(attn_weights.unsqueeze(1), values) # (batch, 1, hidden) context = context.squeeze(1) # (batch, hidden) return context, attn_weights 1.1 Luong Attention (2015) Luong 提出了多种变体,其中 Dot-Product Attention 影响最为深远: ...

2026-06-25 · 7 min · 1453 words · 硅基 AGI 探索者
attention mechanism explained

Attention 机制详解:从 Self-Attention 到 Multi-Query Attention

1. Attention 的本质 Attention 机制的核心思想:给定一个查询(Query),在一系列键值对(Key-Value pairs)中计算相关性权重,然后对值(Value)加权求和,得到输出。 2. Scaled Dot-Product Attention 2.1 公式推导 给定查询矩阵 $Q \in \mathbb{R}^{n \times d_k}$、键矩阵 $K \in \mathbb{R}^{m \times d_k}$、值矩阵 $V \in \mathbb{R}^{m \times d_v}$: $$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$ 为什么要除以 $\sqrt{d_k}$? 当 $d_k$ 较大时,$QK^T$ 的点积值会变大,导致 softmax 梯度趋近于 0(饱和区)。假设 $q$ 和 $k$ 的分量是均值为 0、方差为 1 的独立随机变量,则点积 $q \cdot k = \sum_{i=1}^{d_k} q_i k_i$ 的均值为 0、方差为 $d_k$。除以 $\sqrt{d_k}$ 将方差归一化为 1。 2.2 计算流程 import torch import torch.nn.functional as F import math def scaled_dot_product_attention(Q, K, V, mask=None): """ Q: (batch, n_heads, seq_len, d_k) K: (batch, n_heads, seq_len, d_k) V: (batch, n_heads, seq_len, d_v) """ d_k = Q.size(-1) scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k) if mask is not None: scores = scores.masked_fill(mask == 0, float('-inf')) attn_weights = F.softmax(scores, dim=-1) output = torch.matmul(attn_weights, V) return output, attn_weights 2.3 为什么用点积而不是加性 Attention? 加性 Attention(Bahdanau)计算 $a(q, k) = v^T \tanh(W_q q + W_k k)$,理论表达力更强,但点积 Attention 可以用矩阵乘法高效并行,在实践中速度更快。当 $d_k$ 较小时两者性能接近,$d_k$ 大时点积配合缩放因子更优。 ...

2026-06-25 · 4 min · 662 words · 硅基 AGI 探索者
flash attention 3 guide

Flash Attention 3 指南:GPU IO 优化的终极武器

为什么需要 Flash Attention? 标准 Attention 的瓶颈不在计算,而在显存 IO。考虑 $n = 8192$, $d = 128$ 的注意力计算: 操作 HBM 读写量 SRAM 计算 $S = QK^T$ 读 Q(8MB) + 读 K(8MB) + 写 S(512MB) ~16 GFLOPs $P = \text{softmax}(S)$ 读 S(512MB) + 写 P(512MB) ~8 MFLOPs $O = PV$ 读 P(512MB) + 读 V(8MB) + 写 O(8MB) ~16 GFLOPs 总计 ~1.6 GB ~32 GFLOPs A100 的 HBM 带宽 2 TB/s,SRAM 带宽 19 TB/s。计算只需 ~0.02ms,但 IO 需要 ~0.8ms——IO 是瓶颈的 40 倍。 ...

2026-06-25 · 5 min · 924 words · 硅基 AGI 探索者
layer normalization deep

LayerNorm vs RMSNorm:Transformer 归一化的选择

1. 归一化的必要性 深层神经网络中,各层输入的分布会随训练过程不断变化(Internal Covariate Shift),导致:训练不稳定、梯度消失/爆炸、收敛慢。归一化通过将激活值约束到合理范围来缓解这些问题。 2. Batch Normalization 为何不适用于 NLP? BatchNorm 在 CV 中广泛使用,但在 NLP 中效果差: 变长序列:不同序列长度不同,Batch 维度统计不一致 推理与训练不一致:训练用 batch 统计量,推理用移动平均,序列长度变化时偏差大 batch size 敏感:NLP 训练常用小 batch + 梯度累积,BatchNorm 统计量不可靠 3. Layer Normalization 3.1 公式 对每个样本的每个 Token 独立归一化,沿特征维度计算统计量: $$ \mu = \frac{1}{d} \sum_{i=1}^{d} x_i $$ $$ \sigma^2 = \frac{1}{d} \sum_{i=1}^{d} (x_i - \mu)^2 $$ $$ \hat{x}_i = \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}} $$ $$ y_i = \gamma_i \hat{x}_i + \beta_i $$ ...

2026-06-25 · 3 min · 474 words · 硅基 AGI 探索者
mixture of experts internals

MoE 内部机制:专家路由、负载均衡与容量因子

1. MoE 的核心思想 Mixture-of-Experts(MoE)的核心:条件计算。不是让所有参数都参与每个 Token 的计算,而是为每个 Token 选择少量"专家"子网络来处理。 以 Mixtral 8×7B 为例:总参数 46.7B,但每个 Token 只激活 12.9B。用接近 13B 模型的计算量获得接近 47B 模型的性能。 2. MoE 架构 2.1 基本结构 MoE 替换 Transformer FFN 层: 标准 FFN: x → W2·σ(W1·x) → output MoE FFN: x → Router(x) → 选择 Top-K 专家 → 分别计算 → 加权求和 → output 2.2 路由器(Router/Gate) 路由器是一个小型线性层 + softmax: $$ G(x) = \text{softmax}(W_g x) $$ 其中 $W_g \in \mathbb{R}^{N \times d}$,$N$ 是专家数量。 ...

2026-06-25 · 4 min · 739 words · 硅基 AGI 探索者
ring attention explained

Ring Attention 解析:百万 Token 上下文的秘密

朴素 Attention 的显存墙 标准自注意力的计算: $$\text{Attn}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V$$ 对于序列长度 $n$,中间矩阵 $QK^T$ 的形状为 $n \times n$。当 $n = 1\text{M}$ 时: FP16 显存:$10^6 \times 10^6 \times 2 \text{ bytes} = 2 \text{ TB}$ 即使分块计算,单 GPU 的 HBM(80 GB)也远远不够 朴素方案是序列并行——将序列切分到多个 GPU,但 Softmax 需要全局归约,通信量巨大。 Ring Attention 核心思想 Liu et al. (2023) 提出 Ring Attention:将序列分块分布在多个 GPU 上,以环形拓扑传递 KV 块,与计算重叠。 关键洞察 注意力可以分解为分块计算: $$\text{softmax}(QK^T)V = \frac{\sum_{j} e^{s_j} V_j}{\sum_{j} e^{s_j}}, \quad s_j = QK_j^T$$ 每个 GPU 只需要:本地 Q + 当前 KV 块 → 计算部分 score → 更新 running max 和 running sum。 ...

2026-06-25 · 4 min · 826 words · 硅基 AGI 探索者
tokenizer internals

Tokenizer 原理详解:BPE/WordPiece/Unigram/SentencePiece

1. 为什么 Tokenization 至关重要 LLM 不能直接处理文本,必须将文本切分为离散的 Token 序列,再将每个 Token 映射为向量。Tokenizer 直接影响: 词汇表大小:影响 Embedding 层参数量和 Softmax 计算量 序列长度:同一段文本,不同 Tokenizer 产生的 Token 数不同,影响上下文窗口利用率 多语言公平性:中文一个字 vs 英文一个 word,Tokenizer 决定了编码效率 OOV 问题:未知 Token 的处理能力 2. BPE (Byte Pair Encoding) 2.1 算法思想 BPE 最初是数据压缩算法,被 Sennrich 等人(2016)引入 NLP。核心思路:从一个字符级词汇表开始,反复合并出现频率最高的相邻 Token 对。 2.2 训练过程 输入语料: {"low": 5, "lower": 2, "newest": 6, "widest": 3} 步骤 1: 拆分为字符序列 l o w </w> : 5 l o w e r </w> : 2 n e w e s t </w> : 6 w i d e s t </w> : 3 步骤 2: 统计相邻 Token 对频率 (l, o): 7, (o, w): 7, (e, r): 2, (n, e): 6, ... 步骤 3: 合并最高频对 (l, o) → "lo" lo w </w> : 5 lo w e r </w> : 2 n e w e s t </w> : 6 w i d e s t </w> : 3 重复直到词汇表达到目标大小 2.3 编码过程 对新文本,按训练时的合并规则顺序应用: ...

2026-06-25 · 4 min · 707 words · 硅基 AGI 探索者
鲁ICP备2026018361号