嵌入层优化

嵌入层优化:从查找到计算

嵌入层:被忽视的显存大户 在LLM中,嵌入层(Embedding Layer)往往是被忽视的显存消耗者。以Llama-3为例,词表大小128K、隐藏维度4096、FP16精度下,嵌入层参数量为 128K × 4096 × 2 = 1GB。对于更大的词表(如Qwen的152K),嵌入层可达1.5GB以上。 在70B模型中,嵌入层占总参数量的约2%,但在推理时它还需要一个等大的输出投影层(LM Head),两者合计占4%——这还不算小。 标准嵌入层 查找表 标准嵌入层是一个简单的查找表——词表中的每个token对应一个可学习的向量: class StandardEmbedding(nn.Module): def __init__(self, vocab_size, d_model): super().__init__() self.weight = nn.Parameter(torch.randn(vocab_size, d_model)) def forward(self, input_ids): # 简单的索引查找 return self.weight[input_ids] # [batch, seq_len, d_model] 权重共享 许多LLM共享嵌入层和输出层的权重(Weight Tying): class SharedEmbeddingModel(nn.Module): def __init__(self, vocab_size, d_model): super().__init__() self.embedding = nn.Embedding(vocab_size, d_model) # 输出层直接使用嵌入矩阵的转置 # 不需要额外的参数 def forward(self, input_ids): x = self.embedding(input_ids) x = self.transformer(x) # 输出logits = x @ embedding.weight.T logits = F.linear(x, self.embedding.weight) return logits 权重共享的好处: 减少参数量(节省1GB+显存) 输入和输出在同一个语义空间中 训练时梯度信号更强 但也有研究指出,权重共享可能导致冲突——输入嵌入需要捕捉"词的语义",输出层需要捕捉"词的预测概率分布",两者的最优表示可能不同。 嵌入层压缩 矩阵分解 将大的嵌入矩阵分解为两个小矩阵的乘积: class FactorizedEmbedding(nn.Module): def __init__(self, vocab_size, d_model, d_factor): """ d_factor: 分解后的中间维度 """ super().__init__() # V × D → V × d_factor × d_factor × D self.factor1 = nn.Parameter(torch.randn(vocab_size, d_factor)) self.factor2 = nn.Parameter(torch.randn(d_factor, d_model)) def forward(self, input_ids): # 查找低维因子,然后投影到高维 low_dim = self.factor1[input_ids] # [batch, seq, d_factor] return low_dim @ self.factor2 # [batch, seq, d_model] 参数量从 V×D 降低到 V×d + d×D。当 D=4096、d=256、V=128K 时,参数量减少约16倍。 ...

2026-07-02 · 3 min · 562 words · 硅基 AGI 探索者
fine tuning vs prompt

微调 vs Prompt 工程:何时该选哪个?

核心问题 “我应该用 Prompt 工程还是微调?“答案是:取决于瓶颈在哪。 模型理解能力不足 → 微调 上下文信息不足 → RAG / Prompt 工程 输出格式不稳定 → Prompt 工程(或少量微调) 领域知识缺失 → RAG(而非微调) Prompt 工程的能力边界 能做什么 # 1. 角色设定和行为控制 SYSTEM_PROMPT = "你是专业法律顾问,仅基于提供的条文回答" # 2. 输出格式控制 FORMAT_PROMPT = '输出JSON: {"risk_level":"high|medium|low", "factors":[]}' # 3. 少样本学习 FEW_SHOT = "示例:\n输入:订单没到\n输出:{\"intent\":\"logistics\"}\n现在处理:{input}" # 4. 思维链推理 COT = "请一步步思考:首先分析...然后...最后..." 天花板 # 解决不了的问题: # 1. 风格深度定制 — 需要大量token示例,成本高且不稳定 style_prompt = "请模仿以下风格(附10000字示例)..." # token成本爆炸 # 2. 领域术语理解 — Prompt过长,模型注意力分散 medical_prompt = "医学缩写对照表(500个)..." # 效果差 # 3. 复杂工具调用模式 — 规则太多时遵循率下降 tool_prompt = "调用工具的50条注意事项..." # 遵循率低 微调的适用场景 场景一:风格和格式定制 # 微调数据:客服风格定制 training_data = [ {"messages": [ {"role": "system", "content": "你是XX品牌客服"}, {"role": "user", "content": "你们的东西太贵了"}, {"role": "assistant", "content": "理解您的感受~我们坚持品质路线,现有新人9折优惠😊"}, ]}, # 500-1000条这样的数据 ] # 微调后:无需长Prompt,模型自然使用品牌语气 场景二:降低推理成本 # 微调前:GPT-4o + 2000 token system prompt → $0.017/请求 # 微调后:GPT-4o-mini fine-tuned → $0.0015/请求 # 成本降低91%,回本周期约0.5个月 # 蒸馏:用GPT-4生成数据训练小模型 distillation_data = [] for input_text in training_inputs: gpt4_output = await gpt4.generate(input_text, system_prompt=LONG_PROMPT) distillation_data.append({"input": input_text, "output": gpt4_output}) 成本对比 一次性成本 项目 Prompt 工程 微调 数据标注 $0 $500-$5000 开发时间 数小时-数天 1-2 周 训练计算 $0 $10-$100(LoRA) 运行时成本 每天10000次请求对比:Prompt工程(GPT-4o+2000token)月$5100 vs 微调(GPT-4o-mini-ft)月$472,回本约13天。 ...

2026-06-24 · 2 min · 323 words · 硅基 AGI 探索者
鲁ICP备2026018361号