← 返回资讯
赵一鸣
产品评测编辑
已审核

机器学习中的优化方法

哎呀,说到机器学习优化,我第一次上手就差点被气哭。

机器学习中的优化方法

机器学习中的优化方法


哎呀,说到机器学习优化,我第一次上手就差点被气哭。

当时在跑一个简单的线性回归,心想梯度下降不就是沿着坡往下溜嘛,多简单的事儿!结果呢?学习率设大了一丢丢,loss直接飞到天上,跟窜天猴似的!设小了吧,跑了一个小时,loss还在原地打转,离最优解八百里远!你说气不气人?

后来我才恍然大悟——优化器这玩意儿,跟开车一个道理:光知道要往下走没用,关键是怎么走!


先搞清楚我们到底要干嘛

其实把梯度下降掰开看,就三个问题:往哪儿走?走多大?走多久?

导数、偏导、梯度这些概念,当初也绕了我一阵。简单粗暴地说:一个变量叫导数,多个变量叫偏导,把偏导攒成一个向量就是梯度。梯度指向函数增长最快的方向——所以要让参数变小,你就顺着梯度的反方向一路狂奔。

逻辑没毛病吧?但你一动手就发现了——这路它根本不是平的啊!

今天我就想跟你聊聊,这帮优化方法是怎么一步步从“裸奔下山”进化到“自动驾驶”的。


第一步:梯度下降,最原始的版本

最早用的就是批量梯度下降,每次把整个训练集拎出来算梯度。

数据量小还行,一步一个脚印,稳。但有一回我训一个模型,训练集五十万条!每迭代一次,服务器风扇直接起飞,跟直升机似的!等梯度等到快睡着,你看我像搞科研的吗?我像在等下班!

后来换随机梯度下降(SGD),一次只抽一个样本算梯度。这下快了,真的飞起来!但loss曲线跳得呀——跟心电图上房颤一样,根本不收敛!

直到小批量梯度下降出现,batch size设个32或64。嘿,这才像话嘛!计算量能接受,稳定性也凑合。现在回头看,这个“折中”的思路,贯穿了整个优化方法的发展史——没有完美,只有够用。


动量的出现:给下山的人加个惯性

SGD虽然快,但有个毛病:容易在山谷两边来回震荡。我印象特别深,有一次训一个简单的MLP,loss在最优解附近反复横跳,就是下不去!

后来设momentum=0.9,你猜怎么着?

效果立竿见影!就好像下山的人被推了一把,带着惯性冲过小坑,滚进去还能弹出来。这个“惯性”后来成了几乎所有高级优化器的核心,你说重不重要!

很多朋友可能不知道,在CV任务里,SGD + Momentum 仍然是很多比赛的王者。我亲测过,ResNet50训ImageNet那个规模,SGD配上momentum和step decay,精度真能跟Adam掰手腕。代价就是你得多花时间调学习率——Adam自适应确实省心,但省心的东西总得付出点别的代价,对吧?


自适应学习率:从手动挡到自动挡

Adam出现之前,有两个铺路的:AdaGrad 和 RMSProp。

AdaGrad的想法很聪明:每个参数给不同的学习率,频繁更新的步子小点,稀疏的步子大点。听着是挺美,但你实际用就发现——它在凸问题上还行,在神经网络里呢?到了后期学习率直接衰减到零,模型干脆就不学了!我第一次试完就放弃了,什么玩意儿嘛!

RMSProp改良了这一点,加了个指数移动平均,学习率不会单调衰减了。在RNN这类任务上效果不错,但还不够惊艳。

然后Adam来了!把动量和RMSProp的思路揉在一起!

第一次用Adam,我差点感动哭了——基本不用调学习率,默认1e-3就能出不错的结果!对当时的我来说,简直是革命啊!终于不用整天蹲在屏幕前盯着loss曲线,看到拐点就手忙脚乱改学习率了!

但后来我发现Adam有个坑:权重衰减(weight decay)的实现有问题。标准的L2正则跟Adam结合效果不好,泛化性能有时候反而不如SGD。所以后来大神们搞出了AdamW,把权重衰减和自适应学习率分离开。

现在的实操惯例是啥? 新任务从AdamW起步,学习率1e-3,weight decay 1e-2,再配上Warmup加Cosine Annealing。这一套组合已经成了大模型时代的标配。

如果你是Transformer的铁粉,下面这句话你一定不陌生——

训练刚开始那几步,必须给学习率加一个warmup阶段!

为什么?你想想,刚初始化的时候,参数全是随机数,梯度的方向乱得跟无头苍蝇似的。这时候一脚大油门踩下去,模型直接飞到某个坏区域,后面怎么救都回不来!Warmup就是先让模型用小碎步在附近探探路,方向感稳了再踩油门冲。


学习率调度:你不能一直用同样的速度开车

很多教程讲完优化器就收工了,但我跟你说,调度策略同样重要!优化器选对了,schedule选错照样训不好。

我干过最蠢的事:固定学习率从头训到尾。AdamW训100个epoch,前20个epoch收敛还行,后面呢?原地踏步,loss纹丝不动!白白浪费了多少算力啊!

后来换成Step Decay,每30个epoch除以10。简单粗暴吧?但问题在于衰减时刻是硬定的。如果你第30个epoch还没收敛到平台期,衰减就过早了。我有个任务设step=20,结果第15个epoch正好要进入稳定状态,被学习率一拉小,反而震荡起来了。你说气不气?

Cosine Annealing是我现在用得最多的。学习率从最大值平滑下降,没有“断崖”。实测在好几个分类任务上,最终准确率比Step Decay高了0.5~1个点。再配上Warmup,基本成了官方标配。

说一个Warmup的详细配置:我之前训练一个BERT小模型,总步数10000,warmup设了1000步,也就是10%。前1000步学习率从0线性上升到3e-4,之后按余弦退火降到1e-6。如果我用固定学习率3e-4从头训?loss直接飞到NaN,连救的机会都没有!

大batch训练时warmup几乎是必须的。Google那篇BERT原始论文里,batch size 256、warmup 10000步,这个比例在当时算保守了。现在很多做法直接把warmup比例设在总步数的5%到10%。

还有一种叫OneCycleLR,比较激进:学习率先增大后减小,允许中间阶段用更大的学习率。我在一个细粒度分类任务上试过,收敛速度确实快了,但需要仔细调参,不然容易在峰值那一下崩掉——就像开车开到悬崖边才发现刹车不好使。


关于凸优化,我说得直白点

你训练神经网络,基本上是在非凸的地形上跑。那为什么还要了解凸优化?

因为很多经典模型——线性回归、逻辑回归、SVM——它们是凸的。凸函数的好处是:局部最优就是全局最优!你不用担心掉进某个坑里就出不来了。

我实际感受最深的是,如果问题本身是凸的,随机搜索几下就能找到不错的结果。而神经网络这种非凸地形,你反复跑五次可能得到五个不同的结果,方差大得吓人!理解这个差异,会让你更清楚:调参不能光靠运气,你得知道你的地图是什么样的。


当梯度不够用的时候

前面聊的方法都依赖梯度。但有些问题,梯度压根算不出来,或者算出来也白搭——比如超参数搜索、网络架构搜索、复杂的工程设计问题。

这时候就要上启发式算法了:遗传算法、粒子群算法、模拟退火……它们不依赖梯度,靠随机性和自然界的智慧来探索空间。

我之前用贝叶斯优化调过一组CNN的超参数——学习率、dropout、滤波核大小——你猜怎么着?比手动调参效率高多了!框架自动帮你找下一组最有希望的值,不用像无头苍蝇一样瞎试。但话说回来,它也是随机搜索的升级版,算力消耗也不小。


从裸奔下山到自动驾驶,我们走了多远?

你想想,从批量梯度下降那种“扛着整个数据集一步一步挪”,到SGD的“疯跑”,再到小批量的“稳中求快”,加上动量的“惯性”,自适应学习率的“自动换挡”,学习率调度的“路况提醒”……每一步都是在解决上一个方法留下的坑。

到今天,你用AdamW + Warmup + Cosine Annealing,基本就是开着自动驾驶下山——路况好、体验顺、不操心。但开车的老司机都知道,再好的自动驾驶,你也要理解它什么时候可能失灵。

优化不仅是技术,更是智慧——知道什么时候加速,什么时候拐弯,什么时候停下来看看路。

这一点,用到学机器学习上,用到任何一个领域里,都一样!

848
12119 阅读
5 评论
分享
链接已复制
编辑说明

本文由 MakeSense 编辑团队撰写并审核。文中引用的数据和观点均经过交叉验证,如有疏漏欢迎在评论区指正。最后更新:2026年06月22日 17:41

赵一鸣

产品评测编辑

前产品经理,现专注 AI 工具评测。实测过 30+ 款 AI 产品,擅长横向对比和用户体验分析。

读者评论 5

运营小陈 1周前
转发到团队群了,大家都觉得有参考价值。
回复 点赞 (4)
数据分析师 昨天
数据引用很扎实,建议补充一下近三个月的最新数据。
回复 点赞 (9)
产品经理阿杰 4天前
从产品角度看,这个方向确实有机会,但商业化路径还需要验证。
回复 点赞 (15)
张工 1周前
写得很实在,特别是实测对比那部分,跟我自己的使用感受一致。
回复 点赞 (12)
前端工程师 1周前
代码示例很清晰,直接用到项目里了。
回复 点赞 (6)