Deep Learning for Computer Vision——Regularization and Optimization
2026/8/14 14:09:29 网站建设 项目流程
🎯 本课核心要解决的两大问题
  1. 正则化(Regularization):模型在训练集上太“死记硬背”了(过拟合),我们怎么给它套个紧箍咒,让它在新数据上也能考高分?

  2. 优化(Optimization):上一课我们有了损失函数(痛苦指标),这节课我们具体怎么下山——怎么一步步修改权重 WW,让损失降到最低?

第一部分:正则化(Regularization)—— 给模型戴上“紧箍咒”

1. 为什么要正则化?(奥卡姆剃刀原则)

白话解释:如果两个模型在训练集上都得了100分(完全猜对),我们优先选那个更简单的模型。如果简单模型实在搞不定,再换复杂的。

2. 损失函数的新公式(加刑!)
现在损失函数变成两部分:

总损失=数据损失(Data Loss)+λ×正则化损失(Regularization Loss)

  • 数据损失:模型在训练集上猜得有多痛苦(越大越差)。

  • 正则化损失:模型自己带了多少“累赘”(权重越大,惩罚越重)。

  • λ(Lambda)正则化强度。这是一个超参数(和KNN里的K一样,要用验证集来调)。

    • λ=0:完全不管,随便模型怎么复杂。

    • λ=∞(无穷大):模型敢有任何权重,直接罚死,模型变成全0(啥也学不到)。

3. 两大常用正则化武器:L1 和 L2(一定要分清!)

假设我们有一个权重向量 w=[0.5,−0.5,1.0,0.0]:

正则化类型数学公式计算示例(代入w)性格特点(几何直观)
L2 正则化(岭回归)0.25+0.25+1.0+0=1.5“和稀泥”:它讨厌大数字,逼迫所有权重都尽量小且分散。因为它平方了,大数字(1.0)的惩罚(1.0)比小数字(0.5)的惩罚(0.25)大得多。
L1 正则化(Lasso)0.5+0.5+1.0+0=2.0“极端洁癖”:它只算绝对值,会让大量不重要的特征权重直接变成0(稀疏矩阵)。用来做特征选择特别好。

🎨灵魂画图(L1 vs L2 的等高线)
想象在二维坐标轴(权重 w1w1​, w2w2​)上:

  • L2的等高线是个圆形。它跟损失函数相交时,很容易切在坐标轴上非零的地方,所以权重多为非零小值。

  • L1的等高线是个菱形(正方形旋转45度)。它的尖角顶在坐标轴上,所以很多权重会被强制切成0

选哪个?

  • 如果特征数量巨大(比如文本分析),认为很多特征没用 → 用L1(砍掉无用特征)。

  • 如果特征本来就很重要(比如图像像素),认为大家都有用 → 用L2(让大家平分权重)。

第二部分:优化(Optimization)—— 怎么找到最好的 W?

1. 最蠢但最直观的办法:随机搜索(Random Search)

  • 做法:生成几千组随机的 W,挨个算损失,选损失最小的那个。

  • 效果:在CIFAR-10(10类)上,瞎蒙准确率是10%,随机搜索最好能到15.5%

  • 结论:比瞎蒙强点,但跟傻子差不多,绝不可取

2. 聪明办法:沿着斜坡往下滚(梯度下降)

既然我们要求损失函数 L(W) 的最小值,而高维空间我们想象不出来,我们看一维情况(只有一个权重 x):

导数的定义(斜率)
导数大于0,函数在上升;导数小于0,函数在下降。

在多维空间(有N个权重)中
我们把每个权重的偏导数()拼成一个向量,这就是梯度(Gradient)
梯度的方向:指向函数值上升最快的方向。
我们想要下降,所以参数更新公式是:

学习率×梯度

3. 梯度下降的代码骨架(最基础的版本)

# 伪代码 while True: # 1. 根据当前权重w,计算损失函数关于w的梯度 dw = compute_gradient(loss_function, data, w) # 2. 沿着梯度的反方向,迈出一步(步长 = learning_rate) w -= learning_rate * dw

第三部分:深入梯度下降的痛点(为什么需要高级优化器?)

最基本的梯度下降(Batch Gradient Descent)有两个致命缺点:

痛点1:计算太慢
如果训练集有100万张图,算一次梯度要跑遍100万张,太慢。
解法:随机梯度下降(SGD)
每次只随机抽一小批(Mini-batch)数据(比如256张)来算梯度,用这个梯度代表全局梯度。

痛点2:在“陡峭峡谷”中左右横跳(高条件数)
图示

text

⛰️ 山脊(陡峭方向) ↑ 振荡巨大 ←—————→ (我们想去的平坦方向,但走得极慢)

如果损失函数的形状像个长条形峡谷(一个方向特别陡,另一个方向特别平),SGD会在陡坡上左右震荡,在平坡上像蜗牛爬。

痛点3:陷入局部极小值(Local Minima)和鞍点(Saddle Point)

  • 局部极小值:掉进小坑里,以为到底了,其实旁边还有个深谷。

  • 鞍点(这是高维噩梦!)

    • 在二维图上像个马鞍,一个方向向上,一个方向向下,梯度在此处为0。

    • 关键认知:在深度学习(高维空间)中,局部极小值很少见,满大街都是鞍点!因为要让所有方向都向上太难了,只要有某个方向是平的或向下的,梯度就是0,SGD就卡死在这里不动了。

第四部分:四大优化器进化史

为了解决上述痛点,优化器经历了四代进化。我们把dx当成当前算出来的梯度。

🥇 第一代:Vanilla SGD(原始版)
# 缺点:在峡谷震荡,在鞍点卡死 x -= learning_rate * dx
🥈 第二代:SGD + Momentum(动量法)—— 像推铁球下山

核心思想:不只看当前的梯度,还要积累历史速度(惯性)。如果一直往一个方向走,速度越来越快,能冲过鞍点和小坑。

# 先定义速度 v,初始为0 v = 0 while True: dx = compute_gradient(x) # 更新速度:旧速度*动量系数 + 当前梯度 v = mu * v - learning_rate * dx # mu通常取0.9 x += v # 更新参数

作用:在峡谷的陡峭方向,梯度正负震荡,累加起来抵消了;在平坦方向,一直有微小的正梯度,越积越大,嗖的一下就冲出去了

🥉 第三代:RMSProp(自适应学习率)—— 给每个参数单独调步长

核心思想:梯度大的参数(陡峭方向),步长调小点防止震荡;梯度小的参数(平坦方向),步长调大点加速前进。

# 缓存梯度平方的移动平均 grad_squared = 0 while True: dx = compute_gradient(x) # 累加平方梯度(哪边陡,哪边累加得大) grad_squared = decay_rate * grad_squared + (1 - decay_rate) * dx * dx # 更新参数:除以 sqrt(累加平方),陡峭方向除以大数,步长变小;平坦方向除以小数,步长变大 x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7) # 1e-7防止除以0
🏆 第四代:Adam(目前最主流,Momentum + RMSProp 的私生子)

核心思想:既有动量(存历史梯度),又有自适应学习率(存历史平方梯度)。

⚠️偏差修正(Bias Correction),这是Adam防止刚开始训练时步子迈太大的关键!

没有偏差修正的Adam(起步会爆炸!)

first_moment = 0 # 一阶动量(带速度) second_moment = 0 # 二阶动量(自适应) while True: dx = compute_gradient(x) first_moment = beta1 * first_moment + (1 - beta1) * dx # 类似Momentum second_moment = beta2 * second_moment + (1 - beta2) * dx*dx # 类似RMSProp x -= lr * first_moment / (np.sqrt(second_moment) + 1e-7)

问题:因为first_momentsecond_moment初始都是0,在训练刚开始(t=1)时,算出来的值会被初始化为极小的数,导致分母极小,除以它后第一步步长巨大无比,直接飞出银河系!

✅ 加了偏差修正

first_moment = 0 second_moment = 0 for t in range(1, num_iterations): dx = compute_gradient(x) first_moment = beta1 * first_moment + (1 - beta1) * dx second_moment = beta2 * second_moment + (1 - beta2) * dx * dx # 🔥 关键修正:除以 (1 - beta^t),随着t增大,分母趋近于1,修正逐渐消失 first_unbias = first_moment / (1 - beta1 ** t) second_unbias = second_moment / (1 - beta2 ** t) x -= learning_rate * first_unbias / (np.sqrt(second_unbias) + 1e-7)

结论:Adam通常默认参数beta1=0.9,beta2=0.999,learning_rate=1e-3在99%的CV任务中,先无脑上Adam,效果都不差。

第五部分:学习率(Learning Rate)—— 你迈的步子有多大?

学习率是最重要的超参数,没有之一!

  • 太高(10−110−1):步子太大,在谷底左右横跳,甚至越过山丘,Loss直接爆掉(变成NaN)。

  • 太低(10−610−6):步子太小,像蚂蚁爬山,训练100年也不收敛。

  • 理想(10−3∼10−410−3∼10−4):稳定下降。

学习率衰减(Learning Rate Schedules)—— 训练到一半要“慢下来”
刚开始可以大步流星,快到底部时如果步子还很大,就会在最优解附近转圈,永远落不下去。所以:

  1. 阶梯式衰减(Step Decay):每训练30轮(Epoch),学习率直接除以10(比如ResNet的经典操作)。

  2. 余弦退火(Cosine Annealing):像余弦曲线一样平滑地从最大值降到0。

  3. 线性预热(Linear Warmup):刚开始用极小的学习率(比如最大值的10%)跑几轮,防止Adam起步爆炸,再慢慢升上去。

第六部分:正则化与优化器的关系(AdamW 小科普)

  • 在普通的SGD中,L2正则化(λwλw)权重衰减(Weight Decay)是等价的。

  • 但在Adam中,因为自适应学习率的存在,L2正则化会失效(梯度大的被缩小,梯度小的被放大,导致L2惩罚不均)。

  • 现代正解:用AdamW。它不把正则化加在梯度里,而是直接在更新参数的最后,硬生生把权重乘一个小于1的系数(如0.995),这叫权重衰减,干净又利落。

💡 第三课终极认知闭环

  1. 正则化:给损失函数加刑(L1稀疏,L2平滑),λλ 控制惩罚强度,防止模型在训练集上作弊。

  2. 优化本质:利用梯度(导数向量)指引方向,负梯度下山。

  3. SGD太笨:遇到峡谷震荡,遇到鞍点卡死,计算全数据集太慢。

  4. Momentum:加个惯性,冲过鞍点,抵消震荡。

  5. RMSProp:自适应学习率,陡坡慢点走,平坡快点走。

  6. Adam(集大成者)= Momentum + RMSProp +偏差修正(防止起步炸),当下CV默认首选。

  7. 学习率策略:配合预热和衰减,让模型最后稳稳落进谷底。

代码避坑指南

  • 在PyTorch里,一行torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)就把Adam和L2正则化全搞定了。

  • 如果训练时Loss突然变成nan99%是学习率设太高了,赶紧降低一个数量级。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询