1. 什么是Mini-Batch梯度下降法
Mini-Batch梯度下降法是介于批量梯度下降(Batch Gradient Descent)和随机梯度下降(Stochastic Gradient Descent, SGD)之间的一种优化算法。它的工作原理是:
- 将整个训练集分成若干个小批量(mini-batches)
- 每次迭代使用一个小批量来计算梯度并更新参数
- 遍历完所有小批量称为一个epoch
三种梯度下降方法对比:
方法 | 每次迭代使用的样本量 | 优点 | 缺点 |
---|---|---|---|
批量梯度下降 | 全部训练样本 | 梯度计算准确,收敛稳定 | 计算量大,内存要求高 |
随机梯度下降 | 单个样本 | 计算快,可在线学习 | 梯度波动大,收敛不稳定 |
Mini-Batch梯度下降 | 小批量样本 | 平衡计算效率和收敛稳定性 | 需要选择合适的小批量大小 |
2. Mini-Batch梯度下降的优点
- 计算效率:比批量梯度下降更快,因为每次迭代计算量小
- 收敛稳定性:比随机梯度下降更稳定,梯度估计方差小
- 内存友好:特别适合无法将全部数据放入内存的大数据集
- 硬件加速:可以利用现代计算硬件的并行计算能力
3. 代码实现
以下是使用Python和NumPy实现Mini-Batch梯度下降的示例代码:
3.1 线性回归的Mini-Batch梯度下降
python
import numpy as np
import matplotlib.pyplot as plt
# 生成模拟数据
np.random.seed(42)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
# 添加偏置项
X_b = np.c_[np.ones((100, 1)), X]
# Mini-Batch梯度下降参数
n_epochs = 50
batch_size = 10
m = len(X_b) # 样本数量
learning_rate = 0.1
# 随机初始化参数
theta = np.random.randn(2, 1)
# 存储损失历史
loss_history = []
for epoch in range(n_epochs):
# 打乱数据
shuffled_indices = np.random.permutation(m)
X_b_shuffled = X_b[shuffled_indices]
y_shuffled = y[shuffled_indices]
for i in range(0, m, batch_size):
# 获取当前mini-batch
xi = X_b_shuffled[i:i+batch_size]
yi = y_shuffled[i:i+batch_size]
# 计算梯度
gradients = 2/batch_size * xi.T.dot(xi.dot(theta) - yi)
# 更新参数
theta = theta - learning_rate * gradients
# 计算并存储整个训练集的损失
loss = np.mean((X_b.dot(theta) - y)**2)
loss_history.append(loss)
# 绘制训练过程
plt.plot(range(n_epochs), loss_history, 'b-')
plt.xlabel('Epochs')
plt.ylabel('MSE')
plt.title('Mini-Batch Gradient Descent')
plt.show()
print("最终参数:", theta)
3.2 使用PyTorch实现Mini-Batch梯度下降
python
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
# 生成数据
X = torch.rand(100, 1) * 2
y = 4 + 3 * X + torch.randn(100, 1)
# 创建数据集和数据加载器
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=10, shuffle=True)
# 定义线性模型
model = nn.Linear(1, 1)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
# 训练循环
n_epochs = 50
loss_history = []
for epoch in range(n_epochs):
for X_batch, y_batch in dataloader:
# 前向传播
y_pred = model(X_batch)
loss = criterion(y_pred, y_batch)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 计算整个数据集的损失
with torch.no_grad():
y_pred = model(X)
epoch_loss = criterion(y_pred, y)
loss_history.append(epoch_loss.item())
# 绘制训练过程
plt.plot(range(n_epochs), loss_history, 'b-')
plt.xlabel('Epochs')
plt.ylabel('MSE')
plt.title('PyTorch Mini-Batch Gradient Descent')
plt.show()
print("最终参数:")
print("权重:", model.weight.data)
print("偏置:", model.bias.data)
4. Mini-Batch梯度下降的注意事项
-
批量大小的选择:
- 常用值:32, 64, 128, 256
- 较小的批量:更快的训练,但梯度估计噪声大
- 较大的批量:梯度估计更准确,但计算量增加
-
学习率调整:
- Mini-Batch通常需要比批量梯度下降更小的学习率
- 可以考虑学习率衰减策略
-
数据洗牌(Shuffling):
- 每个epoch前洗牌数据很重要,防止模型学习到数据顺序
-
归一化:
- 对输入特征进行归一化可以加速收敛
-
早停(Early Stopping):
- 监控验证集性能,防止过拟合
Mini-Batch梯度下降是现代深度学习中最常用的优化方法之一,大多数深度学习框架都提供了高效实现。在实际应用中,通常使用框架内置的优化器(如PyTorch的SGD或Adam)而不是手动实现。