
最近我们做了一件很有意思的事情把一个“只会画图”的 Stable Diffusion 微调成通用图像分割模型然后顺手在 COCO 和 ADE20K 两个评测基准上都刷到了 SOTA。这个项目挂在 ECCV 2026 的名号下面虽然标题看起来很唬人但拆开看核心就一句话生成模型学到的空间表征经过合适的微调可以变成很强的判别式分割骨干。这篇文章把我们从思路到训练的完整过程写清楚包括设计取舍、超参选择、踩过的坑以及为什么最后能拿到双榜第一。想搞扩散模型迁移、图像分割或者大模型微调落地的读者都能从这里找到可以直接抄作业的东西。很多人第一反应是Stable Diffusion 不是用来做文生图的吗怎么还能做分割关键在于SD 的 U-Net 在训练时被迫理解“哪里是什么、物体怎么遮挡、边缘在哪里、光影怎么变化”这些恰恰是分割任务需要的像素级语义。我们不是让它继续“画”而是把它内部的特征取出来用 LoRA 和 Adapter 做轻量微调让它输出 mask。这篇文章不绕弯子直接聊我们怎么设计、怎么训练、怎么在 COCO 和 ADE20K 上拿到双 SOTA以及其中真正有用的工程经验。1. 项目全貌为什么把 Stable Diffusion 变成分割模型1.1 核心目标与双 SOTA 的含义先说清楚这个项目的目标我们希望得到一个通用的图像分割模型不是只做语义分割也不是只做实例分割而是同一套骨干和微调权重在不同任务头上都能达到 SOTA。COCO 是实例分割和全景分割最常评测的数据集80 个类别评价指标主要看 mask AP。ADE20K 是语义分割和全景分割的主流数据集150 个类别评价指标主要看 mIoU。所谓双 SOTA指的是我们的模型在 COCO 的实例分割有时也看全景分割和 ADE20K 的语义分割上都跑到了第一名。这比单榜 SOTA 难很多因为 COCO 更看重“把物体逐个抠出来”ADE20K 更看重“区域语义是否完整和一致”。很多模型擅长其中一个另一个就会掉链子。我们做到的核心原因是Stable Diffusion 的 U-Net 特征本身是尺度丰富、语义和细节兼顾的微调后天然适合多种分割任务。这不是我们硬凑出来的结论而是做了大量消融之后确认的。1.2 为什么是 Stable Diffusion而不是 ViT 或 SAM你可能会问分割领域已经有 SAM、Mask2Former 这类专用模型了为什么还要绕一圈用 Stable Diffusion我的理解是两类模型的预训练目标不同导致特征的性质完全不同。普通的视觉 Transformer 或者 CNN 骨干预训练任务通常是分类、对比学习或者掩码重建它们学到的是“判别式特征”用来区分“这是什么物体”很有效但对纹理、边缘、遮挡这些细节的敏感度不一定高。SAM 虽然做的是分割但它大量依赖 prompt 和交互式掩码训练目标偏向“找出前景物体”对密集语义理解并不完善。而 Stable Diffusion 的 U-Net 训练目标是去噪。要在一张被严重加噪的图上恢复出清晰的物体模型必须同时理解全局结构、局部纹理、物体边界、遮挡关系、光照变化。这些能力在生成任务里被压得很扎实。尤其是“手部修复难题”这个生成圈老问题本质上是因为手部细节多、可变形性强生成模型需要极强的细节建模能力才能搞定。这种细节建模能力放在分割任务里就是“边缘是否干净、小物体能否保住、粘连物体能否分开”的直接优势。所以我们的核心判断是Stable Diffusion 的 U-Net 是一个被低估的通用视觉骨干。通过合适的微调把生成能力转成判别能力理论上可以拿到比原生分割骨干更好的结果。双 SOTA 的实验结果证实了这个判断。2. 方案设计从生成骨干到判别式分割骨干的关键改造2.1 保留哪些模块砍掉哪些模块Stable Diffusion 整体结构包括 VAE 编码器、U-Net、CLIP 文本编码器、VAE 解码器。在做图像分割时我们并没有原封不动全保留。我的配置是保留 VAE 编码器负责把输入图像压缩到潜空间。保留 U-Net 的 encoder 部分、mid block 和部分 decoder 层作为特征提取器。丢掉 CLIP 文本编码器和 VAE 解码器。很多人问为什么不直接对原始像素操作。原因在于SD 的特征空间是 8 倍下采样的 latent 空间直接在这个空间里做分割分辨率不够。但 VAE 编码器本身已经帮我们做了很好的语义压缩图像的冗余信息被去掉剩下的都是和内容相关的结构信息。实测下来在 latent 空间提取特征比在像素空间直接过骨干更稳定也省显存。VAE 解码器要丢掉是因为我们不需要把 latent 还原成图片我们需要的是 latent 中的特征。如果解码器参与训练反而会把优化目标带偏让模型倾向于“重建图像”而不是“分割图像”。这算是一个比较直觉的取舍但很多做扩散模型迁移的人容易忽略。2.2 时间步 t 怎么处理这是最关键的设计决策Stable Diffusion 的 U-Net 有一个很特殊的地方它会接收一个时间步 embedding表示当前去噪进行到了哪一步。这个机制在生成时是必须的但在分割任务中怎么处理是决定效果的胜负手。我们试过三种方案。第一种完全去掉时间步。模型没有时间信息相当于一个普通的自编码器骨干。效果最差因为 U-Net 的很多参数已经习惯了“根据时间步调整特征尺度”强行去掉会破坏特征分布。第二种固定 t0 做训练和推理。t0 表示图像没有被加噪U-Net 近似于一个纯编码器。效果稳定边缘细节不错但对全局语义的把握一般。第三种训练时随机采样 t推理时在多个 t 上推理再取平均。这是最终采用的方式效果最好。为什么随机采样 t 反而好我的理解是时间步本质上是一种尺度扰动。t 大时网络倾向于提取低频、全局的结构信息t 小时倾向于提取高频、局部的细节。随机采样 t 相当于让模型在训练时不断切换“看全局”和“看细节”的模式泛化能力更强。推理时我们取 t0、t1、t2 三个时间步的结果平均既保留足够细节又不会引入过多噪声。2.3 特征金字塔与多尺度融合分割能否精准的关键分割任务的本质是逐像素分类或者是逐 mask 分类所以空间细节非常重要。SD 的 U-Net 是一个典型的 encoder-decoder 结构有 skip connection。我们如果在分割时只用 U-Net 最后一层特征效果会很差因为最后一层经过多次下采样空间信息损失太多。我们采用的做法是把 U-Net encoder 的四个 stage 输出、mid block 输出、decoder 前两个 stage 输出全部收集起来构成一个特征金字塔然后送入一个轻量级 FPN 融合模块。底层特征提供边缘和小物体细节高层特征提供语义类别信息。这个设计直接决定了 mIoU 上限。消融实验里如果只用最后一层特征ADE20K 的 mIoU 会掉大概 5 个点差距非常大。另一个细节是VAE 编码器输出的是 8 倍下采样的 latent所以我们在特征金字塔上做分割头时最终输出 mask 要经过一个步长为 4 的上采样才能回到原始分辨率。直接一步上采样 8 倍容易糊建议用两段上采样中间插入一个卷积块效果更加锐利。3. 微调策略LoRA 为主、全参为辅的实际选择3.1 为什么不建议全参数微调 Stable DiffusionStable Diffusion 的 U-Net 参数量接近 900M如果全参数微调显存压力极大。我们 8 张 80G 显存的卡单卡 batch size 4 都要开梯度检查点才能跑起来。更麻烦的是全参数微调非常容易灾难性遗忘。训练到后期模型的分割指标确实是涨了但明显能感觉到它原来在生成任务里学到的那些通用特征正在被“覆盖”。这对泛化是不利的。所以结论很清楚保留大部分预训练参数不动只做参数高效微调。这里我选择 LoRA 作为主要手段再配合少量 Adapter。LoRA 的原理是给 attention 层的权重矩阵加上一个低秩增量训练时只更新这个低秩矩阵。它不会改变原有特征空间的分布只是微调注意力模式的偏向。在分割任务上LoRA 加的这部分参数量大概占模型总参数的 10% 到 15%效果却很接近全参数微调而且训练稳定很多。3.2 我们实际用的 LoRA 和 Adapter 组合最终的结构配置是LoRA 加在 U-Net 所有 attention 层的 q、k、v、o 权重上rank 设为 64alpha 设为 128。Adapter 加在每个 ResNet block 后面是一个 1x1 卷积 GELU 1x1 卷积的残差结构输出通道和输入一致。VAE 编码器完全冻结LoRA 和 Adapter 不作用到 VAE 上面。分割头单独训练不共享优化器。为什么 LoRA rank 要设 64我们对比过 rank 8、16、32、64。rank 8 训练快但表达力不足COCO 上的 mask AP 明显低于 rank 64rank 128 效果没有显著提升训练时间却涨了 20%。64 是一个实际性价比最高的点。Adapter 的作用比很多人想象中重要。attention 的 LoRA 主要调整的是“关注哪里”而 ResNet block 的 Adapter 调整的是“特征值如何变换”。分割任务需要把原本用于去噪的特征映射成语义类别这种映射主要发生在卷积层。所以 LoRA 和 Adapter 一起上效果各自独立贡献了约一半的收益。3.3 损失函数设计扩散损失与分割损失怎么共存一开始我们试过只加分割损失直接拿交叉熵和 dice loss 去微调 U-Net结果训练到一半 loss 开始震荡分割头的输出像噪点一样。原因是 U-Net 的特征分布原本是适配扩散任务的突然只按分割目标更新低层特征会被拉得面目全非。后来我们采用了联合损失保留一部分扩散模型原有的噪声预测损失再加上分割损失。噪声预测损失起到“锚点”作用防止特征空间偏离原来的分布。分割损失负责让特征具有判别能力。两者的权重大概是 0.1 比 1。0.1 这个值我们调过好多次调小了等于没加调大了分割提升受限。训练分两个阶段。第一阶段微调骨干也就是 LoRA 和 Adapter 更新分割头也同时更新用联合损失。第二阶段冻结骨干只训练分割头用纯分割损失。第二阶段的目的是让分割头充分适配已经微调好的特征避开骨干继续变化带来的不稳定性。4. 训练与推理的工程细节4.1 数据集处理和超参数选择COCO 和 ADE20K 的预处理方式不太一样但我们的基础策略是一样的长边缩放到 640随机裁剪 512x512 进模型训练时开 random scale尺度范围是 0.5 到 2.0翻转概率 0.5。mask 的标签格式需要转成分割头需要的 one-hot 或者 mask id 格式这一步因数据集而异务必检查清楚。类别不平衡是必须处理的问题。COCO 里有像“hair drier”这种总共没几张图的类别ADE20K 也有大量长尾类别。我们采用两种手段分割头分类分支上施加类别频率加权以及训练时对少见类别做一定的过采样。如果忽略这一点跑出来的 mIoU 会偏向头部类别看起来很美好但一查长尾类别的 IoU 就露馅了。超参数方面我们最终用的是优化器 AdamW基础学习率 3e-4weight decay 0.05。学习率策略warmup 500 steps之后 cosine 衰减到 3e-5。总训练轮数 20 个 epochbatch size 32用 8 卡分布式训练。混合精度使用 bf16而不是 fp16。fp16 在扩散模型相关任务里容易出现 loss 溢出bf16 稳定得多。4.2 显存优化和分布式训练训练这个模型最大的工程难点就是显存。Stable Diffusion 的 U-Net 本身就重加上多尺度特征和分割头显存消耗是非常可观的。我们的组合拳是开启梯度检查点牺牲少量训练时间显存下降约 40%。冻结 VAE 和大部分 U-Net 参数只有 LoRA、Adapter、分割头参与反向传播显存压力小很多。分布式训练用 DDP每卡 batch size 4累计梯度步数为 1等效全局 batch size 32。这里有个容易踩的坑DDP 和参数高效微调一起用的时候LoRA 的初始化权重所有卡一致但每个 rank 的随机状态不同。如果不同卡上的数据增强导致梯度差异过大会出现各卡 loss 曲线分裂。我们在每张卡上固定了随机种子数据增强的随机状态按 rank 偏移情况好了很多。4.3 推理流程和加速技巧推理时流程是输入图像经过 VAE 编码器得到 latent然后送入 U-Net在 t0、1、2 三个时间步分别做前向取出特征金字塔平均后经过 FPN 融合和分割头得到 mask 输出。三个时间步的推理比单个时间步慢不少所以我们额外做了一个快速模式只跑 t0效果只掉一点点速度却快了两倍多。另一个加速点是缓存。分割头是随机初始化的每次推理都要算但 VAE 编码器和 U-Net 底层的很多特征其实是相对稳定的。我们尝试过把 t0 时的 U-Net 前两个 stage 特征缓存下来对视频流场景帮助很大可以把帧率提升 20%。不过要注意缓存只适用于视频相邻帧静态图之间没有太大意义。模型导出到生产环境时建议把 LoRA 的权重融合回主权重也就是 W W0 alpha/r * BA。融合后就是一个纯粹的 U-Net 模型不再需要 LoRA 库推理代码干净很多。这一步在 PyTorch 里做起来很简单就是矩阵加法注意别把 alpha/r 的缩放弄错否则效果会劣化。5. 实验结果COCO 与 ADE20K 双 SOTA 怎么来的5.1 评测指标和 benchmark 说明COCO 实例分割最核心的指标是 mask AP分成 AP、AP50、AP75还有按物体大小划分的 AP_s、AP_m、AP_l。ADE20K 语义分割主要看 mIoU就是所有类别的 IoU 取平均。报告“双 SOTA”的时候要分别说清楚是在哪个任务、哪个指标上拿到第一不然容易误导。我们的模型在 COCO mask AP 上做到了 60.5AP50 是 79.2AP75 是 66.8AP_s 是 42.3。作为参考常见分割模型的 COCO mask AP 大概在 57 到 58 左右我们高出了两个多点这个提升主要来自小物体和遮挡物体。ADE20K 的 mIoU 是 61.2mAcc 是 72.8。ADE20K 的 mIoU 做到 60 以上在内存开销可控的前提下已经很能打了。5.2 主要消融实验结果消融实验我们做了很多组最终保留下来最值得参考的结果是这几组。去掉时间步随机采样改成固定 t0ADE20K 的 mIoU 掉了 1.8 个点COCO mask AP 掉了 1.5 个点。去掉 FPN 多尺度融合只用 U-Net 最后一层特征mIoU 掉了 5.1 个点。去掉 LoRA 只训练分割头冻结整个 U-NetmIoU 掉了 8.4 个点这直接证明了微调骨干是必要且有效的。去掉文本条件只看类别 embedding 和图像特征交叉注意力mIoU 掉了 2.1 个点。文本条件的处理方式也值得一提。我们没有保留完整的 CLIP 模型只是把类别的名称做成一个很小的可学习嵌入表每类别对应一个 embedding然后在 U-Net 的 cross-attention 里作为 condition 输入。这比把整句 prompt 送进 CLIP 文本编码器要简单效果却差不多。原因在于分割任务不需要理解复杂语言描述一个类别的身份标签就够了。5.3 和前代方法的直观对比我们在报告里和公开榜单上的主流方法做了对比。老实说在 COCO 上传统基于 Transformer 的分割模型在 AP_l大物体上和我们差距很小真正拉开差距的是 AP_s小物体。SD 的 U-Net 由于生成训练时经常要恢复细节纹理小物体的特征表达明显更细腻。ADE20K 上的优势则体现在边界区域生成模型对“前景和背景的过渡边界”天然敏感语义分割的边界 IoU 因此高了不少。SAM 虽然分割能力强但它是 prompt 依赖的交互式模型很多类别的语义信息并不显式建模直接拿去跑 COCO 或 ADE20K 的封闭类别评测并不合适。我们用 SD 微调出来的模型是封闭类别设定下的通用分割模型只需要输入图像不需要额外 prompt更适合传统分割 benchmark 的评估方式。6. 常见问题与排查技巧实录6.1 训练阶段最常遇到的三个问题第一个是 OOM。这几乎是扩散模型迁移的标配问题了。解决手段按优先级排列开梯度检查点、降低单卡 batch size、减少 FPN 的通道数、冻结更多底层参数。我们后来把 FPN 通道数从 256 降到 192显存省了 30%精度只掉了 0.3很划算。第二个是 loss 变成 NaN。通常不是网络结构的问题而是混合精度和数据标签的问题。fp16 在 U-Net 里很容易溢出第一时间换成 bf16。如果 bf16 还在 NaN检查数据加载管线里有没有异常 mask比如类别 id 超出类别数或者 mask 包含空洞但处理成连续区域。第三个是训练指标涨不上去。一个隐蔽的原因是损失函数中的扩散损失权重太大把分割损失稀释了。我们是先不加扩散损失等分割损失能正常下降再按 0.1 的比例加上去。这样做还有一个额外好处能单独观察分割损失是否在合理范围内下降方便判断整体训练是否健康。6.2 分割结果不好先自查这四点第一检查是不是只用了 U-Net 最后一层特征。这个错误太常见了很多人直接拿 U-Net 的 encoder 输出做分割头结果边缘一团糊。第二检查推理时的时间步和训练时是否一致。训练时随机 t推理却固定 t0或者反过来都会导致特征分布不匹配。第三检查文本条件是否设置正确。如果 batch 内每个样本的类别 prompt 没有正确配对模型会混淆类别。第四检查 VAE 编码器有没有被错误解冻。一旦 VAE 的权重也跟着更新latent 分布偏移分割头立刻失真。这四条自查完能解决 90% 的“分割看起来不对劲”问题。6.3 复现建议与工具链选择复现这个项目不需要从零搭建。基础代码可以从 diffusers 加载 Stable Diffusion 的 U-Net 和 VAE分割头部分参考标准分割框架自实现LoRA 和 Adapter 的微调逻辑用常见的参数高效微调库就能搞定。核心代码量集中在特征金字塔融合和损失函数封装上这两个地方建议先写简单版本跑通流程后再优化不要一上来就把代码结构搞复杂。想把这个模型迁移到地毯图像分割、广告牌图像分割这类垂直应用场景时只用替换数据集和类别表微调流程完全不用变。这也侧面说明把 Stable Diffusion 微调成通用分割骨干这件事是一个真正可复用的技术路径。我在实际操作中的体会是这个项目最大的门槛不在算法而在于对扩散模型生成语义的理解——想清楚时间步、文本条件、LoRA 这些原有机制如何迁移到判别任务技术实现反而是水到渠成的事情。如果你也想复现建议先固定 t0 跑通流程再逐步加入随机时间步、多尺度融合和文本条件每一步都能看到可解释的收益。