1. 梯度下降法:从数学原理到代码实现
梯度下降法是深度学习中最核心的优化算法之一,它的本质是通过迭代寻找函数最小值的方法。让我们用一个最简单的例子来理解这个算法的精髓。
1.1 直观理解梯度下降
假设我们有一个简单的二次函数 y = x²,它的导函数是 y' = 2x。当x=-1时,导数值为-2。这个负导数告诉我们:在x=-1这个点,如果x增大(向右移动),y值会减小。
关键理解:导数的符号决定了搜索方向。负导数意味着我们应该向右移动寻找最小值,正导数则意味着应该向左移动。
这个简单的例子展示了梯度下降的核心思想:通过计算导数(梯度)来确定参数的更新方向,逐步逼近函数的最小值点。
1.2 梯度下降的数学表达
梯度下降的权重更新公式为:
code复制w_new = w_old - η * ∇J(w)
其中:
- η是学习率(learning rate)
- ∇J(w)是损失函数关于参数w的梯度
在我们的例子中,当x=-1,学习率η=0.5时:
code复制x_new = -1 - (0.5 * -2) = 0
正好找到了函数y=x²的最小值点x=0。
1.3 学习率的选择艺术
学习率η控制着每次更新的步长,是梯度下降中最重要的超参数之一:
- η太大:可能跳过最优解,甚至发散
- η太小:收敛速度过慢,训练时间过长
在实际应用中,我们通常会尝试不同的学习率,常见的经验值是0.1、0.01或0.001。更高级的做法是使用学习率衰减策略,随着训练过程逐步减小学习率。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从数学到代码:实现一个简单的深度学习模型
2.1 模型定义与数据准备
我们实现一个简单的二次回归模型:
python复制def func(x_true):
y_predict = w1 * x_true**2 + w2 * x_true + w3
return y_predict
训练数据是通过真实函数Y=2x²+3x+4生成的:
python复制X = [0.01 * x for x in range(100)]
Y = [2*x**2 + 3*x + 4 for x in X]
2.2 关键组件实现
1. 损失函数:使用均方误差(MSE)
python复制def loss(y_predict, y_true):
return (y_predict - y_true) ** 2
2. 梯度计算:手动推导每个参数的偏导数
python复制grad_w1 = 2 * (y_predict - y_true) * x_true ** 2
grad_w2 = 2 * (y_predict - y_true) * x_true
grad_w3 = 2 * (y_predict - y_true)
3. 参数更新:标准的梯度下降更新
python复制w1 = w1 - lr * grad_w1
w2 = w2 - lr * grad_w2
w3 = w3 - lr * grad_w3
2.3 训练过程分析
训练循环的主要步骤:
- 前向传播计算预测值
- 计算损失
- 反向传播计算梯度
- 更新参数
- 重复直到收敛
训练输出示例:
code复制第0轮, loss 3.240000
第1轮, loss 2.332800
...
第999轮, loss 0.000000
训练后权重:w1:2.000018 w2:2.999975 w3:4.000005
可以看到,经过1000轮训练后,模型参数已经非常接近真实值(2,3,4)。
3. 梯度下降的变体与优化技巧
3.1 批量梯度下降 vs 随机梯度下降
我们的示例使用的是批量梯度下降(Batch Gradient Descent),即每次使用全部训练数据计算梯度。在实际中,我们更常用:
-
随机梯度下降(SGD):每次随机选择一个样本计算梯度
- 优点:计算快,适合大数据集
- 缺点:更新方向波动大
-
小批量梯度下降(Mini-batch GD):折中方案,使用一小批数据(如32、64个样本)
- 兼具计算效率和稳定性
3.2 动量法(Momentum)
为了加速收敛并减少震荡,可以引入动量项:
python复制v = γ * v + η * ∇J(w)
w = w - v
其中γ是动量系数(通常0.9),v是速度向量。
3.3 自适应学习率方法
更先进的优化器可以自动调整学习率:
- AdaGrad:为每个参数适应性地调整学习率
- RMSprop:改进的AdaGrad,解决学习率衰减过快问题
- Adam:结合了动量和自适应学习率,最常用的优化器
4. 实战经验与常见问题
4.1 梯度消失与爆炸
在深层网络中,梯度可能会:
- 指数级减小(消失):导致底层参数几乎不更新
- 指数级增大(爆炸):导致参数更新过大,模型不稳定
解决方案:
- 使用ReLU等合适的激活函数
- 批归一化(BatchNorm)
- 残差连接(ResNet)
- 梯度裁剪
4.2 学习率选择策略
- 学习率预热:开始训练时从小学习率开始,逐步增大
- 余弦退火:按余弦曲线调整学习率
- 周期性学习率:在训练过程中周期性变化学习率
4.3 模型初始化技巧
参数初始化对训练成功至关重要:
- Xavier初始化:适合tanh等S型激活函数
- He初始化:适合ReLU系列激活函数
- 正交初始化:保持矩阵的正交性
5. 代码优化与扩展
5.1 向量化实现
原始代码逐个样本计算效率低,可以改为矩阵运算:
python复制def forward(X):
return w1 * X**2 + w2 * X + w3
def backward(X, Y, y_pred):
error = y_pred - Y
grad_w1 = 2 * np.mean(error * X**2)
grad_w2 = 2 * np.mean(error * X)
grad_w3 = 2 * np.mean(error)
return grad_w1, grad_w2, grad_w3
5.2 添加正则化项
为了防止过拟合,可以在损失函数中加入L2正则化:
python复制def loss(y_pred, y_true, w1, w2, w3, lambda_=0.01):
mse = (y_pred - y_true)**2
reg = lambda_ * (w1**2 + w2**2 + w3**2)
return mse + reg
5.3 早停法(Early Stopping)
监控验证集损失,当不再下降时停止训练:
python复制best_loss = float('inf')
patience = 10
counter = 0
for epoch in range(epochs):
# ...训练代码...
val_loss = compute_validation_loss()
if val_loss < best_loss:
best_loss = val_loss
counter = 0
else:
counter += 1
if counter >= patience:
break
6. 从简单模型到深度学习
虽然我们的例子非常简单,但它包含了深度学习的核心要素:
- 前向传播计算预测值
- 定义损失函数衡量预测误差
- 反向传播计算梯度
- 优化算法更新参数
现代深度学习模型如ResNet、Transformer等,本质上都是在这个框架上的扩展和深化。理解这个简单的例子,就掌握了深度学习最核心的优化原理。
