news 2026/9/10 23:57:52

Diffusers 中的 CogVideoXDPMScheduler:为 CogVideoX 视频生成量身定制的 DPM-Solver++ 多步调度器解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Diffusers 中的 CogVideoXDPMScheduler:为 CogVideoX 视频生成量身定制的 DPM-Solver++ 多步调度器解析

Diffusers 中的 CogVideoXDPMScheduler:为 CogVideoX 视频生成量身定制的 DPM-Solver++ 多步调度器解析

【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers

导读

本文围绕 🤗 Diffusers 仓库中为 CogVideoX 视频扩散模型专门实现的CogVideoXDPMScheduler(对应文档见 multistep_dpm_solver_cogvideox.md)展开,深入讲解其理论基础、完整配置参数、采样算法细节(二阶多步 DPM-Solver++)以及它与 CogVideoX 文生视频 / 图生视频 / 视频生视频三条 pipeline 的集成方式。读完本文,你将掌握该调度器的每个构造参数的作用与默认值、采样循环中step方法的调用契约,并能直接在自己的 CogVideoX 推理脚本中正确替换、配置与调优该调度器。

一、CogVideoXDPMScheduler 是什么

CogVideoXDPMScheduler是 Diffusers 库中面向 CogVideoX 视频生成模型的高阶 ODE 求解调度器,其核心实现位于 scheduling_dpm_cogvideox.py(类定义见 L134)。官方文档对其定位的说明非常明确:

CogVideoXDPMScheduler基于 DPM-Solver(DPM-Solver: A Fast ODE Solver for Diffusion Probabilistic Model Sampling in Around 10 Steps)与 DPM-Solver++(DPM-Solver++: Fast Solver for Guided Sampling of Diffusion Probabilistic Models)两篇论文,专门面向 CogVideoX 模型设计。

与通用的DPMSolverMultistepScheduler相比,该调度器针对 CogVideoX 的视频潜空间扩散任务做了三处关键定制:

  1. SNR 偏移(SNR shift):仿照 Stable Diffusion 3 的做法,在初始化阶段对alphas_cumprod施加snr_shift_scale偏移,适配高分辨率视频潜空间的信噪比分布;
  2. 二阶多步(2M)更新:采样时缓存上一步预测的原始样本old_pred_original_sample,用 DPM-Solver++(2M) 的二阶校正公式提升少步数采样质量;
  3. zero-SNR 支持:通过rescale_betas_zero_snr对 beta 序列做零终端信噪比重标定。

该调度器在仓库中已注册为公开导出 API,见 schedulers/init.py 与 diffusers/init.py,可以直接通过from diffusers import CogVideoXDPMScheduler导入使用。

二、算法背景:从 DPM-Solver 到 DPM-Solver++(2M)

扩散模型的采样本质上是求解一条概率流 ODE:

dx / dt = ...

DPM-Solver 系列论文的核心思想是:利用扩散模型输出的噪声估计构造关于 log-SNR(即lambda(t))的精确解形式,从而用远比 DDPM/DDIM 更少的步数完成采样。

在 DPM-Solver++ 中,模型被用来直接预测原始样本x_0(去噪结果),而不是预测噪声。二阶多步(2M)形式进一步利用上一步的模型预测结果构造二阶泰勒校正项,使每一步的截断误差更小。

CogVideoXDPMScheduler正是实现了这种"二阶多步"更新:它在采样循环外维护一个old_pred_original_sample变量,把上一时间步预测的x_0传入当前步,参与二阶校正项的计算。这一设计在 pipeline_cogvideox.py 的采样循环中有完整的体现。

三、完整配置参数详解

CogVideoXDPMScheduler的构造函数通过@register_to_config注册全部超参数(见 scheduling_dpm_cogvideox.py)。下面按功能分组列出全部参数、类型、默认值与作用:

3.1 噪声调度(beta schedule)

参数默认值说明
num_train_timesteps1000训练时使用的扩散步数,决定 beta 序列长度,也是推理时间步的最大值
beta_start0.00085beta 起始值(注意:类 docstring 写的是 0.0001,实际构造函数默认值为 0.00085)
beta_end0.0120beta 终止值(docstring 写 0.02,实际默认值为 0.0120)
beta_schedule"scaled_linear"支持linearscaled_linearsquaredcos_cap_v2三种
trained_betasNone直接传入训练好的 beta 数组,传入后将绕过beta_start/beta_end

beta_schedule的三种取值在 scheduling_dpm_cogvideox.py 中实现:

  • lineartorch.linspace(beta_start, beta_end, ...)线性插值;
  • scaled_linear:对beta_start/beta_end开方后线性插值再平方,这是潜扩散模型(latent diffusion)特有的调度,也是本类的默认值;
  • squaredcos_cap_v2:调用betas_for_alpha_bar(见 L52)生成 Glide 风格的余弦调度,底层支持cosineexplaplace三种alpha_transform_type

3.2 采样稳定性相关

参数默认值说明
clip_sampleTrue是否将预测样本裁剪到[-clip_sample_range, clip_sample_range],保证数值稳定性
clip_sample_range1.0样本裁剪的最大幅值,仅当clip_sample=True时生效
set_alpha_to_oneTrue最后一步无"上一步 alpha"时,将上一时刻的alphas_cumprod固定为 1(否则取第 0 步的 alpha 值),见 L239-L243
thresholdingFalse是否启用动态阈值(dynamic thresholding)方法;文档明确提示该方法不适用于潜空间扩散模型
dynamic_thresholding_ratio0.995动态阈值比率,仅当thresholding=True时生效
sample_max_value1.0动态阈值的阈值上限,仅当thresholding=True时生效

3.3 预测类型与时间步

参数默认值说明
prediction_type"epsilon"模型输出类型:epsilon(预测噪声)、sample(直接预测干净样本)、v_prediction(预测速度,见 Imagen Video 论文 2.4 节)
timestep_spacing"leading"时间步缩放方式,支持leadinglinspacetrailing,对应论文Common Diffusion Noise Schedules and Sample Steps are Flawed中 Table 2 的三种方案
steps_offset0推理时间步的偏移量,某些模型族需要
rescale_betas_zero_snrFalse是否将 beta 重标定为零终端 SNR,见下文 3.4
snr_shift_scale3.0SNR 偏移尺度(SNR shift),是本调度器针对 CogVideoX 的关键定制项

3.4 SNR 偏移与 zero-SNR 重标定

初始化阶段对噪声调度的两个后处理是理解本调度器"专为 CogVideoX 定制"的关键,实现见 scheduling_dpm_cogvideox.py:

self.alphas = 1.0 - self.betas self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) # Modify: SNR shift following SD3 self.alphas_cumprod = self.alphas_cumprod / (snr_shift_scale + (1 - snr_shift_scale) * self.alphas_cumprod) # Rescale for zero SNR if rescale_betas_zero_snr: self.alphas_cumprod = rescale_zero_terminal_snr(self.alphas_cumprod)
  • SNR shift:将alphas_cumprodsnr_shift_scale进行非线性缩放。SNR(信噪比)定义为alpha / (1 - alpha),偏移后整个扩散过程的信噪比曲线整体上移/变形,使模型在低噪声端也能获得足够的梯度信息,这对大分辨率、大压缩比的视频潜空间尤为重要;
  • zero-SNR 重标定rescale_zero_terminal_snr(见 L104)按论文Common Diffusion Noise Schedules and Sample Steps are Flawed的 Algorithm 1 实现:先对alphas_cumprod开方,减去末项使最后一步为零,再等比缩放回首项原始值,最后平方还原。零终端 SNR 允许模型生成极亮、极暗的样本,而不是被限制在中等亮度区间。

这两个机制决定了采样所使用的alphas_cumprod曲线,进而影响set_timestepsstep中所有alpha_prod_*的计算。

四、时间步设置:set_timesteps 的三种间距策略

set_timesteps方法(见 scheduling_dpm_cogvideox.py)负责在推理前生成离散时间步序列,其签名如下:

def set_timesteps(self, num_inference_steps: int, device: str | torch.device | None = None)

有两个需要注意的约束:

  1. num_inference_steps > num_train_timesteps(默认 1000),会直接抛出ValueError,因为模型最多只能处理训练步数对应的时间步;
  2. 三种timestep_spacing策略的行为(均返回降序时间步):
策略生成方式
linspace[0, num_train_timesteps-1]上均匀取num_inference_steps个点,round 后反转
leadingstep_ratio = num_train_timesteps // num_inference_steps整数倍取步,并叠加steps_offset(默认策略)
trailingnum_train_timesteps开始以-step_ratio步长回退取整,再整体减 1

生成的timesteps会移动到device上,并保存在self.timesteps中,供采样循环逐项消费。另外,采样所需的final_alpha_cumprod(最后一步无前序 alpha 时的回退值,set_alpha_to_one=True时为 1.0)与init_noise_sigma = 1.0(初始噪声标准差)都在构造函数中完成设置。

五、采样核心:step 方法中的 DPM-Solver++(2M) 更新

step方法是整个调度器的灵魂(见 scheduling_dpm_cogvideox.py)。与常规调度器不同,它的签名多出两个关键参数:

def step( self, model_output: torch.Tensor, # 当前时间步的模型输出 old_pred_original_sample: torch.Tensor, # 上一步预测的原始样本 x_0(2M 二阶校正用) timestep: int, # 当前时间步 timestep_back: int, # 需要"回看"的时间步(即上一步) sample: torch.Tensor, # 当前带噪样本 x_t eta: float = 0.0, use_clipped_model_output: bool = False, generator: torch.Generator | None = None, variance_noise: torch.Tensor | None = None, return_dict: bool = False, ) -> DDIMSchedulerOutput | tuple

5.1 第一步:由预测类型还原 x_0

根据prediction_type从模型输出还原预测原始样本pred_original_sample(见 L479-L492):

  • epsilonx_0 = (x_t - sqrt(1 - alpha_t) * eps) / sqrt(alpha_t)
  • sample:模型直接输出x_0
  • v_predictionx_0 = sqrt(alpha_t) * x_t - sqrt(1 - alpha_t) * v

5.2 第二步:计算 log-SNR 差与乘子

get_variables(见 L331)把alphas_cumprod转换成 log-SNR 值:

lamb = log(sqrt(alpha / (1 - alpha))) # 当前步 lamb_next = log(sqrt(alpha_prev / (1 - alpha_prev))) # 前一步 h = lamb_next - lamb # log-SNR 差(步长)

若提供了alpha_prod_t_back(即timestep_back对应的累积 alpha),还会额外计算上一步与上上步的 log-SNR 差比值r = h_last / h,用于二阶校正。

get_mult(见 L364)则基于这些量计算 DPM-Solver++ 的更新乘子:

mult1 = sqrt((1 - alpha_prev) / (1 - alpha)) * exp(-h) mult2 = expm1(-2h) * sqrt(alpha_prev) mult3 = 1 + 1/(2r) # 二阶校正系数(仅二阶步) mult4 = 1/(2r) # 二阶校正系数(仅二阶步)

5.3 第三步:执行二阶多步更新

完成一阶项与二阶校正项的合成(见 L494-L514):

h, r, lamb, lamb_next = self.get_variables(alpha_prod_t, alpha_prod_t_prev, alpha_prod_t_back) mult = list(self.get_mult(h, r, alpha_prod_t, alpha_prod_t_prev, alpha_prod_t_back)) mult_noise = (1 - alpha_prod_t_prev) ** 0.5 * (1 - (-2 * h).exp()) ** 0.5 # 一阶项(含随机噪声项,mult_noise * noise) prev_sample = mult[0] * sample - mult[1] * pred_original_sample + mult_noise * noise if old_pred_original_sample is None or prev_timestep < 0: # 第一步或最后一步:省去一次网络评估,直接返回 return prev_sample, pred_original_sample else: # 二阶校正:用上一步的 x_0 预测修正当前步 denoised_d = mult[2] * pred_original_sample - mult[3] * old_pred_original_sample x_advanced = mult[0] * sample - mult[1] * denoised_d + mult_noise * noise prev_sample = x_advanced

这段代码的注释(L455-L464)给出了符号对照:pred_original_sample -> f_theta(x_t, t)prev_sample -> x_{t-1}。注意step的返回值是(prev_sample, pred_original_sample)二元组或DDIMSchedulerOutput(其结构定义见 L32-L48,包含prev_sample与可选的pred_original_sample两个字段,return_dict=False时返回 tuple)。调用方需要把返回的pred_original_sample作为下一次调用的old_pred_original_sample传回,这是 2M 算法的必要约定。

5.4 其他辅助方法

  • scale_model_input(L262):恒等返回sample,用于与其他需要按时间步缩放输入的调度器保持接口一致;
  • add_noise(L522):前向扩散加噪,x_t = sqrt(alpha_t) * x_0 + sqrt(1 - alpha_t) * noise,会先把alphas_cumprod移到与输入相同的 device/dtype,减少跨设备拷贝;
  • get_velocity(L565):v = sqrt(alpha_t) * noise - sqrt(1 - alpha_t) * sample,供v_prediction训练使用;
  • __len__返回num_train_timesteps

另外需要留意类属性order = 1(L188):虽然算法本身是二阶多步,但每个时间步只调用一次网络(利用缓存的上一步预测),因此order被标记为 1,它直接参与 pipeline 中进度条与 warm-up 步数的计算(见下文第六节)。

六、与 CogVideoX Pipeline 的集成方式

CogVideoXDPMScheduler在仓库中被以下 pipeline 使用(见 pipelines/cogvideo 目录):

  • pipeline_cogvideox.py(文生视频):构造函数的scheduler参数类型标注为CogVideoXDDIMScheduler | CogVideoXDPMScheduler(L185);
  • pipeline_cogvideox_image2video.py(图生视频);
  • pipeline_cogvideox_video2video.py(视频生视频);
  • 此外pipeline_cogview3plus.pypipeline_consisid.py等也引用了该类。

6.1 采样循环中的特殊调用契约

在 pipeline_cogvideox.py 的去噪循环中,对 DPM 调度器与其他调度器做了分支处理:

num_warmup_steps = max(len(timesteps) - num_inference_steps * self.scheduler.order, 0) with self.progress_bar(total=num_inference_steps) as progress_bar: # for DPM-solver++ old_pred_original_sample = None for i, t in enumerate(timesteps): ... # compute the previous noisy sample x_t -> x_t-1 if not isinstance(self.scheduler, CogVideoXDPMScheduler): latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs, return_dict=False)[0] else: latents, old_pred_original_sample = self.scheduler.step( noise_pred, old_pred_original_sample, # 回传上一步的 x_0 预测 t, timesteps[i - 1] if i > 0 else None, # timestep_back latents, **extra_step_kwargs, return_dict=False, ) latents = latents.to(prompt_embeds.dtype)

从源码可以清晰地看到 2M 算法的完整协作模式:

  1. 循环外初始化old_pred_original_sample = None
  2. 每次调用step时传入上一步的pred_original_sample与上一步的时间步timesteps[i-1](第一步传None);
  3. step内部据此决定执行一阶(第一步)还是二阶(后续步)更新,并把(prev_sample, pred_original_sample)返回;
  4. pipeline 将返回的pred_original_sample存回old_pred_original_sample,进入下一轮迭代。

timesteps[i-1]正是step签名中的timestep_back,用于在alphas_cumprod中索引alpha_prod_t_back,从而计算二阶校正系数r

6.2 动态 CFG 与进度控制

采样循环中还有两点与本调度器间接相关:

  • 动态引导(dynamic CFG):当use_dynamic_cfg=True时,pipeline 会按余弦曲线在采样过程中动态调整引导系数(L742-L745),CogVideoX 的官方推理脚本(例如 image2video 示例中pipe(image, prompt, use_dynamic_cfg=True))常配合本调度器一起使用;
  • warm-up 步数num_warmup_steps的计算使用了self.scheduler.order,由于本类order=1,进度条按每步一次网络评估推进(L776)。

6.3 如何切换到该调度器

视频生视频 pipeline 的官方示例(见 pipeline_cogvideox_video2video.py)展示了标准的替换方式——保留原配置并原地换调度器:

import torch from diffusers import CogVideoXDPMScheduler, CogVideoXVideoToVideoPipeline from diffusers.utils import export_to_video, load_video pipe = CogVideoXVideoToVideoPipeline.from_pretrained("THUDM/CogVideoX-5b", torch_dtype=torch.bfloat16) pipe.to("cuda") pipe.scheduler = CogVideoXDPMScheduler.from_config(pipe.scheduler.config) input_video = load_video("path/to/input.mp4") prompt = ( "An astronaut stands triumphantly at the peak of a towering mountain. Panorama of rugged peaks and " "valleys. Very futuristic vibe and animated aesthetic. Highlights of purple and golden colors in " "the scene. The sky is looks like an animated/cartoonish dream of galaxies, nebulae, stars, planets, " "moons, but the remainder of the scene is mostly realistic." ) video = pipe(video=input_video, prompt=prompt, strength=0.8, guidance_scale=6, num_inference_steps=50).frames[0] export_to_video(video, "output.mp4", fps=8)

from_config(pipe.scheduler.config)会继承原调度器配置(num_train_timestepsbeta_*prediction_type等),确保与已训练好的模型匹配;需要调参时只需在from_config后传入覆盖参数,例如:

pipe.scheduler = CogVideoXDPMScheduler.from_config( pipe.scheduler.config, snr_shift_scale=3.0, timestep_spacing="leading", prediction_type="v_prediction", )

文生视频与图生视频 pipeline 的用法完全一致(from diffusers import CogVideoXPipeline/CogVideoXImageToVideoPipeline),官方图生视频示例(见 pipeline_cogvideox_image2video.py)中pipe(image, prompt, use_dynamic_cfg=True)即默认配合该调度器工作。

七、使用建议与注意事项

综合源码与文档,使用CogVideoXDPMScheduler时有以下几点需要留意:

  1. 推理步数上限num_inference_steps不能超过num_train_timesteps(默认 1000),否则set_timesteps会抛错(L295-L300);官方示例通常使用 50 步,这也是 DPM-Solver 系列擅长的少步数区间;
  2. 二阶校正依赖上一步预测:不要在采样循环中破坏old_pred_original_sample的回传链路,否则退化为低阶更新;
  3. eta参数对该调度器无效eta(DDIM 论文中的随机噪声权重)仅对DDIMScheduler生效,pipeline 的prepare_extra_step_kwargs(L359-L368)会检测step是否接受eta参数——虽然本类step签名中声明了eta,但实现中并未使用它来引入随机性,随机性只来自mult_noise * noise项;
  4. thresholding不建议开启:动态阈值是为像素空间模型设计的,对潜空间模型(包括 CogVideoX)不适用,文档原文即有明确提示;
  5. rescale_betas_zero_snr需要配合训练一致:该开关会改变整个噪声调度曲线,只有模型在 zero-SNR 设定下训练(或与官方 checkpoint 配置一致)时才应开启;
  6. 与 DDIM 的互换性:CogVideoX pipeline 同时支持CogVideoXDDIMScheduler与本调度器(L185),当isinstance判断不命中 DPM 分支时走通用step调用路径,两条分支的返回契约(return_dict=False取第一个元素)保持一致,因此可以在两种调度器间平滑切换对比效果。

八、小结

CogVideoXDPMScheduler是 Diffusers 为 CogVideoX 视频生成场景定制的高阶多步 ODE 求解器:它以 DPM-Solver/DPM-Solver++ 理论为基础,通过snr_shift_scale完成针对视频潜空间的 SNR 偏移,通过"缓存上一步x_0预测"的 2M 二阶校正换取少步数下的高质量采样,并通过set_alpha_to_one、zero-SNR 重标定、clip_sample等一系列开关保证数值稳定性。其实现集中在一个文件 scheduling_dpm_cogvideox.py 中(约 600 行),采样循环的协作契约(old_pred_original_sampletimestep_back的传递)则在 pipeline_cogvideox.py 中清晰可见,是理解"调度器如何与扩散 pipeline 协作"的极佳范本。若要深入对比,可同时阅读通用多步求解器 scheduling_dpmsolver_multistep.py(其中solver_order=2配合algorithm_type="dpmsolver++"即为通用场景下的同类推荐配置),以及文档站点的调度器索引页面 index.md(若存在)获取完整调度器清单。

【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 23:57:24

### IEEE 754 单精度浮点数阶码深度解析报告

在现代计算机科学与数值计算领域&#xff0c;IEEE 754 标准是浮点数运算的绝对基石。该标准由电气和电子工程师协会&#xff08;IEEE&#xff09;于1985年制定&#xff0c;旨在解决不同计算机架构之间浮点数表示与运算不一致的问题。无论是底层的微处理器架构&#xff08;如x86…

作者头像 李华
网站建设 2026/9/10 23:57:10

GPS北斗双模公交调度方案:从车载终端选型到到站预报的落地实践

我在公交站等车时经常会看那个电子站牌&#xff0c;上面写着"XX路还有3分钟进站"&#xff0c;结果等了8分钟车才到。刚开始我也吐槽电子站牌不准&#xff0c;后来跟公交运营的朋友聊深了才发现&#xff0c;问题不在站牌本身&#xff0c;而在于很多公交公司连自己调度…

作者头像 李华
网站建设 2026/9/10 23:55:54

孤岛微电网事件触发控制策略与Simulink仿真实践

1. 项目概述在新能源发电占比逐年提升的背景下&#xff0c;孤岛微电网的稳定运行控制成为电力系统领域的研究热点。传统基于周期采样的控制方式存在通信资源浪费、控制器计算负担重等问题&#xff0c;而事件触发机制通过仅在系统状态超出预设阈值时进行控制更新&#xff0c;可显…

作者头像 李华
网站建设 2026/9/10 23:55:05

Flipper Zero 固件中文显示完整教程:3 步汉化你的设备界面

Flipper Zero 固件中文显示完整教程&#xff1a;3 步汉化你的设备界面 【免费下载链接】flipperzero-firmware Flipper Zero firmware source code 项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware 本文带你基于 flipperzero-firmware 固件实现…

作者头像 李华
网站建设 2026/9/10 23:54:01

牧野PRO3数控机床操作与维护实战:从对刀到模态分析的完整指南

牧野PRO3这台机床第一次出现在我们车间的时候&#xff0c;说实话我并没有觉得它有多特别。后来用了大概三个月&#xff0c;我才慢慢体会到它和普通国产设备的差别——不是单纯快&#xff0c;而是那种“稳定到让你几乎忘记它在运转”的可靠感。在模具配件和电极加工这块&#xf…

作者头像 李华
网站建设 2026/9/10 23:53:07

STM32+RM500U 5G模组接入OneNET:温湿度采集全链路实战

简介&#xff1a;这套压缩包是一例面向嵌入式初学者的STM32物联网实战工程&#xff0c;主控采用STM32系列单片机&#xff0c;通信侧使用移远RM500U 5G模块&#xff0c;传感器选用AHT20&#xff0c;采集温湿度数据后通过MQTT协议上传至OneNET平台&#xff0c;完成从硬件驱动、网…

作者头像 李华