candle_transformers/models/z_image/
sampling.rs1use candle::{DType, Device, Result, Tensor};
4
5pub fn get_noise(
17 batch_size: usize,
18 channels: usize,
19 height: usize,
20 width: usize,
21 device: &Device,
22) -> Result<Tensor> {
23 Tensor::randn(0f32, 1.0, (batch_size, channels, height, width), device)
24}
25
26pub fn get_schedule(num_steps: usize, mu: f64) -> Vec<f64> {
35 let timesteps: Vec<f64> = (0..=num_steps)
36 .map(|v| v as f64 / num_steps as f64)
37 .rev()
38 .collect();
39
40 timesteps
42 .into_iter()
43 .map(|t| {
44 if t <= 0.0 || t >= 1.0 {
45 t } else {
47 let e = mu.exp();
48 e / (e + (1.0 / t - 1.0))
49 }
50 })
51 .collect()
52}
53
54pub fn postprocess_image(image: &Tensor) -> Result<Tensor> {
57 let image = image.clamp(-1.0, 1.0)?;
58 let image = ((image + 1.0)? * 127.5)?;
59 image.to_dtype(DType::U8)
60}
61
62#[derive(Debug, Clone)]
64pub struct CfgConfig {
65 pub guidance_scale: f64,
67 pub cfg_truncation: f64,
69 pub cfg_normalization: bool,
71}
72
73impl Default for CfgConfig {
74 fn default() -> Self {
75 Self {
76 guidance_scale: 5.0,
77 cfg_truncation: 1.0,
78 cfg_normalization: false,
79 }
80 }
81}
82
83pub fn apply_cfg(
91 pos_pred: &Tensor,
92 neg_pred: &Tensor,
93 cfg: &CfgConfig,
94 t_norm: f64,
95) -> Result<Tensor> {
96 let current_scale = if t_norm > cfg.cfg_truncation {
98 0.0
99 } else {
100 cfg.guidance_scale
101 };
102
103 if current_scale <= 0.0 {
104 return Ok(pos_pred.clone());
105 }
106
107 let diff = (pos_pred - neg_pred)?;
109 let pred = (pos_pred + (diff * current_scale)?)?;
110
111 if cfg.cfg_normalization {
113 let ori_norm = pos_pred.sqr()?.sum_all()?.sqrt()?;
114 let new_norm = pred.sqr()?.sum_all()?.sqrt()?;
115 let ori_norm_val = ori_norm.to_scalar::<f32>()?;
116 let new_norm_val = new_norm.to_scalar::<f32>()?;
117
118 if new_norm_val > ori_norm_val {
119 let scale = ori_norm_val / new_norm_val;
120 return pred * scale as f64;
121 }
122 }
123
124 Ok(pred)
125}
126
127pub fn scale_noise(noise: &Tensor, sigma: f64) -> Result<Tensor> {
132 noise * sigma
133}