优先监控验证损失(val_loss),因其更稳定;需确保是平均batch loss、标量且用.item()提取;早停类只需维护best_score等三个状态,通过minimize参数统一处理方向;验证时须禁用梯度并及时清理显存。

早停判断该用验证损失还是验证准确率?
验证损失(val_loss)更稳定,尤其在类别不平衡或损失函数含正则项时;验证准确率(val_acc)易受阈值、样本分布影响,小幅波动就可能误触发早停。默认优先监控 val_loss,且必须是**平均每个 batch 的 loss**(不是累计值),否则 batch size 变化会导致数值漂移。
- 确保
val_loss 是标量:调用 .item() 后再传入早停逻辑
- 避免用
torch.no_grad() 之外的上下文计算验证 loss,否则可能意外启用梯度导致显存泄漏
- 如果任务是多分类且最后一层是
nn.LogSoftmax + nn.NLLLoss,验证 loss 天然可比;若用 nn.CrossEntropyLoss,注意它已内置 softmax,别重复激活
PyTorch 中最简可用的早停类怎么写?
不需要继承或复杂封装,一个轻量 EarlyStopping 类就够用,核心只维护三个状态:best_score、counter、patience。关键在「方向」控制——loss 越小越好,acc 越大越好,统一用 minimize 布尔值处理:
class EarlyStopping:
def __init__(self, patience=7, minimize=True, delta=0.):
self.patience = patience
self.minimize = minimize
self.delta = delta
self.best_score = None
self.counter = 0
self.early_stop = False
<pre class="brush:python;toolbar:false;">def __call__(self, score):
if self.best_score is None:
self.best_score = score
elif (self.minimize and score self.best_score + self.delta):
self.best_score = score
self.counter = 0
else:
self.counter += 1
if self.counter >= self.patience:
self.early_stop = True
-
delta=0. 表示严格单调,设为 1e-4 可容忍微小抖动
- 不要在
<strong>call</strong> 里保存模型,那是训练循环的责任;早停类只做判断
- 每次验证后立即调用,不要等到 epoch 结束再批量判断
验证阶段报错 “CUDA out of memory” 怎么和早停一起缓解?
早停本身不省显存,但验证频繁 + 显存未释放是常见组合问题。根本原因常是验证时没禁用梯度计算,或中间变量被隐式保留在计算图中。
- 验证前加
model.eval(),验证后记得 model.train()(尤其在 epoch 内多次验证时)
- 验证 loop 内必须包在
with torch.no_grad(): 下,否则 loss.backward() 可能残留
- 清空验证 batch 的中间 tensor:显式删掉
outputs、loss 等变量,再调用 torch.cuda.empty_cache()(仅调试时用,线上慎用)
- 如果验证集太大,考虑用
torch.utils.data.Subset 抽样 20% 代替全量验证,早停对趋势敏感,不依赖绝对精度
val_loss 是标量:调用 .item() 后再传入早停逻辑 torch.no_grad() 之外的上下文计算验证 loss,否则可能意外启用梯度导致显存泄漏 nn.LogSoftmax + nn.NLLLoss,验证 loss 天然可比;若用 nn.CrossEntropyLoss,注意它已内置 softmax,别重复激活 EarlyStopping 类就够用,核心只维护三个状态:best_score、counter、patience。关键在「方向」控制——loss 越小越好,acc 越大越好,统一用 minimize 布尔值处理:
class EarlyStopping:
def __init__(self, patience=7, minimize=True, delta=0.):
self.patience = patience
self.minimize = minimize
self.delta = delta
self.best_score = None
self.counter = 0
self.early_stop = False
<pre class="brush:python;toolbar:false;">def __call__(self, score):
if self.best_score is None:
self.best_score = score
elif (self.minimize and score self.best_score + self.delta):
self.best_score = score
self.counter = 0
else:
self.counter += 1
if self.counter >= self.patience:
self.early_stop = True
-
delta=0.表示严格单调,设为1e-4可容忍微小抖动 - 不要在
<strong>call</strong>里保存模型,那是训练循环的责任;早停类只做判断 - 每次验证后立即调用,不要等到 epoch 结束再批量判断
验证阶段报错 “CUDA out of memory” 怎么和早停一起缓解?
早停本身不省显存,但验证频繁 + 显存未释放是常见组合问题。根本原因常是验证时没禁用梯度计算,或中间变量被隐式保留在计算图中。
- 验证前加
model.eval(),验证后记得 model.train()(尤其在 epoch 内多次验证时)
- 验证 loop 内必须包在
with torch.no_grad(): 下,否则 loss.backward() 可能残留
- 清空验证 batch 的中间 tensor:显式删掉
outputs、loss 等变量,再调用 torch.cuda.empty_cache()(仅调试时用,线上慎用)
- 如果验证集太大,考虑用
torch.utils.data.Subset 抽样 20% 代替全量验证,早停对趋势敏感,不依赖绝对精度
model.eval(),验证后记得 model.train()(尤其在 epoch 内多次验证时) with torch.no_grad(): 下,否则 loss.backward() 可能残留 outputs、loss 等变量,再调用 torch.cuda.empty_cache()(仅调试时用,线上慎用) torch.utils.data.Subset 抽样 20% 代替全量验证,早停对趋势敏感,不依赖绝对精度 早停真正起效的前提是验证信号干净——loss 曲线得真实反映泛化能力退化,而不是被 batch norm 统计、dropout 随机性或数据加载器 shuffle 扰动掩盖。这点比选哪个 patience 数值重要得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











