共计 2458 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点:为什么我们需要区分这两者?
刚开始接触 BP 神经网络时,我也经常搞混价值函数(Value Function)和损失函数(Loss Function)。直到有一次训练模型时,遇到了奇怪的震荡收敛问题——损失值忽高忽低,模型就是不肯稳定下来。后来才发现,原来在强化学习任务中错误地使用了均方误差(MSE)作为损失函数,而实际上应该用基于 TD-error 的价值函数。

这类混淆会导致:
- 梯度消失或爆炸(尤其在使用 sigmoid 激活函数时)
- 训练过程出现周期性震荡
- 模型最终收敛到次优解
数学本质:它们到底在计算什么?
损失函数(监督学习)
衡量当前预测值与真实标签的差异,目标是最小化即时误差:
$$ L(\theta) = \frac{1}{N}\sum_{i=1}^N (y_i – f_\theta(x_i))^2 $$
经典例子包括:
- 分类任务:交叉熵损失
- 回归任务:均方误差(MSE)
价值函数(强化学习)
评估状态或动作的长期收益,目标是最大化未来回报的期望:
$$ V^\pi(s) = \mathbb{E}\pi[\sum | s_t = s] $$}^\infty \gamma^k r_{t+k
关键区别在于:
- 时间维度:损失函数看单步,价值函数看多步
- 优化方向:一个最小化,一个最大化
代码实战:PyTorch 中的不同实现
案例 1:分类任务的交叉熵损失
import torch.nn as nn
# 定义网络和损失函数
model = nn.Sequential(nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 10)
)
criterion = nn.CrossEntropyLoss() # 内置自动 softmax
# 训练循环片段
for x, y in dataloader:
outputs = model(x)
loss = criterion(outputs, y) # 计算当前 batch 损失
loss.backward() # 误差反向传播
optimizer.step() # 参数更新
案例 2:DQN 中的价值函数
import torch
import numpy as np
class DQN(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
self.q_network = nn.Sequential(nn.Linear(state_dim, 64),
nn.ReLU(),
nn.Linear(64, action_dim)
)
def forward(self, state):
return self.q_network(state)
# Bellman 方程实现
def compute_q_target(rewards, next_states, dones, gamma=0.99):
with torch.no_grad():
# 下个状态的最大 Q 值
next_q_values = target_network(next_states).max(1)[0]
# 考虑游戏是否结束
q_targets = rewards + gamma * next_q_values * (1 - dones)
return q_targets
# TD-error 计算
current_q_values = q_network(states).gather(1, actions)
loss = nn.MSELoss()(current_q_values, q_targets) # 注意这里用 MSE 计算 TD-error
关键差异点:
- 损失函数直接比较输出与标签
- 价值函数需要通过 Bellman 方程迭代计算目标值
可视化诊断:TensorBoard 实战
安装 TensorBoard 后,可以同时监控两种函数:
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter()
# 在训练循环中添加
writer.add_scalar('Loss/train', loss.item(), global_step)
writer.add_scalar('Value/avg_q', current_q_values.mean(), global_step)
健康训练的特征:
- 损失函数曲线应单调递减(可能有小幅波动)
- 价值函数曲线应逐步上升并趋于稳定
三大常见错误及修复方案
错误 1:在 DQN 中直接使用原始损失函数
- 现象:模型无法学习有效策略
- 修复:改用 TD-error 计算(即预测 Q 值与目标 Q 值的差)
错误 2:价值函数学习率设置过高
- 现象:训练过程剧烈震荡
- 修复:降低学习率,或使用 target network 稳定目标值
错误 3:混淆最大化与最小化方向
- 现象:模型性能越训越差
- 修复:检查优化器设置,价值函数通常需要梯度上升
进阶思考:混合使用会怎样?
在 Actor-Critic 框架中:
- Critic 使用价值函数评估状态价值
- Actor 使用策略梯度更新参数
可以尝试的实验:
- 在 Critic 中同时加入 L2 正则化损失
- 比较纯价值函数与混合损失的效果
- 调整两种函数的权重比例
# 混合损失示例
def actor_critic_loss(states, actions, rewards, next_states):
# 价值函数部分
values = critic(states)
next_values = critic(next_states)
td_targets = rewards + gamma * next_values
value_loss = F.mse_loss(values, td_targets)
# 策略梯度部分
log_probs = actor(states).log_prob(actions)
policy_loss = -(log_probs * (td_targets - values.detach())).mean()
return value_loss + policy_loss # 可以添加权重系数
通过这样的对比实践,相信你能更清晰地把握两者的适用场景。当遇到训练异常时,第一反应就应该是检查:我当前该用价值函数还是损失函数?这个习惯能帮你避开很多坑。
正文完
