趋近智
一旦我们定义了神经网络 (neural network)结构并选择了合适的损失函数 (loss function)来衡量其误差,下一步就是实际训练模型。这个学习过程包括调整模型的参数 (parameter)(权重 (weight)和偏置 (bias))以使计算出的损失最小化。优化器是执行这项重要任务的算法,有效地引导模型的学习过程。你可以把优化器看作是推动模型获得更好表现的引擎。它借助损失函数的信息智能地更新模型参数。
深度学习 (deep learning)中的大多数优化算法都基于梯度下降原理。核心思路很简单:要最小化一个函数(我们的损失函数 (loss function)),我们应该沿着其梯度的反方向迈步。梯度,你可能还记得,指向最陡峭的上升方向。因此,逆着它移动,我们就能趋近最小值。
在模型学习过程中,参数 (parameter)更新的幅度由一个超参数 (hyperparameter)决定,该超参数称为学习率,通常用 (eta)表示。参数 的基本更新规则如下:
这里, 是损失函数 相对于参数 的梯度。
实际上,我们通常不是对整个数据集(这将是批量梯度下降)计算梯度,而是对称为小批量的数据子集计算。这种方法称为**随机梯度下降(SGD)**或小批量梯度下降,它在计算效率和稳定收敛之间提供了很好的平衡。
Flux.jl 在其 Flux.Optimise 模块中提供了一系列预设的优化器,每种都有不同的参数调整策略。让我们看看几种常用优化器。
这是最基本的优化器。它为每个小批量实现基本的梯度下降更新规则。
using Flux
# 学习率为 0.01
opt_sgd = SGD(0.01)
特点:
动量优化器在 SGD 的基础上添加了一个“速度”分量。它累积一部分过去的梯度更新,并用它来影响当前的更新方向。这有助于减弱震荡并加速学习,尤其是在梯度方向一致的区域。想象一个球滚下山坡;它会积累动量,不容易卡在小坑里。
更新涉及一个速度项 : (或类似的包含 的公式) (如果 不在 中) 这里, 是动量系数,通常为 0.9 左右。
在 Flux.jl 中,你可以使用 Momentum:
# 学习率为 0.01,动量为 0.9
opt_momentum = Momentum(0.01, 0.9)
通常,Momentum 会与 SGD 或其他优化器隐含地使用,或者作为增强 SGD 的独立选项。Flux 的 Momentum 构造函数接受学习率和动量系数(通常表示为 或 )。
特点:
Adam 是一种自适应学习率优化算法,已成为许多深度学习应用的非常普遍的默认选择。它通过跟踪过去梯度的指数衰减平均值(一阶矩,类似于动量)和过去平方梯度的指数衰减平均值(二阶矩,类似于 RMSProp)来为每个参数 (parameter)计算自适应学习率。
# 默认学习率为 0.001,默认 beta 值为 (0.9, 0.999)
opt_adam = Adam()
# 自定义学习率
opt_adam_custom = Adam(0.0005)
# 自定义学习率和 beta 值
opt_adam_full_custom = Adam(0.001, (0.9, 0.999))
特点:
Flux.jl 还提供了其他优化器,例如 RMSProp、AdaGrad、AdaMax 和 NAdam,每种都有其特定的更新规则和特点。对于许多问题来说,Adam 是一个很好的起始选择。
要在 Flux 中使用优化器,首先需要指定它应该更新模型的哪些参数 (parameter)。Flux.params() 函数用于从模型或层中收集所有可训练的参数。
假设你已经定义了一个 model 和一个 loss_function:
# model 和 loss_function 已定义
ps = Flux.params(model)
# 实例化一个优化器
opt = Adam(0.001) # 使用 Adam,学习率为 0.001
# 示例数据点 (x_batch, y_batch)
# x_batch 是你的输入,y_batch 是目标输出
# 在你的训练循环中:
# 1. 计算梯度
grads = gradient(() -> loss_function(model(x_batch), y_batch), ps)
# 2. 使用优化器更新参数
Flux.Optimise.update!(opt, ps, grads)
在这段代码中:
ps = Flux.params(model) 从你的 model 中收集所有符合训练条件的参数(权重 (weight)、偏置 (bias))。opt = Adam(0.001) 创建一个 Adam 优化器实例。gradient(() -> loss_function(model(x_batch), y_batch), ps) 计算损失相对于参数 ps 的梯度。这就是自动微分发挥作用的地方,我们将在下一节讨论它。Flux.Optimise.update!(opt, ps, grads) 使用计算出的 grads 应用优化器的更新规则来修改参数 ps。Flux 还提供了一个更高级的 Flux.train! 辅助函数,它封装了梯度计算和更新步骤,这可以简化你的训练循环代码。我们将在后面的章节中看到更多关于 Flux.train! 的内容。
选择最佳的优化器及其超参数 (parameter) (hyperparameter),特别是学习率,会大幅影响训练速度和模型表现。
下图抽象地展示了不同优化器如何在一个误差曲面上行进:
不同的优化器采用不同的策略在误差曲面上行进,目标是高效地找到导致模型误差低的参数值。
优化器是主力,它们根据模型看到的数据和犯的错误迭代地改进模型。它们依赖于精确的梯度来指导其更新。在下一节“Zygote.jl:Flux 中的自动微分”中,我们将研究 Flux.jl 如何在 Zygote.jl 的帮助下,高效地计算几乎任何 Julia 代码的这些必需梯度,构成训练过程的主干。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•