图像分类中的批量归一化与高精度实现
立即解锁
发布时间: 2025-09-02 00:52:51 阅读量: 7 订阅数: 24 AIGC 

# 图像分类中的批量归一化与高精度实现
## 1. 批量归一化(Batch Normalization)概述
在深度学习中,数据归一化是加速学习过程的重要手段。之前我们主要关注在将训练集输入到输入层之前对其进行预处理。然而,如果输入层能从归一化中受益,那么对隐藏单元中不断变化的提取特征进行同样的操作,是否能进一步提升训练速度和网络的鲁棒性呢?这就是批量归一化(Batch Normalization,简称 BN)的核心思想。
### 1.1 协变量偏移问题(Covariate Shift Problem)
为了理解 BN 要解决的问题,我们先看一个例子。假设我们正在构建一个猫分类器,并且仅使用白色猫的图像来训练算法。当我们用不同颜色猫的图像来测试这个分类器时,它的表现会很差。这是因为模型是在具有特定分布(白色猫)的训练集上进行训练的,当测试集的数据分布发生变化时,模型就会产生混淆。
这种数据分布的变化被称为协变量偏移。如果一个模型正在学习将数据集 X 映射到标签 y,当 X 的分布发生变化时,就会出现协变量偏移,此时可能需要重新训练学习算法。
### 1.2 神经网络中的协变量偏移
以一个简单的四层多层感知机(MLP)为例,从第三层(L3)的角度来看,它的输入是第二层(L2)的激活值。随着网络的训练,第一层的参数(w, b)会发生变化,进而导致第二层的激活值也不断变化。因此,从第三层的视角看,第二层的值一直在改变,这就导致 MLP 面临协变量偏移的问题。
批量归一化可以减少隐藏单元值分布的变化程度,使这些值更加稳定,从而让神经网络的后续层有更坚实的基础。需要注意的是,批量归一化并不会消除或减少隐藏单元值的变化,而是确保这种变化的分布保持不变,即即使单元的具体值发生变化,其均值和方差也不会改变。
### 1.3 批量归一化的工作原理
在 2015 年的论文 “Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift” 中,Sergey Ioffe 和 Christian Szegedy 提出了 BN 技术来减少协变量偏移。批量归一化在神经网络的每一层激活函数之前添加一个操作,具体步骤如下:
1. **零中心化输入**:算法需要计算输入的均值和标准差(这里的输入指的是当前的小批量数据,因此称为批量归一化)。
- 小批量均值:$\mu_B \leftarrow \frac{1}{m} \sum_{i=1}^{m} x_i$
- 小批量方差:$\sigma_B^2 \leftarrow \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu_B)^2$
其中,$m$ 是小批量中的实例数量,$\mu_B$ 是均值,$\sigma_B$ 是当前小批量的标准差。
2. **归一化零中心化输入**:
- $\hat{x}_i \leftarrow \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}$
其中,$\hat{x}$ 是零中心化和归一化后的输入,$\epsilon$ 是一个小的数(通常为 $10^{-5}$),用于避免在某些估计中 $\sigma$ 为零时的除零错误。
3. **缩放和偏移结果**:将归一化后的输出乘以变量 $\gamma$ 进行缩放,并加上 $\beta$ 进行偏移。
- $y_i \leftarrow \gamma \hat{x}_i + \beta$
其中,$y_i$ 是 BN 操作的输出,经过了缩放和偏移。
批量归一化引入了两个新的可学习参数 $\gamma$ 和 $\beta$,优化算法会像更新权重和偏置一样更新它们。在实践中,这意味着在开始时训练可能会比较慢,因为梯度下降(GD)正在为每一层寻找最优的缩放和偏移值,但一旦找到合理的值,训练速度就会加快。
### 1.4 Keras 中批量归一化的实现
在 Keras 中,添加批量归一化到神经网络非常简单,只需在隐藏层之后添加一个 BN 层,以在将结果输入到下一层之前对其进行归一化。以下是一个示例代码:
```python
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers.normalization import BatchNormalization
model = Sequential()
model.add(Dense(hidden_units, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(units, activation='relu'))
model.add(BatchNormalization())
model.add(Dense(2, activation='softmax'))
```
在这个代码中,我们首先导入了必要的库,然后初始化了一个顺序模型。接着添加了第一个隐藏层,并在其后添加了批量归一化层。如果要在网络中添加 dropout,建议在批量归一化层之后添加,以确保随机关闭的节点不会错过归一化步骤。最后添加了第二个隐藏层、批量归一化层和输出层。
### 1.5 批量归一化总结
批量归一化不仅将归一化过程应用于输入层,还应用于神经网络的隐藏层。这削弱了前层和后层学习过程之间的耦合,使网络的每一层能够更独立地学习。从网络的后层来看,前层的变化不会太大,因为它们被约束为具有相同的均值和方差,这使得后层的学习任务更加容易。
## 2. 项目:实现图像分类的高精度
### 2.1 项目概述
在这个项目中,我们将重新审视 CIFAR - 10 分类项目,并应用本章中的一些改进技术,将准确率从约 65% 提高到约 90%。我们将按照以下步骤完成项目:
1. 导入依赖项
2. 准备训练数据
3. 构建模型架构
4. 训练模型
5. 评估模型
6. 绘制学习曲线
### 2.2 步骤 1:导入依赖项
以下是导入所需依赖项的 Keras 代码:
```python
import keras
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.utils import np_utils
from keras.layers import Dense, Activation, Flatten, Dropout, BatchNormalization, Conv2D, MaxPooling2D
from keras.callbacks import ModelCheckpoint
from keras import regularizers, optimizers
import numpy as np
from matplotlib import pyplot
```
### 2.3 步骤 2:准备训练数据
#### 2.3.1 下载和拆分数据
Keras 提供了 CIFAR - 10 数据集,我们可以直接下载并将其拆分为训练集和测试集。然后,我们将训练集进一步拆分为 45,000 张用于训练的图像和 5,000 张用于验证的图像。
```python
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
(x_train, x_valid) = x_train[5000:], x_train[:5000]
(y_train, y_valid) = y_train[5000:], y_train[:5000]
print('x_train =', x_train.shape)
print('x_valid =', x_valid.shape)
print('x_test =', x_test.sh
```
0
0
复制全文
相关推荐









