训练流程中的功能组件 - 优化器
训练流程中的功能组件 - 优化器flyfish真实规律是y 2x 3我们给数据加一点噪声。模型只有 2 个可学习参数权重w和偏置b。训练的目标就是让模型自动学到 wb优化器主要是接收反向传播算出的梯度按照自身算法规则更新模型的可学习参数权重、偏置驱动损失函数持续下降。importtorch# --------------------------# 1. 准备训练数据# --------------------------# 生成100个x样本从0到10均匀分布xtorch.linspace(0,10,100).reshape(-1,1)# 真实值 y 2x 3加一点随机噪声模拟真实数据y_true2*x3torch.randn_like(x)*0.5# --------------------------# 2. 初始化可学习参数 超参数# --------------------------# 随机初始化w和brequires_gradTrue 表示需要对它们求梯度wtorch.randn(1,requires_gradTrue)btorch.randn(1,requires_gradTrue)learning_rate0.01# 学习率epochs200# 训练总轮数# --------------------------# 3. 训练循环手动实现优化器# --------------------------forepochinrange(epochs):# 1前向传播输入x算出预测值y_predw*xb#2 计算损失均方误差预测值和真实值的差的平方取平均losstorch.mean((y_pred-y_true)**2)# 3 反向传播自动算出w和b的梯度存在 w.grad 和 b.grad 里loss.backward()# # 这里就是优化器的逻辑# # 关闭梯度追踪只做纯数值更新避免生成计算图浪费资源withtorch.no_grad():# 核心更新公式新参数 旧参数 - 学习率 × 梯度w-learning_rate*w.grad b-learning_rate*b.grad# 梯度清零把w.grad和b.grad重置为0避免下一轮累加旧梯度w.grad.zero_()b.grad.zero_()# # 每20轮打印一次结果if(epoch1)%400:print(f轮次{epoch1:3d}| 损失:{loss.item():.4f}| w{w.item():.4f}| b{b.item():.4f})# 训练结束看最终结果print(f\n训练完成最终w{w.item():.4f}最终b{b.item():.4f})print(真实值w2b3)代码中with torch.no_grad()里的两行 梯度清零是最基础的随机梯度下降SGD优化器的功能。它做两件事参数更新对应PyTorch的optimizer.step()按照固定公式新参数 旧参数 - 学习率 × 梯度逐个更新所有可学习参数。梯度告诉我们参数往哪个方向调能让损失变小学习率控制调多大幅度。梯度清零对应PyTorch的optimizer.zero_grad()PyTorch 默认会累加梯度每轮更新完必须手动清零否则下一轮的梯度会叠加上旧值导致更新完全错误。优化器就是参数更新规则的封装。使用PyTorch自带的torch.optim实现importtorch# 数据和参数初始化和上面完全一样xtorch.linspace(0,10,100).reshape(-1,1)y_true2*x3torch.randn_like(x)*0.5wtorch.randn(1,requires_gradTrue)btorch.randn(1,requires_gradTrue)learning_rate0.01epochs200# SGD优化器把所有参数交给它管理optimizertorch.optim.SGD([w,b],lrlearning_rate)forepochinrange(epochs):y_predw*xb losstorch.mean((y_pred-y_true)**2)# 对应手动的 w.grad.zero_(); b.grad.zero_()optimizer.zero_grad()# 反向传播算梯度loss.backward()# 对应手动的 w - lr*w.grad; b - lr*b.gradoptimizer.step()if(epoch1)%400:print(f轮次{epoch1:3d}| 损失:{loss.item():.4f}| w{w.item():.4f}| b{b.item():.4f})省去了逐个参数手写更新、逐个清零的麻烦可以把epoch加大看效果轮次40|损失:0.8172|w2.2211|b1.5349轮次80|损失:0.6443|w2.1822|b1.7936轮次120|损失:0.5282|w2.1504|b2.0055轮次160|损失:0.4503|w2.1243|b2.1792轮次200|损失:0.3979|w2.1029|b2.3215在单轮训练迭代中优化器的执行逻辑接收梯度输入获取由反向传播算法计算得到的损失函数对各参数的一阶导数梯度∇L(θ)\nabla L(\boldsymbol{\theta})∇L(θ)该信息指明了参数空间中损失上升最快的方向与速率。计算参数更新量基于当前梯度、历史梯度状态与预设超参数计算每个参数的更新方向与步长生成参数更新向量Δθ\Delta\boldsymbol{\theta}Δθ。这是优化器的核心功能不同优化算法的差异均体现于此基础随机梯度下降SGD仅以全局学习率对梯度做线性缩放即Δθ−η⋅∇L(θ)\Delta\boldsymbol{\theta} -\eta \cdot \nabla L(\boldsymbol{\theta})Δθ−η⋅∇L(θ)所有参数共享统一的步长缩放系数自适应优化器如Adam会额外维护每个参数的梯度一阶矩动量与二阶矩波动幅度统计量为每个参数动态适配更新步长在梯度波动剧烈的维度收窄步长以抑制震荡在梯度平缓的维度放大步长以加速收敛。执行参数更新与状态维护按照θ←θΔθ\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} \Delta\boldsymbol{\theta}θ←θΔθ更新所有可学习参数的数值同时清零参数的梯度缓存避免迭代间梯度累加导致更新偏差并更新优化算法所需的历史状态变量供后续迭代使用。