查看全课大纲(第 30 / 93 节)
- 1.计算机视觉概述
- 2.计算机视觉应用场景
- 3.困难与挑战
- 4.开源库介绍
- 5.图像显示与存储
- 6.CLAHE
- 7.腐蚀膨胀与开闭运算
- 8.滤波与边缘填充
- 9.各种滤波
- 10.图像金字塔
- 11.傅里叶变换
- 12.短时傅里叶变换与小波变换
- 13.颜色特征与颜色直方图
- 14.几何特征_边缘
- 15.几何特征-角点与斑点
- 16.局部特征-SIFT特征描述子
- 17.局部特征-SURF特征描述子
- 18.局部特征-ORB特征描述子
- 19.其他特征描述子
- 20.传统图像分割技术
- 21.GraphCut
- 22.GrabCut
- 23.人脸检测的传统方法
- 24.行人检测的传统方法HOG+SVM
- 25.行人检测DPM
- 26.人工神经网络的架构
- 27.目标函数与梯度下降
- 28.误差反向传播
- 29.可手算的神经网络
- 30.改进目标函数与克服梯度消散
- 31.神经网络之传统神经网络与深度网络的差异
- 32.各种梯度下降算法
- 33.如何选择合适的梯度下降算法
- 34.避免过适应
- 35.CNN的架构
- 36.CNN的误差反向传播_卷积层
- 37.CNN的误差反向传播_池化层
- 38.分类所用的数据集
- 39.Alexnet详解
- 40.VGG详解
- 41.GoogLeNet_v1
- 42.BatchNormalization
- 43.GoogLeNet_v3v4
- 44.ResNet
- 45.ResNeXt
- 46.CNN设计准则
- 47.图像检索与推土机距离
- 48.基于颜色相似性
- 49.基于形状相似性
- 50.基于纹理相似性
- 51.基于局部特征相似性
- 52.DL的二值哈希编码
- 53.高维空间中检索KDTree
- 54.高维空间中检索LSH
- 55.目标识别任务综述
- 56.RCNN
- 57.SPP-Net
- 58.Fast R-CNN
- 59.Faster R-CNN
- 60.R-CNN系列模型回顾
- 61.R-FCN的设计思路
- 62.R-FCN的实现
- 63.YOLOv1
- 64.YOLOv2_9000
- 65.YOLOv3
- 66.图像分割应用场景与数据集
- 67.上采样的实现方式
- 68.FCN网络架构的由来
- 69.FCN构建细节
- 70.DeepLabv1
- 71.CRF
- 72.DeepLabv2
- 73.DeepLabv3
- 74.特定的医学影像分割任务
- 75.U-Net
- 76.3D U-Net
- 77.V-Net
- 78.DenseNet
- 79.病理切片分析任务及数据集
- 80.病理切片分析
- 81.图说任务及其传统处理方法
- 82.深度语言模型与RNN
- 83.LSTM及其变种
- 84.NIC模型
- 85.SAT模型
- 86.图说的性能指标
- 87.判别模型与生成模型
- 88.KL散度与JS散度
- 89.VAE
- 90.GAN的基本原理
- 91.DCGAN与CGAN
- 92.Wasserstein GAN
- 93.SRGAN
改进目标函数与克服梯度消散
小象实战讲义 · 基于深度学习的计算机视觉
在深度神经网络训练中,选择合适的损失函数和激活函数至关重要。本节将深入探讨深度学习为何放弃传统的均方误差,转而采用交叉熵损失函数,以及如何通过改进激活函数(如 ReLU)来有效克服深度网络训练中的“梯度消散”难题,从而为构建更深、更强大的模型奠定基础。
💡 核心导读
- 目标函数革新:从均方误差(MSE)到交叉熵(Cross-Entropy),理解为何交叉熵能提供更“陡峭”的优化地形,加速模型收敛。
- Softmax 层的作用:学习如何将网络输出转化为概率分布,并巧妙避免因概率为零带来的计算困难。
- 梯度消散的根源:分析 Sigmoid 激活函数在深层网络中导致梯度指数级衰减的数学原理。
- ReLU 的救赎:认识修正线性单元(ReLU)如何以其简单的形式,从根本上缓解梯度消散,并带来稀疏化等额外好处。
- 历史方案回顾:了解深度学习早期(如2006年)为解决梯度问题曾采用的受限玻尔兹曼机(RBM)预训练方法。
从均方误差到交叉熵
在传统的神经网络中,最常用的目标函数(损失函数)是均方误差。对于一个有 n 个样本的批次,其形式为:
其中, 是第 i 个样本的真实值(标签), 是模型预测出的值。我们的优化目标是最小化这个均方误差。
然而,在深度学习中,尤其是在分类任务中,我们普遍采用了交叉熵作为目标函数。对于二分类问题,其形式为:
对于多分类问题(假设有 K 个类别),形式为:
这里, 是 one-hot 编码的真实标签, 是模型预测的属于第 k 类的概率。
为什么是交叉熵?
交叉熵损失函数有两大核心优势:
- 与概率输出的天然契合:深度学习分类网络的输出层通常使用 Softmax 函数,将原始的得分(logits)转化为概率分布。交叉熵衡量的是两个概率分布(真实分布
y和预测分布ŷ)之间的差异,这与 Softmax 的输出形式完美匹配。 - 提供更陡峭的梯度:这是加速训练的关键。考虑一个极端情况:模型对一个本应属于类别 A()的样本预测概率极低()。此时,交叉熵损失项 会变得非常大(因为 ),并且损失对预测概率的梯度为 ,幅度极大,这为优化器提供了一个非常强烈的修正信号。相比之下,均方误差 对预测值的梯度约为 ,信号强度远不如交叉熵。因此,交叉熵损失函数的“优化地形”更陡峭,有利于梯度下降算法快速找到最优解。(注:若输出层接 Softmax,损失对 logits 的梯度会归一化为 ,幅度有界,但仍比同错误程度下的 MSE 梯度更大。)
Softmax:从得分到概率
交叉熵损失要求输入是概率。Softmax 层正是负责将网络最后一层线性层的输出(得分)转换为概率分布的函数。对于一个包含 K 个类别的向量 ,Softmax 的计算如下:
Softmax 的精妙之处在于:
- 突出最大值:通过指数运算,放大得分间的差异,使最大得分对应的概率显著高于其他。
- 归一化为概率:所有输出概率之和为 1,符合概率公理。
- 避免零概率:即使某个得分 非常小(负很大),其指数 也是一个大于 0 的极小正数,从而保证 不会出现计算错误(
log(0)未定义)。
下面我们用一个小例子来直观感受 Softmax 的作用:
import numpy as np
# 假设网络最后一层输出三个类别的得分
logits = np.array([3.0, 1.0, -3.0])
print("原始得分 (logits):", logits)
# 计算 Softmax
exp_logits = np.exp(logits)
probabilities = exp_logits / np.sum(exp_logits)
print("Softmax 概率:", probabilities)
print("概率总和:", np.sum(probabilities))原始得分 (logits): [ 3. 1. -3.]
Softmax 概率: [0.87887824 0.11894324 0.00217852]
概率总和: 1.0可以看到,得分 3 被放大为约 0.88 的高概率,得分 -3 则被压缩为约 0.0022(约 0.22%)的极小概率,但绝非零。这正好满足了交叉熵损失计算的要求。
梯度消散:深度网络的“拦路虎”
在深度学习兴起之前,神经网络通常只有 3-5 层。一个关键的限制因素是 梯度消散:在误差反向传播过程中,梯度从输出层向输入层传递时,其幅度会指数级地衰减,导致靠近输入层的权重几乎得不到有效的更新。
根源:Sigmoid 激活函数
梯度消散问题与传统的 Sigmoid 激活函数密切相关。Sigmoid 函数及其导数如下:
Sigmoid 导数的最大值出现在 处,。在大部分定义域内,其导数值都远小于 1。
现在,我们结合反向传播公式来理解问题。考虑一个简化场景,我们计算损失函数 对某一层偏置 的梯度。根据链式法则,这个梯度可以表示为后续各层权重 和激活函数导数 的连乘积形式。
假设权重按较小的随机值初始化(绝对值通常小于 1)。那么,在反向传播路径上,每经过一层,梯度就要乘以一个小于 1 的权重 和一个小于等于 0.25 的激活函数导数 。
例如,对于一个 3 层隐藏层的网络,梯度从输出层传回第一层隐藏层时,至少会被乘以 这个过程三次。即使忽略权重的影响,仅激活函数导数部分就会引入 的衰减因子。如果网络更深,衰减将是指数灾难性的 ,导致底层梯度几乎消失。
import numpy as np
# 模拟一个简单的反向传播梯度计算(概念性展示)
np.random.seed(42)
# 假设有三层,每层的“梯度衰减因子”由权重(假设为0.5)和sigmoid导数(假设为0.25)构成
layer_factor = 0.5 * 0.25 # 每层的复合衰减因子
num_layers = 3
# 输出层初始梯度假设为 1.0
gradient_at_output = 1.0
# 传播回第一层隐藏层
gradient_at_first_hidden = gradient_at_output * (layer_factor ** num_layers)
print(f"经过 {num_layers} 层 Sigmoid 网络反向传播后,梯度衰减为: {gradient_at_first_hidden:.6f}")
print(f"这相当于初始梯度的 {gradient_at_first_hidden * 100:.2f}%")经过 3 层 Sigmoid 网络反向传播后,梯度衰减为: 0.001953
这相当于初始梯度的 0.20%历史方案:受限玻尔兹曼机预训练
在 2006 年左右,Geoffrey Hinton 等人提出了使用 受限玻尔兹曼机 进行无监督预训练的方法来缓解梯度消散。其核心思想是“分层训练”:
- 从最接近输入的第一层开始,训练一个 RBM,使其能够较好地重建输入数据。
- 固定第一层的权重,将其输出作为第二层 RBM 的输入,再训练第二层。
- 如此逐层训练,初始化整个网络的权重。
- 最后,使用有标签数据和反向传播对整个网络进行微调。
这种方法相当于为网络提供了一个较好的初始权重点,使其在微调阶段不至于陷入梯度太小的区域。然而,它的训练流程复杂、调参经验性强,随着更简单有效的技术出现,已不再是主流。
ReLU:简单而有效的解决方案
2010 年后,修正线性单元 迅速成为深度学习中最主流的激活函数,它从根本上改变了局面。
ReLU 函数的定义极其简单: 其导数为:
ReLU 如何克服梯度消散?
关键在于其导数。在激活区域(),ReLU 的导数为常数 1。
回顾梯度消散的分析,现在反向传播路径上的激活函数导数项不再是小于 0.25 的 ,而是等于 1(对于处于激活状态的神经元)。这意味着,梯度在通过 ReLU 层时,在激活路径上不再有衰减。梯度衰减的主要来源只剩下权重 的连乘。虽然权重初始化值通常仍小于 1,但衰减速度从原来的 变成了单纯的 ,极大地缓解了梯度消散问题。
此外,ReLU 还有两大优势:
- 计算高效:仅涉及比较和取最大值操作,比计算指数函数的 Sigmoid/Tanh 快得多。
- 引入稀疏性:当输入为负时,ReLU 输出为零。这使得网络中的一部分神经元在训练过程中被“关闭”,整个网络变得“更瘦”。这可以看作一种隐式的正则化,有助于防止过拟合。
下面我们通过一个简单的对比,直观感受 ReLU 和 Sigmoid 在梯度上的差异:
import numpy as np
# 定义函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
def relu(x):
return np.maximum(0, x)
def relu_derivative(x):
return np.where(x > 0, 1.0, 0.0)
# 在[-5, 5]区间采样
x = np.linspace(-5, 5, 11)
print("输入值 x:", x)
print("Sigmoid 导数:", np.round(sigmoid_derivative(x), 4))
print("ReLU 导数: ", np.round(relu_derivative(x), 4))输入值 x: [-5. -4. -3. -2. -1. 0. 1. 2. 3. 4. 5.]
Sigmoid 导数: [0.0066 0.0177 0.0452 0.105 0.1966 0.25 0.1966 0.105 0.0452 0.0177
0.0066]
ReLU 导数: [0. 0. 0. 0. 0. 0. 1. 1. 1. 1. 1.]可以看到,Sigmoid 的导数在 0 附近最大也只有 0.25,并向两侧迅速衰减。而 ReLU 在正半轴的导数恒为 1,为梯度流动提供了“高速公路”。
ReLU 的变体
尽管 ReLU 非常成功,但它也存在“神经元死亡”问题:一旦某个神经元的输入永久落入负半轴,其梯度将永远为零,该神经元再也不会被激活。为此,研究者提出了几种变体:
- Leaky ReLU:,给负半轴一个小的斜率 (如 0.01),让梯度不至于完全为零。
- Parametric ReLU (PReLU):将负半轴的斜率 也作为可学习的参数。
- Exponential Linear Unit (ELU):,试图让激活的均值更接近零,加速收敛。
这些变体在不同场景下各有优劣,但标准 ReLU 因其简单和可靠,仍然是大多数架构的首选起点。
📝 动手练一练
- 概念辨析:假设一个三分类网络的最后一层输出 logits 为
[2.0, -1.0, 0.5]。 a) 请手动计算(或心算估算)经过 Softmax 层后的概率分布。 b) 如果真实标签是第二类(index=1,one-hot 编码为[0, 1, 0]),请估算此时的交叉熵损失值大约是多少?
👉 点击查看参考答案
a) Softmax 计算: 首先计算指数:, , 。 求和:。 概率:, , 。 所以概率分布约为 [0.785, 0.039, 0.175]。
b) 交叉熵损失: 真实标签为第二类,所以只有 ,其他为 0。 损失 。 由于 ,所以 。 这是一个相对较大的损失值,因为模型对正确类别的预测概率很低(0.039),符合交叉熵惩罚错误预测的特性。
- 梯度计算思考:在一个使用 Sigmoid 激活函数的 10 层全连接网络中,假设每层的权重绝对值约为 0.8,每层 Sigmoid 激活函数的导数平均值约为 0.2。请估算,从输出层传播到第一层的梯度,大约会衰减为初始梯度的多少倍?这说明了什么问题?
👉 点击查看参考答案
每层的“梯度衰减因子”约为 。 经过 10 层传播,总衰减因子为 。 计算:。, , 。再平方得到 。 这意味着初始梯度传到第一层时,只剩下约 一亿分之一()。如此微小的梯度几乎无法有效更新底层网络的权重,这就是典型的“梯度消散”问题。它解释了为什么使用 Sigmoid 的深层网络难以训练。
本章小结
本节深入剖析了深度学习在基础组件上对传统神经网络的重大改进。首先,我们看到了目标函数从均方误差到交叉熵的转变,后者与 Softmax 概率输出层相结合,为分类任务提供了更清晰、更陡峭的优化路径,极大地加速了训练收敛。其次,我们揭示了困扰深层网络训练的梯度消散问题的根源——Sigmoid 类激活函数导数值过小且在深层连乘。最后,我们认识了 ReLU 激活函数如何以其简洁的形式(正区间导数为1)有效缓解了梯度消散,并带来了计算高效和网络稀疏化的额外好处,从而成为推动深度学习走向“深度”的关键技术之一。
今天,交叉熵 + Softmax 仍是分类任务的默认组合,ReLU 及其变体(Leaky ReLU、GELU、SiLU 等)仍是绝大多数网络的第一选择。后续的 BatchNorm/LayerNorm、残差连接与更好的初始化,进一步把“深层难训练”这件事系统性地解决了;但“让梯度在反传路上不掉得太快”这一核心思路,正是从本节这几个改动开始的。
📋 行动清单
- 理解交叉熵的优越性:能够用自己的话解释为什么在分类任务中,交叉熵损失比均方误差损失更有效。
- 掌握 Softmax 计算:给定一组 logits,能手动或编程计算出对应的概率分布,并理解其避免零概率的意义。
- 明晰梯度消散与 ReLU 的关系:能清晰阐述 Sigmoid 导致梯度消散的数学原理,以及 ReLU 是如何解决这个问题的。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。