PaZO零阶优化:不计算梯度也能高效微调大模型的新路径

发布时间:2026/10/19 19:21:43
PaZO零阶优化:不计算梯度也能高效微调大模型的新路径 如果你最近在调大模型八成已经碰到过同一个尴尬代码写得挺顺手一跑全参微调显存直接报警。于是大家开始转向 LoRA、QLoRA、梯度检查点这些外围功夫很少有人去质疑反向传播本身是不是微调唯一的路。2025 年 NeurIPS 上有一篇标题为 PaZO 的工作——Preconditioned Accelerated Zeroth-Order Optimization for Fine-Tuning LLMs——把零阶优化这个古老思路重新拉回大模型微调的前台。零阶优化Zeroth-Order Optimization的意思是不计算梯度只靠目标函数的值来估计下降方向。PaZO 在零阶优化之上又叠加了预条件Preconditioning和加速Acceleration两块机制直接针对零阶方法过去收敛慢、怕病态问题的短板。这篇文章从一个从业者的角度把我对这条技术路线的理解、公式直觉、落地实现和一些调参经验整理出来给正在为显存发愁或者想做低资源微调的读者一个可以顺畅上手的参考。1. 反向传播的隐形成本比大多数人以为的更高1.1 我们在为“梯度”付三笔账微调一个 7B 模型很多人只盯着一张显卡的显存数字却很少去拆这张账到底花在哪。以 BF16 全参微调为例参数本身占 14GB这只是一部分训练过程中优化器状态又要吃掉一大块Adam 需要为每个参数维护一阶矩和二阶矩通常按 32 位浮点存又是 28GB再加上反向传播要算出来的梯度14GB前向过程中为了反传保存的激活值这个量随着序列长度和 batch size 线性往上飙。七七八八加起来56GB 只是起步价长序列场景下 80GB 也不一定够。但这三笔账里真正“刚性”的其实是反向传播链路本身。你一旦决定用一阶优化器就必须存在从 loss 到每一层参数的梯度回传路径就必须保存中间激活就必须在每一步更新时读取并更新优化器状态。这套机制在稠密小模型上运行了几十年没什么问题到了大模型时代它成了瓶颈。零阶优化第一个吸引人的地方就在这里它直接绕开了三笔账中的后两笔。推理只需要前向传播拿到 loss 值不需要 backward不需要保存中间激活也不需要维护 Adam 状态。等于把大部分显存预算从“训练开销”里挪出来还给模型本身。1.2 零阶优化不是新东西但在 LLM 时代有了新身份零阶优化的历史很长早年主要用在黑箱优化、仿真调参、对抗样本生成这些场景里。它的核心逻辑很简单你不知道梯度的解析表达式就通过采样函数值来“猜”梯度方向。最基本的做法是两点估计对参数加一个微小的扰动计算扰动前后的 loss用两者的差除以扰动幅度得到一个沿随机方向的梯度近似。在大模型之前这套做法给人最大的印象就是慢。每个参数维度都要采样或者至少每个随机方向都要跑一遍完整前向成本高得吓人。但大模型微调的场景出现后游戏规则变了反向传播省下来的显存和内存带宽可以换来更多次前向传播而前向传播是纯计算密集的分布式并行、算子融合、FlashAttention 这些优化成熟之后单次前向的开销已经降到非常低的水平。PaZO 正是踩在这个平衡点上。它名字里的三个限定词——Preconditioned预条件、Accelerated加速、Zeroth-Order零阶——分别对应三个问题零阶解决显存预条件解决收敛效率加速解决步数。理解了这三者的组合逻辑才算真正看懂了这篇工作。2. PaZO 拆解预条件和加速分别补上了什么短板2.1 零阶优化的心头痛梯度噪声与病态条件数零阶优化最被人诟病的是它估计出来的梯度带噪声。两点估计的误差和扰动步长 δ 直接相关δ 太小函数值差分被浮点精度淹没δ 太大有限差分近似偏离真实梯度。这个噪声会让收敛曲线变得毛躁但还只是表面问题。真正要命的是条件数。一阶方法里SGD 的收敛速度强烈依赖于 Hessian 的条件数——如果损失函数在不同方向上的曲率差异很大梯度下降会走锯齿路径每一步都在来回震荡步长只能取最小曲率方向允许的上限。这个问题在零阶方法里会被放大你的梯度本身是估计的方向误差叠加上病态几何会让锯齿效应更严重。这就是为什么普通零阶方法在小模型玩具任务上看着还行一到大模型这种动辄上亿参数、各向异性严重的损失曲面就彻底拉胯。PaZO 要做的第一件事就是用预条件来纠正这种几何上的不平衡。2.2 预条件的几何直觉把椭圆拉回正圆预条件这个概念很多人第一次接触是在数值线性代数里。解线性方程组时如果系数矩阵条件数太大直接迭代会收敛得很慢于是你会左乘一个矩阵的逆把特征值分布压到 1 附近再去做迭代。放到优化里是一样的逻辑。损失函数等值线是一个高维椭球预条件矩阵的作用就是做一个线性变换让这个椭球尽量变成正球。通俗点说原来有的方向陡峭、有的方向平缓步长照顾平缓方向就会被陡峭方向害死预条件之后每个方向都按各自的尺度缩放更新方向自然就正了。在深度学习里Adam 其实已经隐含了对角预条件它对每个参数的历史梯度平方做指数平均然后按这个量归一化更新步长。PaZO 的思路延续了这种思想但把它明确地设计成零阶优化里的预条件模块用有限的函数值估计信息构建出近似 Hessian 对角或者低秩逼近再把它应用到梯度估计上。2.3 加速除了去掉锯齿还要抄近路预条件解决了“方向对不对”的问题加速Acceleration解决的是“步长能不能更大、路径能不能更直”的问题。加速方法的核心不是简单地增大学习率而是引入动量或者更高阶的路径修正把历史梯度方向的信息利用起来。零阶优化里加速尤其重要因为每一步的方向都有噪声。如果只按当前估计走噪声会被直接放大如果加入动量机制噪声在时间维度上互相抵消真实下降方向被累积增强。PaZO 的“Accelerated”大概率走的也是这个思路把 Nesterov 型加速或者重球法Heavy Ball的思想移植到零阶框架里让每次更新既用当前梯度估计也用前面的运动趋势。这里有一个细节值得注意一阶方法里的动量实现非常简单因为梯度是准确的零阶方法里动量有效性的前提是“梯度估计的无偏性”。如果两点估计是有偏的动量反而会把偏差累积起来。所以 PaZO 在加速模块前面一定要配非常谨慎的梯度估计器设计这正是它和早期纯零阶方法拉开差距的地方。3. 从公式直觉到工程落地一个可操作的 PaZO 实现框架3.1 梯度估计器几种方案怎么选零阶梯度估计的核心模块常见的有三类坐标梯度估计每次只扰动一个参数维度得到该维度的偏导近似。方差小但需要 O(d) 次前向维度灾难严重大模型下不现实。随机方向两点估计每次用一个随机方向扰动全部参数两次前向得到标量差一除就得到一个方向上的投影。方差大但每次只需要两次前向是当前主流。随机方向多点估计用多个随机方向做平均方差随采样数线性下降但前向次数也线性增加。PaZO 这类面向 LLM 的工作几乎必然选第二种或者第三种的折中。单步两次前向听起来很贵但配合预条件下一次方向质量不够好多采样几个方向再平均往往比增加几倍步数更划算。实操中可以在 2 到 16 之间调节采样数一般 4 到 8 是一个性价比很高的区间。这里还要提一个工程细节随机方向向量的生成和存储。如果是 7B 模型一个随机方向向量本身就是 7B 个浮点数生成用正态分布随机数存储需要十几 GB。所以实现时通常用种子生成器每次采样方向时从同一个种子恢复避免存整个方向向量只存种子状态。3.2 预条件矩阵的构造对角近似最现实LLM 场景下构造完整预条件矩阵不现实7B 乘 7B 的矩阵光存储就超出预算。可行的近似包括对角近似从过去几次梯度估计中累计二阶信息类似于 RMSProp 的二阶矩。每个参数一个标量内存 O(d)。分块低秩把参数划分成若干块每块用低秩矩阵近似块内曲率。内存 O(dr)适合小规模测试。结构预条件按 Transformer 的结构分层处理比如 attention 和 MLP 分别统计曲率尺度。对标现有的生态Adafactor 的分层二阶矩做法可以直接借鉴过来做预条件对不同层给不同的学习率缩放相当于层级别的对角预条件。PaZO 工作里大概率用的是对角或层结构预条件这个选择既照顾了内存也抓住了 LLM 损失曲面里最主要的不平衡来源——层间尺度差异。3.3 伪代码一个能在现有框架里魔改的雏形把 PaZO 的想法落成可运行流程核心只有幾步import torch def pazo_step(model, loss_fn, params, state, lr5e-4, eps1e-6): 简易 PaZO 风格更新。 state 维护动量 m 和预条件二阶信息 v。 seed torch.Generator(deviceparams[0].device).seed() def perturb_and_loss(alpha): with torch.no_grad(): for p, direction_cache in zip(params, state[directions]): p.add_(direction_cache, alphaalpha) loss loss_fn() for p, direction_cache in zip(params, state[directions]): p.add_(direction_cache, alpha-alpha) state[directions] [] for p in params: d torch.randn_like(p, generatorseed) d.div_(torch.linalg.vector_norm(d, keepdimTrue).clamp_min(1e-12)) state[directions].append(d) f_plus None with torch.no_grad(): for p, d in zip(params, state[directions]): p.add_(d, alphaeps) f_plus loss_fn() for p, d in zip(params, state[directions]): p.sub_(d, alphaeps) f_minus loss_fn() # 方向梯度估计标量投影 g_proj (f_plus - f_minus) / (2 * eps) # 把标量投影转成参数梯度估计 grads [d * g_proj for d in state[directions]] # 预条件 加速简化为重球动量 for p, g, d, m in zip(params, grads, state[directions], state[momentum]): v state[v][id(p)] v 0.9 * v (1 - 0.9) * g.pow(2) state[v][id(p)] v m.mul_(0.9).add_(g) update m / torch.sqrt(v 1e-8) p.add_(update, alpha-lr) return f_minus这段代码离完整实现还有距离但骨架是齐的一次方向采样对应两次前向动量提供加速v 提供对角预条件。实际部署时loss_fn 需要自己实现为只返回标量 loss不维护任何计算图否则又走回反向传播的老路。这是零阶微调最需要注意的一点一定不要在你采样前向时构建计算图所有扰动都必须在 no_grad 环境下进行。3.4 与现有微调生态怎么整合Lora、PEFT、HuggingFace Transformers 这些库默认假设你要反向传播所以把它们应用到零阶优化时要做一点适配。最简单的做法是把可训练参数包成一个扁平化列表loss_fn 里手动跑模型的前向计算 loss然后只调用我上面写的 pazo_step不调用 loss.backward()。我实际试下来这个过程最烦的是模型的输出层和损失函数那一堆细节例如语言模型的 logits 怎么展开、cross entropy 是在显存里算还是 CPU 上算、中间结果是不是要 detach。建议第一次写的时候先把输入 batch 缩小到单条跑通数值检查再放大否则很容易踩到“某个算子自动构建了计算图”的坑。4. 显存、通信与迭代代价到底什么时候该用 PaZO4.1 记账本同样一个模型钱花在哪不一样下面这张表是经验估算具体数字会根据实现而浮动但结构是对的。方案参数梯度优化器状态激活/中间量每次迭代前向次数全参 Adam参数梯度约双倍参数量2 或 4 倍参数量较大依赖序列和 batch1 次 backward 附带额外前向LoRA极小可训练参数极小仍要反向传播激活省不了1 次完整 forwardbackward零阶PaZO 风格只有参数本身对角预条件约 1 倍参数量几乎可以清空只要 loss 标量2 次纯 forward零阶方案的一大优势是激活值几乎可以被清零你不需要保存任何中间张量来反传只要拿到 loss 标量中间层的结果立刻可以释放。这在大 batch、长序列场景下节省的显存是惊人的。另一个优势是优化器状态大幅压缩对角的二阶矩只需要和模型参数同等规模比 Adam 的 2 到 4 倍少了不止一半。4.2 适合 PaZO 的三个典型场景第一个场景显存有限但推理显存已够。很多研究团队只有单张 24GB 或 32GB 的卡跑不动 7B 全参微调但跑得动 7B 推理。PaZO 这类零阶方式可以让你在“只多一张卡”的条件下完成微调而不是被迫换卡或者强行量化。第二个场景批量微调多个模型。如果运维或者说团队手里有一批模型要反复做指令微调、风格微调且每个模型都只有几小时生命周期零阶方式因为不需要维护庞大的 Adam 状态切换任务时几乎没有额外负担。第三个场景模型权重不可导或接口黑盒化。有些模型经过编译优化、量化、或者封装成 API内部结构不受你控制你能拿到的只有输入和输出。这时候零阶方法是唯一还能做优化的路径可以用同样的逻辑去调 prompt、调权重的外部化版本甚至做系统级调参。4.3 和 LoRA、QLoRA 不是替代关系是不同维度的取舍很多读者会问有 LoRA 为什么还要搞零阶答案很简单LoRA 是在参数维度做降维PaZO 是在梯度获取方式上做替换两者并不互斥。你可以先取 LoRA 低秩化再用零阶优化去更新 LoRA 参数也可以反过来对全量参数用零阶优化但只在某些层上实施预条件。PaZO 最有价值的一点其实是它把微调从“必须逆向传播”的框架里解放出来。假设未来模型权重通过 API 发布或者所有权受到保护微调就只能在外面做零阶优化。PaZO 这条路线实际上是在为一个更开放、更灵活的生态布局。5. 实测体验与参数调优笔记稳定性和收敛速度两手抓5.1 学习率与扰动量需要联合调整零阶优化最核心的两个超参数一个是学习率一个是扰动步长 eps。这里有个关键经验学习率和扰动步长并不是独立的。eps 太小数值差分会因为浮点误差失效eps 太大梯度估计会凭空引入巨大偏差。而学习率直接放大了梯度估计中的噪声。在实践中我建议用这样一组初始值开始再做自适应调整eve 初始范围1e-4 到 1e-2 之间建议从 1e-3 起步做 log 扫描学习率比对应的 Adam 场景低三分之一到一半因为动量累积后实际步长会变大方向采样数先用 4看梯度估计方向的方差是否可接受再往 8 或 16 调预条件二阶矩的衰减率β 取 0.99 到 0.999 之间偏向 0.99 让近期信息占主导一次实验中我发现当 eps 从 1e-3 调到 1e-4 时loss 曲线从剧烈震荡变成平缓下降原因是前者已经偏离线性近似区间。这个问题在 PyTorch 的 float32 下尤其明显如果模型参数是 float16 或 bfloat16eps 还要继续调大保证差分值不被舍入噪声吃掉。5.2 往 8 或 16 方向采样前先确认批量大小的收益零阶方向估计的另一个特点是它会放大 batch 内部的噪声。一阶梯度天然是在一个 batch 上平均了所有样本的梯度零阶梯度则是用一个 batch 的 loss 差分去近似batch 太小loss 的波动会被误当成下降方向。所以调参时优先增大 batch size而不是增加采样方向。我在一个中等规模任务上的经验是batch size 提高一倍效果往往比方向数提高一倍更明显。原因也很简单前向采样次数是线性成本batch size 在同样次数的前向下可以摊平更多样本噪声物美价廉。5.3 常见失败模式与对应的排查路径如果 loss 完全不下降先检查方向扰动有没有真的动到参数。有人把扰动加到 derivative 张量上忘了 actually 更新前向计算的参数副本结果伪装跑了两次前向扰动根本没进去。如果 loss 开始下降但剧烈震荡优先怀疑学习率太高或者扰动步长太大。一个靠谱的稳定技巧是对最终更新方向做一个梯度裁剪或者用余弦退火把学习率压在低位都可以有效缓解。如果初期表现很好、训练后期卡住多半是预条件矩阵算得有问题。预条件本质是环境感知的自适应方法后期损失曲面更平坦时V 里的二阶矩累计值可能过大导致更新步长被压缩。可以周期性重置预条件状态或者对 V 做 max 截断避免它膨胀到夸张级别。5.4 对比观察PaZO 风格方法的实际速度观感很多人在跑零阶之前最担心的是“每次迭代两次前向是不是太慢”。事实是两次前向在单卡上大约是把时间翻倍之后还多一点但如果你原本因为显存不够从 8 batch 被迫降到 2 batch那零阶反而可能是赢的。反向传播本身的启动开销不算贵贵的是内存换页和显存不足时的重计算。PaZO 把重计算彻底消灭掉换来的是更多的原始前向运算一进一出在很多配置上并没有变慢多少而能操作的模型规模明显变大。6. 零阶微调的上限在哪里几个值得继续深挖的方向6.1 跨卡并行下的零阶优化PaZO 目前可以理解的实现方式是单卡或简单数据并行但它的真正威力会在多卡并行下进一步释放。因为零阶优化不需要同步梯度和激活天然省掉了一部分通信开销。跨卡场景下每张卡可以独立采样不同的扰动方向、独立计算函数值最后只汇总一小组标量和方向参数。这个特性非常适合大规模蒸馏、模型融合或联邦式的微调。6.2 与解码阶段工作的交叉零阶优化不一定只用在训练阶段。大模型推理时我们可以把它用来做上下文优化给定一组验证样本调整 prefix 向量、系统提示、甚至采样参数目标是让输出 quality 更好。这个场景下模型不可导又没有训练流程去维护一堆状态零阶加预条件的方法显得非常顺手。6.3 从“预条件加速零阶”到“结构感知零阶”PaZO 的意义可能不在它单个算法上而在它指明了一个方向纯黑箱优化能够利用结构信息也可以做得跟白箱优化一样高效。后续工作完全可以沿着这个思路做分级对不同层用不同的扰动尺度对 attention 和 MLP 用结构化的预条件甚至把 RL 里的奖励模型信号当成零阶反馈来用。这些都不是天方夜谭只是需要有人先把调试痛苦吃一遍。最后我个人的体会是零阶优化调起来确实比 Adam 系列要烦一些需要时刻留意扰动与数值类型交互的细节但换来的是对整个模型训练过程更强的掌控感。你不再需要把模型塞进一层层 backward graph 里去求梯度而是用一个简单的 loss 信号去直接推动权重这种直觉上的直观感是很适合做原型验证和教学演示的。如果你手头正好有显存捉襟见肘的微调任务建议下个周末花几个小时把上面这套 PaZO 风格更新换成一个小实验跑一跑看看你的任务在零阶条件下到底能走多远。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询