Skip to content

神经网络训练(第一部分)

约 2587 个字 7 行代码 预计阅读时间 17 分钟

概述

训练神经网络时需要考虑三个主要方面:

  1. 一次性设置

    • 激活函数
    • 数据预处理
    • 权重初始化
    • 正则化
  2. 训练动态

    • 学习率调度
    • 大批量训练
    • 超参数优化
  3. 训练后操作

    • 模型集成
    • 迁移学习

本讲座主要关注第一部分:一次性设置。


激活函数

神经网络中常用的激活函数有多种选择,每种都有其特点和适用场景。

[激活函数图:展示不同激活函数的曲线图,包括Sigmoid、tanh、ReLU、Leaky ReLU、ELU和GELU]

Sigmoid函数

\[\sigma(x) = \frac{1}{1 + e^{-x}}\]

特点: * 将数值压缩到 [0,1] 范围内 * 历史上很受欢迎,因为它们有饱和"发射率"的良好解释

但存在三个主要问题:

  1. 饱和神经元"杀死"梯度

    当输入值很大或很小时,梯度接近于零: * 当 x = -10 时,输出接近0,梯度几乎为0 * 当 x = 10 时,输出接近1,梯度几乎为0 * 只有当输入接近0时,梯度才明显不为0

  2. Sigmoid输出不是零中心的

    这会导致权重更新时出现曲折的梯度下降路径,因为: * 如果输入永远是正的,那么关于权重的梯度要么全为正,要么全为负 * 梯度只能在某些方向上移动,需要"曲折"才能到达其他方向

  3. exp()计算成本较高

警告:在实践中,饱和问题是最严重的缺点!

tanh函数(双曲正切)

特点: * 将数值压缩到 [-1,1] 范围内 * 零中心化输出(优点) * 但仍然存在饱和问题,会杀死梯度

ReLU(Rectified Linear Unit)

\[f(x) = \max(0, x)\]

特点: * 正区域不会饱和 * 计算效率很高 * 在实践中比sigmoid/tanh收敛快得多(例如快6倍) * 输出不是零中心的

缺点: * 当输入为负时,梯度为零,这可能导致神经元"死亡"

当x为负值时,ReLU的梯度为0,如果参数不当初始化,可能会导致大量神经元永远不会激活,从而永远不会更新。

解决方法

有时将ReLU神经元的偏置初始化为小的正值(例如0.01)可以缓解这个问题。

Leaky ReLU

\[f(x) = \max(\alpha x, x)\]

其中α是一个超参数,通常设为0.01或0.1。

特点: * 不会饱和 * 计算效率高 * 收敛速度快 * 不会"死亡"

变种:Parametric ReLU (PReLU),其中α是通过反向传播学习的参数。

指数线性单元(ELU)

\[ f(x) = \begin{cases} x & \text{if } x > 0 \\ \alpha(e^x - 1) & \text{if } x \leq 0 \end{cases} \]

特点: * 拥有ReLU的所有优点 * 输出更接近零均值 * 与Leaky ReLU相比,有负饱和区域,对噪声更鲁棒 * 但计算需要exp()

缩放指数线性单元(SELU)

\[\text{selu}(x) = \lambda \begin{cases} x & \text{if } x > 0 \\ \alpha(e^x - 1) & \text{if } x \leq 0 \end{cases} \]

其中: * λ = 1.0507009873554804934193349852946 * α = 1.6732632423543772848170429916717

特点: * ELU的缩放版本,对深度网络效果更好 * 具有"自正则化"特性 * 可以在没有BatchNorm的情况下训练深度SELU网络

高斯误差线性单元(GELU)

\[\text{gelu}(x) = xP(X \leq x) = \frac{x}{2}\left(1 + \text{erf}\left(\frac{x}{\sqrt{2}}\right)\right) \approx x\sigma(1.702x)\]

特点: * 思想:以随机方式将输入乘以0或1 * 值越大,越可能乘以1;值越小,越可能乘以0 * 在Transformer架构(BERT、GPT、ViT)中非常常见

激活函数总结

激活函数选择建议

  • 不要想太多,直接使用ReLU
  • 如果想要获得额外的0.1%性能提升,可以尝试Leaky ReLU/ELU/SELU/GELU
  • 不要使用sigmoid或tanh
  • 一些最新的架构使用GELU而非ReLU,但增益微乎其微

数据预处理

数据预处理对于提高网络训练效率和性能至关重要。

假设X是一个数据矩阵,每行代表一个样本。常见的数据预处理方法包括:

  1. 零中心化

    X -= np.mean(X, axis=0)
    

  2. 标准化

    X /= np.std(X, axis=0)
    

  3. PCA和白化

  4. PCA:主成分分析,使数据协方差矩阵对角化
  5. 白化:使协方差矩阵变为单位矩阵

重要:零中心化数据有助于避免当输入总是正数时梯度更新方向受限的问题!

图像数据的预处理

对于图像数据(例如CIFAR-10的[32,32,3]图像),常见的预处理方法:

  • 减去均值图像(例如AlexNet使用)
  • 均值图像是一个[32,32,3]数组

  • 按通道减去均值(例如VGGNet使用)

  • 每个通道的均值是3个数字

  • 按通道减去均值并除以通道标准差(例如ResNet使用)

  • 每个通道的均值和标准差各是3个数字

对于图像数据,通常不进行PCA或白化处理。

[数据预处理效果图:展示标准化前后对分类损失的影响]


权重初始化

良好的权重初始化对于深度网络的训练至关重要。

问题:全零初始化

如果将所有权重W=0和偏置b=0初始化: * 所有输出都是0 * 所有梯度都相同 * 没有"对称性破缺",网络无法学习不同的特征

小随机数初始化

一种简单的方法是使用均值为0、标准差为0.01的高斯分布初始化权重:

W = 0.01 * np.random.randn(D_in, D_out)

这对小型网络效果尚可,但对于深度网络仍存在问题:

[前向传播激活统计图:展示使用小随机数初始化的6层网络,激活值趋于零]

  • 当深度增加时,激活值趋于0
  • 导致梯度也趋于0,网络无法学习

如果增加初始权重的标准差(从0.01到0.05):

[前向传播激活统计图2:展示使用较大随机数初始化时激活值饱和]

  • 激活值饱和
  • 局部梯度为零,网络同样无法学习

Xavier初始化

Xavier初始化方法:

W = np.random.randn(Din, Dout) / np.sqrt(Din)

特点: * 在所有层中,激活值都能保持适当的比例 * 对于卷积层,Din = kernel_size² * input_channels

数学推导

在前向传播中,如果 \(y = Wx\),并假设 \(x\)\(w\) 是独立同分布的,且均值为0,那么:

\(Var(y_i) = Din * Var(x_i) * Var(w_i)\)

如果 \(Var(w_i) = 1/Din\),则 \(Var(y_i) = Var(x_i)\),即输出方差等于输入方差。

ReLU的修正:Kaiming/MSRA初始化

对于使用ReLU激活函数的网络,Xavier初始化效果不佳,因为ReLU不是零中心的。

Kaiming初始化方法:

W = np.random.randn(Din, Dout) * np.sqrt(2/Din)

残差网络的初始化

残差网络对初始化也有特殊处理:

  • 如果对每个残差块都使用MSRA初始化:\(Var(F(x)) = Var(x)\)
  • 但这会导致 \(Var(F(x) + x) > Var(x)\),方差随着块数增加而增长
  • 解决方案:使用MSRA初始化第一个卷积,将第二个卷积初始化为零

这样确保了 \(Var(x + F(x)) = Var(x)\),保持了方差的稳定性。

提示:合适的初始化是一个活跃的研究领域,不同的网络架构可能需要不同的初始化策略。


正则化

训练神经网络时,避免过拟合是一个关键问题。正则化技术帮助模型更好地泛化。

常见的损失函数正则化

  • L2正则化(权重衰减):添加所有权重平方和的惩罚项
  • L1正则化:添加所有权重绝对值和的惩罚项
  • 弹性网络:L1和L2的结合

Dropout

Dropout是一种简单而强大的正则化技术:

  • 在每次前向传播中,随机将一些神经元置为零
  • 丢弃的概率是一个超参数,通常为0.5
  • 迫使网络学习冗余的特征表示
  • 防止特征的协同适应(co-adaptation)

[Dropout示例图:展示使用Dropout的神经网络前向传播]

测试时的Dropout

Dropout在训练时引入随机性,在测试时需要"平均"这种随机性:

  • 方法1:在测试时不丢弃任何神经元,但将所有激活乘以dropout概率
  • 更常用的方法("倒置dropout"):在训练时就进行缩放调整,测试时无需额外操作
# 训练时的dropout(倒置版本)
p = 0.5  # 保留概率
mask = (np.random.rand(*x.shape) < p) / p  # 除以p进行缩放
out = x * mask

# 测试时
out = x  # 不需要做任何事

Dropout在架构中的应用

  • AlexNet和VGG等早期架构在全连接层使用Dropout
  • GoogLeNet、ResNet等现代架构使用全局平均池化代替全连接层,通常不使用Dropout

正则化的通用模式

许多正则化技术都遵循相同的模式: 1. 训练时:添加某种随机性 2. 测试时:对随机性取平均(有时是近似的)

这一模式的其他例子包括: * 批归一化(Batch Normalization) * 数据增强 * DropConnect * 分数池化(Fractional Pooling) * 随机深度(Stochastic Depth)

数据增强

数据增强是一种强大的正则化技术,通过对训练数据进行变换来增加多样性:

  • 水平翻转:对大多数自然图像都适用
  • 随机裁剪和缩放:增加尺度不变性
  • 训练时:随机采样不同尺度和裁剪
  • 测试时:对多个固定裁剪进行平均

  • 颜色抖动

  • 简单方法:随机调整对比度和亮度
  • 复杂方法:对训练集所有像素进行PCA,沿主成分方向添加随机颜色偏移

  • RandAugment:随机组合多种变换

  • 几何变换:旋转、平移、剪切
  • 颜色变换:锐化、对比度、亮度、曝光等

创新正则化技术

随着研究发展,出现了许多新的正则化方法:

  • Cutout / 随机擦除:将图像的随机区域设为0
  • Mixup:在训练时使用两张图像的随机混合
  • 目标标签也进行相应混合(如40%猫,60%狗)
  • CutMix:将一张图像的随机区域替换为另一张图像
  • 标签平滑:目标分布不是硬标签(如100%猫),而是软标签(如90%猫,10%平均分配给其他类别)

正则化总结

最佳实践

  • 对大型全连接层使用Dropout
  • 数据增强总是一个好主意
  • 对CNN使用BatchNorm(但对ViT不一定需要)
  • 可以尝试Cutout、MixUp、CutMix、随机深度、标签平滑等技术来进一步提升性能

总结

本讲座讨论了训练神经网络时的一次性设置:

  • 激活函数:通常使用ReLU,但也可以考虑Leaky ReLU、ELU、SELU或GELU
  • 数据预处理:对数据进行零中心化和标准化
  • 权重初始化:使用适当的初始化方法,如Xavier或Kaiming初始化
  • 正则化:使用L2正则化、Dropout、数据增强等技术防止过拟合

下一讲将讨论训练动态,包括学习率调度、大批量训练和超参数优化。