sam
SAM(Sharpness-Aware Minimization)是一款基于 PyTorch 的优化器工具,旨在通过同时最小化损失值与损失锐度,显著提升深度学习模型的泛化能力。传统优化方法往往只关注找到损失函数的最低点,却容易陷入尖锐的局部极小值,导致模型在未知数据上表现不佳;而 SAM 专门寻找那些周围邻域损失均较低的平坦极小值区域。这种机制不仅让模型在多个数据集上达到了业界领先的性能,还赋予其极强的抗标签噪声鲁棒性。
从技术实现来看,SAM 作为一个轻量级封装器,可无缝对接 SGD 等基础优化器。其核心亮点在于独特的“两步更新”策略:每次迭代需进行两次前向与反向传播,先探测损失曲面的锐度方向,再执行针对性的参数更新,从而引导模型收敛至更宽、更稳定的最优解。不过需要注意的是,由于计算量加倍,训练速度约为常规方法的一半,且在使用批归一化(BatchNorm)时需留意统计量的计算时机。
SAM 非常适合从事深度学习算法研究的研究人员,以及希望提升模型最终表现和稳定性的 AI 开发者。如果你正在处理噪声较大的数据集,或追求极致的泛化效果,SAM 是一个值得尝试的高效解决方案。
使用场景
某医疗影像初创团队正在训练一个基于 ResNet 的肺炎检测模型,旨在提升模型在未知医院数据上的泛化能力。
没有 sam 时
- 模型在内部测试集上准确率高达 98%,但部署到合作医院的真实数据时,性能骤降至 82%,出现严重的过拟合现象。
- 损失函数收敛到了尖锐的局部极小值(Sharp Minimum),导致参数对输入数据的微小扰动极其敏感,鲁棒性差。
- 面对医疗标注中不可避免的噪声(如医生判断差异),模型容易强行记忆错误标签,难以学习到真正的病理特征。
- 为了缓解泛化问题,工程师不得不花费大量时间手动调整学习率、增加 Dropout 比例或引入复杂的数据增强策略,调参成本极高。
使用 sam 后
- 模型主动寻找“平坦”的损失最小值区域(Flat Minimum),在未见过的医院数据上准确率稳定在 94%,泛化差距显著缩小。
- 通过同时最小化损失值及其锐度,模型参数位于低损失的邻域内,对数据噪声和分布偏移表现出极强的抵抗力。
- 即使训练数据包含约 15% 的误标样本,sam 也能有效抑制模型对噪声的过拟合,表现媲美专门针对噪声标签设计的算法。
- 无需繁琐的额外正则化技巧,仅需将优化器替换为 sam 包装器(配合 SGD),即可在两次前向传播的计算代价下获得 State-of-the-Art 的性能。
sam 通过引导模型收敛至更平坦的最优解,以微小的计算开销换取了显著的泛化提升和抗噪鲁棒性,是解决深度学习模型“落地难”问题的关键利器。
运行环境要求
未说明(支持多 GPU 并行训练,需使用 model.no_sync() 处理梯度同步)
未说明

快速开始
(自适应)SAM 优化器
锐度感知最小化:高效提升泛化能力
~ 基于 PyTorch ~
SAM 同时最小化损失值和损失的锐度。具体而言,它寻找位于具有均匀低损失的邻域中的参数。SAM 能够提升模型的泛化能力,并在多个数据集上达到 当前最优性能。此外,它对标签噪声的鲁棒性与专门针对带噪声标签学习的当前最优方法相当。
这是一个关于 锐度感知最小化:高效提升泛化能力 和 ASAM:用于深度神经网络尺度不变学习的自适应锐度感知最小化 的 非官方 代码库。从实现上看,SAM 类是一个轻量级封装,用于计算正则化的“锐度感知”梯度,该梯度由底层优化器(如带有动量的 SGD)使用。本仓库还包含一个简单的 CIFAR-10 WRN 示例;作为概念验证,它在该数据集上的表现优于带有动量的 SGD。
训练结束时,ResNet 在有 SAM 和无 SAM 情况下的损失景观。锐度感知更新会导致更宽的极小值区域,从而带来更好的泛化性能。
使用方法
在你的训练流程中使用 SAM 应该非常直观。需要注意的是,训练速度会减慢一倍,因为 SAM 需要两次前向和反向传播来估计“锐度感知”梯度。如果你使用梯度裁剪,请确保只调整梯度的大小,而不改变其方向。
from sam import SAM
...
model = YourModel()
base_optimizer = torch.optim.SGD # 定义用于“锐度感知”更新的优化器
optimizer = SAM(model.parameters(), base_optimizer, lr=0.1, momentum=0.9)
...
for input, output in data:
# 第一次前向-反向传播
loss = loss_function(output, model(input)) # 使用此损失记录任何训练统计信息
loss.backward()
optimizer.first_step(zero_grad=True)
# 第二次前向-反向传播
loss_function(output, model(input)).backward() # 确保完成完整的前向传播
optimizer.second_step(zero_grad=True)
...
另一种使用方式:基于闭包的单次 step 函数。这种方式提供了与 PyTorch 原生优化器(如 LBFGS)类似的 API(由 @rmcavoy 友好建议):
from sam import SAM
...
model = YourModel()
base_optimizer = torch.optim.SGD # 定义用于“锐度感知”更新的优化器
optimizer = SAM(model.parameters(), base_optimizer, lr=0.1, momentum=0.9)
...
for input, output in data:
def closure():
loss = loss_function(output, model(input))
loss.backward()
return loss
loss = loss_function(output, model(input))
loss.backward()
optimizer.step(closure)
optimizer.zero_grad()
...
训练技巧
- @hjq133:如果使用批归一化,上述用法可能会出现问题。运行统计会在两次前向传播中都被计算,但它们应该只在第一次计算。一种可能的解决方案是将 BN 动量设为零(由 @ahmdtaha 友好建议),以避免在第二次传播中更新运行统计。示例用法见 example/train.py 的第 51 和 58 行:
for batch in dataset.train:
inputs, targets = (b.to(device) for b in batch)
# 第一次前向-反向步骤
enable_running_stats(model) # <- 这是关键行
predictions = model(inputs)
loss = smooth_crossentropy(predictions, targets)
loss.mean().backward()
optimizer.first_step(zero_grad=True)
# 第二次前向-反向步骤
disable_running_stats(model) # <- 这是关键行
smooth_crossentropy(model(inputs), targets).mean().backward()
optimizer.second_step(zero_grad=True)
- @evanatyourservice:如果计划在多 GPU 上训练,论文指出:“为了在多个加速器之间并行化时计算 SAM 更新,我们将每个数据批次均匀地分配到各个加速器,在每个加速器上独立计算 SAM 梯度,然后对得到的子批次 SAM 梯度取平均,以获得最终的 SAM 更新。”这可以通过以下代码实现:
for input, output in data:
# 第一次前向-反向传播
loss = loss_function(output, model(input))
with model.no_sync(): # <- 这是关键行
loss.backward()
optimizer.first_step(zero_grad=True)
# 第二次前向-反向传播
loss_function(output, model(input)).backward()
optimizer.second_step(zero_grad=True)
@evanatyourservice:据报道,自适应 SAM 的性能优于原始 SAM。ASAM 论文建议为自适应更新使用更高的
rho参数(约为原始值的 10 倍)。@mlaves:学习率调度应应用于基础优化器,或者你可以使用 SAM 并通过单次
step调用(结合闭包)来实现:
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer.base_optimizer, T_max=200)
- @AlbertoSabater:与 PyTorch Lightning 集成时,可以这样编写
training_step函数:
def training_step(self, batch, batch_idx):
optimizer = self.optimizers()
# 第一次前向-反向传播
loss_1 = self.compute_loss(batch)
self.manual_backward(loss_1, optimizer)
optimizer.first_step(zero_grad=True)
# 第二次前向-反向传播
loss_2 = self.compute_loss(batch)
self.manual_backward(loss_2, optimizer)
optimizer.second_step(zero_grad=True)
return loss_1
文档
SAM.__init__
| 参数 | 描述 |
|---|---|
params (可迭代对象) |
需要优化的参数的可迭代对象,或定义参数组的字典 |
base_optimizer (torch.optim.Optimizer) |
执行“尖锐度感知”更新的基础优化器 |
rho (float, 可选) |
用于计算最大损失的邻域大小 (默认: 0.05) |
adaptive (bool, 可选) |
如果您希望使用基于元素级别的自适应 SAM 的实验性实现,请将此参数设置为 True (默认: False) |
**kwargs |
传递给 base_optimizer 的 __init__ 方法的关键字参数 |
SAM.first_step
执行第一步优化,找到局部 rho 邻域内损失最大的权重。
| 参数 | 描述 |
|---|---|
zero_grad (bool, 可选) |
如果您希望在此步骤后自动清零所有梯度,请将其设置为 True (默认: False) |
SAM.second_step
执行第二步优化,根据损失曲面上(局部)最高点的梯度来更新原始权重。
| 参数 | 描述 |
|---|---|
zero_grad (bool, 可选) |
如果您希望在此步骤后自动清零所有梯度,请将其设置为 True (默认: False) |
SAM.step
在一次调用中同时执行两个优化步骤。此函数是显式调用 SAM.first_step 和 SAM.second_step 的替代方案。
| 参数 | 描述 |
|---|---|
closure (可调用对象) |
闭包应针对优化后的模型执行一次完整的前向和反向传播 (默认: None) |
实验
我已验证 SAM 在 CIFAR10 数据集上运行的简单 WRN 16-8 模型上有效;您可以通过运行 train.py 来复现该实验。Wide-ResNet 仅通过标签平滑和最基本的图像增强(如 Cutout)进行改进,因此误差高于 SAM 论文 中的结果。理论上,如果训练时间更长(例如 1800 轮而不是 200 轮),可以获得更低的误差,因为 SAM 不太容易过拟合。SAM 使用 rho=0.05,而 ASAM 则按照其作者的建议设置为 rho=2.0,详见 GitHub 问题 #37。
| 优化器 | 测试错误率 |
|---|---|
| SGD + 动量 | 3.20 % |
| SAM + SGD + 动量 | 2.86 % |
| ASAM + SGD + 动量 | 2.55 % |
引用
如果您在工作中使用此优化器,请引用原始作者:
@inproceedings{foret2021sharpnessaware,
title={Sharpness-aware Minimization for Efficiently Improving Generalization},
author={Pierre Foret and Ariel Kleiner and Hossein Mobahi and Behnam Neyshabur},
booktitle={International Conference on Learning Representations},
year={2021},
url={https://openreview.net/forum?id=6Tm1mposlrM}
}
@inproceesings{pmlr-v139-kwon21b,
title={ASAM: Adaptive Sharpness-Aware Minimization for Scale-Invariant Learning of Deep Neural Networks},
author={Kwon, Jungmin and Kim, Jeongseop and Park, Hyunseo and Choi, In Kwon},
booktitle ={Proceedings of the 38th International Conference on Machine Learning},
pages={5905--5914},
year={2021},
editor={Meila, Marina and Zhang, Tong},
volume={139},
series={Proceedings of Machine Learning Research},
month={18--24 Jul},
publisher ={PMLR},
pdf={http://proceedings.mlr.press/v139/kwon21b/kwon21b.pdf},
url={https://proceedings.mlr.press/v139/kwon21b.html},
abstract={近年来,以损失曲面的尖锐度作为泛化差距的有效度量的学习算法取得了最先进的性能。然而,在固定半径的刚性区域内定义的尖锐度,存在对参数缩放敏感的缺点,这会导致损失不变,从而削弱了尖锐度与泛化差距之间的联系。本文引入了尺度不变的自适应尖锐度概念,并提出了相应的泛化界。我们提出了一种新的学习方法——自适应尖锐度感知最小化(ASAM),并利用所提出的泛化界进行优化。在多个基准数据集上的实验结果表明,ASAM 显著提升了模型的泛化性能。}
}
常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
gemini-cli
gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器