【NumPy】MNIST上深度学习计算过程理解:四、激活函数和Dropout
【NumPy】MNIST上深度学习计算过程理解:四、激活函数和Dropout
一、背景
基于对应链接示例上的深度学习过程,对每一步进行详细的说明,方便数据和实例的结合理解深度学习的过程。
示例的简单介绍:提供0-9的数字灰度照片进行深度学习训练,数据包括6万张训练图像和1万张测试图像以及对应的标签(即0-9的标签)。图像的像素为28*28,大小为784。
续:前向传播内部说明
二、激活函数(神经网络的”灵魂“)
激活函数是神经网络能够学习复杂模式的关键所在,其主要作用包括:
- 引入非线性:如果没有激活函数,无论神经网络有多少层,都只是线性变换的组合,最终仍然等价于一个线性模型。激活函数的非线性使网络能够逼近任意复杂函数。
- 决定神经元是否激活:根据输入信号的强度,决定神经元是否被激活(输出非零值)。
- 控制输出范围:不同激活函数将输出值限制在不同范围内(如Sigmoid在0-1,Tanh在-1到1,ReLU在0到正无穷)。
数学证明
假设我们有一个3层无激活函数的网络:
- 第1层:
h₁ = W₁·x + b₁ - 第2层:
h₂ = W₂·h₁ + b₂ = W₂·(W₁·x + b₁) + b₂ - 第3层:
y = W₃·h₂ + b₃ = W₃·(W₂·(W₁·x + b₁) + b₂) + b₃
展开并重新组合:
y = W₃·W₂·W₁·x + W₃·W₂·b₁ + W₃·b₂ + b₃
= (W₃·W₂·W₁)·x + (W₃·W₂·b₁ + W₃·b₂ + b₃)
= W_combined·x + b_combined
其中:W_combined = W₃·W₂·W₁,b_combined = W₃·W₂·b₁ + W₃·b₂ + b₃
结论:无论多少层,最终都可以合并为单个线性变换 y = W·x + b,这就是线性回归模型!
三、Dropout(防止过拟合的"正则化大师")
Dropout是一种在训练期间随机"丢弃"(置零)部分神经元输出的技术,其核心作用包括:
- 防止过拟合:通过随机丢弃神经元,阻止网络过度依赖某些特定特征或神经元组合。
- 促进鲁棒性:迫使每个神经元都能独立发挥作用,而不是依赖于其他特定神经元。
- 实现模型平均:Dropout训练相当于训练了大量共享权重的子网络,测试时相当于这些子网络的集合预测。
扩展之前的实例,加入Dropout机制:
原始前向传播(无Dropout):
z1 = [0.18, 0.26]
a1 = relu(z1) = [0.18, 0.26] # 两个神经元都激活
z2 = a1 · W2 = [0.192, -0.064]
加入Dropout(丢弃率50%):
假设随机生成的Dropout掩码为[1, 0](丢弃第二个神经元):
python
# 前向传播(训练时)
z1 = [0.18, 0.26]
a1 = relu(z1) = [0.18, 0.26]
dropout_mask = [1, 0] # 随机生成,50%概率为0
a1_dropout = a1 * dropout_mask = [0.18, 0] # 第二个神经元被"丢弃"
# 继续前向传播
z2_dropout = a1_dropout · W2
= [0.18, 0] · [[0.2, -0.5], [0.6, 0.1]]
= [0.18*0.2 + 0*0.6, 0.18*(-0.5) + 0*0.1]
= [0.036, -0.09] # 与无Dropout的结果不同!
反向传播的影响:
由于第二个神经元被丢弃,其梯度也为0:
python
# 反向传播时,被丢弃神经元的梯度为0
∂L/∂a1_dropout = [0.5522, -0.0874] # 正常计算的梯度
∂L/∂a1 = ∂L/∂a1_dropout * dropout_mask = [0.5522, 0] # 第二个神经元的梯度被屏蔽
多次迭代中的Dropout效果展示
让我们通过一个简单表格展示不同训练迭代中Dropout的影响:
| 迭代次数 | Dropout掩码 | 激活的神经元 | 网络行为 | 学习效果 |
|---|---|---|---|---|
| 第1次 | [1, 0] | 仅神经元1 | 学习特征A | 神经元1的权重被调整 |
| 第2次 | [0, 1] | 仅神经元2 | 学习特征B | 神经元2的权重被调整 |
| 第3次 | [1, 1] | 两个神经元 | 综合学习 | 两个神经元协同工作 |
| 第4次 | [1, 0] | 仅神经元1 | 巩固特征A | 神经元1进一步优化 |
Dropout的核心思想:通过强迫不同神经元在不同时间独立工作,防止它们形成复杂的共适应关系(co-adaptation),从而增强泛化能力。
四、实例(激活函数与Dropout的协同作用)
1. 实例场景
考虑一个识别猫耳朵的简单任务:
- 神经元1:检测"三角形形状"
- 神经元2:检测"毛茸茸纹理"
- 神经元3:检测"尖尖的顶端"
2. 无Dropout的问题
在没有Dropout的情况下,网络可能学会:
如果(神经元1 AND 神经元3) -> 猫耳朵
这种依赖特定神经元组合的模式容易过拟合训练数据中的偶然模式。
3. 有Dropout的健壮学习
加入Dropout后,网络被迫学习:
- 当神经元1被丢弃时:必须用神经元2和3判断
- 当神经元3被丢弃时:必须用神经元1和2判断
- 最终学会:
神经元1 OR 神经元2 OR 神经元3都能提供部分证据
4. 数值模拟
# 模拟10次训练迭代中Dropout的影响
training_iterations = 10
dropout_rate = 0.5
neurons = ['N1(形状)', 'N2(纹理)', 'N3(尖端)']
for i in range(training_iterations):
# 随机生成Dropout掩码
mask = np.random.binomial(1, 1-dropout_rate, size=3)
# 模拟网络激活
activated = [neurons[j] for j in range(3) if mask[j]==1]
print(f"迭代 {i+1}: 掩码={mask}, 激活的神经元={activated}")
print(f" 学习模式: 基于{' + '.join(activated) if activated else '无'}判断猫耳朵")
print()
输出示例:
迭代 1: 掩码=[1 0 1], 激活的神经元=['N1(形状)', 'N3(尖端)']
学习模式: 基于N1(形状) + N3(尖端)判断猫耳朵
迭代 2: 掩码=[0 1 1], 激活的神经元=['N2(纹理)', 'N3(尖端)']
学习模式: 基于N2(纹理) + N3(尖端)判断猫耳朵
迭代 3: 掩码=[1 1 0], 激活的神经元=['N1(形状)', 'N2(纹理)']
学习模式: 基于N1(形状) + N2(纹理)判断猫耳朵
4. 效果对比:有无激活函数和Dropout
| 网络配置 | 训练准确率 | 测试准确率 | 泛化能力 | 训练稳定性 |
|---|---|---|---|---|
| 无激活函数 | 低 | 低 | 差 | 稳定但性能有限 |
| 有ReLU无Dropout | 高 | 中等 | 一般 | 可能不稳定 |
| 有ReLU有Dropout | 中等偏高 | 高 | 优秀 | 更稳定 |
更多推荐
所有评论(0)