Generate samples by running the full DDPM reverse process with a tiny noise-prediction network, for t = T - 1 down to 0.
x^0xt−1=αˉtxt−1−αˉtϵ^,μ=1−αˉtβtαˉt−1x^0+1−αˉt(1−αˉt−1)αtxt=μ+β~tnoise[T−1−t],β~t=1−αˉtβt(1−αˉt−1)Here βt is betas[t], αt=1−βt, αˉt=α0⋯αt and αˉ−1=1. The loop starts from x_T, which is the sample at timestep T - 1, and step k = T - 1 - t uses noise[k]. At t = 0 the step returns μ with no noise. When clip_value is a number, x^0 is clamped to [-clip_value, clip_value] before μ is computed, and when it is None nothing is clamped.
The prediction is ϵ^=SiLU([xt,e(t)]W1+b1)W2+b2 with params W1 (D + embed_dim, hidden), b1 (hidden), W2 (hidden, D), b2 (D) and SiLU(z)=z⋅sigmoid(z). The embedding e(t)=[cos(tf),sin(tf)] uses half = embed_dim // 2 and fi=exp(−ln(10000)i/half) for i<half, plus one zero when embed_dim is odd, and is the same for all N rows.
Return a dict with "samples" (the final x, shape (N, D)) and "pred_x0" (shape (T, N, D), row k is the possibly clamped x^0 of step k), both with the dtype of x_T.
Input: x_T = [[1.0,-0.5],[0.2,0.8]], betas = [0.1,0.2,0.3], noise = [[[0.5,-1.0],[0.0,0.3]],[[-0.2,0.4],[1.0,-0.6]],[[0.7,0.7],[-0.7,0.1]]], params = {"W1":[[0.5,-0.3,0.2],[0.1,0.4,-0.2],[0.3,0.0,0.1],[-0.2,0.2,0.5]],"b1":[0.0,0.1,-0.1],"W2":[[0.4,-0.1],[0.2,0.3],[-0.5,0.2]],"b2":[0.0,0.05]}, embed_dim = 2, clip_value = null
Output: {"samples":[[1.765787,-1.152671],[0.468101,0.89931]],"pred_x0":[[[1.594648,-0.79624],[0.289775,0.948434]],[[1.881834,-1.28839],[0.248787,1.053894]],[[1.765787,-1.152671],[0.468101,0.89931]]]}
Explanation: The schedule gives alpha_bars of 0.9, 0.72 and 0.504, and the loop visits t = 2, 1, 0 using noise[0] and noise[1]. The last step at t = 0 returns its posterior mean, which equals that step's predicted clean sample, so noise[2] is never used.
Input: x_T = [[2.0,-1.5],[-0.4,1.2],[0.0,0.0]], betas = [0.05,0.25,0.5,0.5], noise = [[[0.1,0.2],[-0.3,0.4],[0.5,-0.6]],[[1.0,0.0],[0.0,1.0],[-1.0,0.5]],[[0.3,-0.3],[0.2,0.2],[-0.4,0.1]],[[0.9,0.9],[0.9,0.9],[0.9,0.9]]], params = {"W1":[[0.6,-0.4],[0.2,0.5],[0.3,-0.1],[-0.2,0.4],[0.1,0.1]],"b1":[0.1,-0.1],"W2":[[0.7,-0.2],[0.3,0.6]],"b2":[0.0,0.0]}, embed_dim = 3, clip_value = 1.0
Output: {"samples":[[1.0,-1.0],[-1.0,1.0],[-0.040924,-0.336405]],"pred_x0":[[[1.0,-1.0],[-1.0,1.0],[0.131976,-0.079674]],[[1.0,-1.0],[-1.0,1.0],[0.64493,-0.670506]],[[1.0,-0.998199],[-1.0,1.0],[0.061717,-0.38619]],[[1.0,-1.0],[-1.0,1.0],[-0.040924,-0.336405]]]}
Input: x_T = [[0.5,-0.5]], betas = [0.2], noise = [[[3.0,-3.0]]], params = {"W1":[[0.5,-0.3,0.2],[0.1,0.4,-0.2],[0.3,0.0,0.1],[-0.2,0.2,0.5]],"b1":[0.0,0.1,-0.1],"W2":[[0.4,-0.1],[0.2,0.3],[-0.5,0.2]],"b2":[0.0,0.05]}, embed_dim = 2, clip_value = null
Output: {"samples":[[0.535208,-0.563034]],"pred_x0":[[[0.535208,-0.563034]]]}
Build alpha_bars once with torch.cumprod and treat the value before index 0 as 1.
Iterating with enumerate over range(T - 1, -1, -1) gives both the step index for noise and the timestep t.
torch.cat of the cos, sin and zero blocks builds one embedding row, and .expand(N, embed_dim) repeats it for every sample.
tensor.clamp(-c, c) clips values.
Accepts: array
Accepts: array
Accepts: array
Accepts: object
Accepts: integer
Accepts: number, null
Generate samples by running the full DDPM reverse process with a tiny noise-prediction network, for t = T - 1 down to 0.
x^0xt−1=αˉtxt−1−αˉtϵ^,μ=1−αˉtβtαˉt−1x^0+1−αˉt(1−αˉt−1)αtxt=μ+β~tnoise[T−1−t],β~t=1−αˉtβt(1−αˉt−1)Here βt is betas[t], αt=1−βt, αˉt=α0⋯αt and αˉ−1=1. The loop starts from x_T, which is the sample at timestep T - 1, and step k = T - 1 - t uses noise[k]. At t = 0 the step returns μ with no noise. When clip_value is a number, x^0 is clamped to [-clip_value, clip_value] before μ is computed, and when it is None nothing is clamped.
The prediction is ϵ^=SiLU([xt,e(t)]W1+b1)W2+b2 with params W1 (D + embed_dim, hidden), b1 (hidden), W2 (hidden, D), b2 (D) and SiLU(z)=z⋅sigmoid(z). The embedding e(t)=[cos(tf),sin(tf)] uses half = embed_dim // 2 and fi=exp(−ln(10000)i/half) for i<half, plus one zero when embed_dim is odd, and is the same for all N rows.
Return a dict with "samples" (the final x, shape (N, D)) and "pred_x0" (shape (T, N, D), row k is the possibly clamped x^0 of step k), both with the dtype of x_T.
Input: x_T = [[1.0,-0.5],[0.2,0.8]], betas = [0.1,0.2,0.3], noise = [[[0.5,-1.0],[0.0,0.3]],[[-0.2,0.4],[1.0,-0.6]],[[0.7,0.7],[-0.7,0.1]]], params = {"W1":[[0.5,-0.3,0.2],[0.1,0.4,-0.2],[0.3,0.0,0.1],[-0.2,0.2,0.5]],"b1":[0.0,0.1,-0.1],"W2":[[0.4,-0.1],[0.2,0.3],[-0.5,0.2]],"b2":[0.0,0.05]}, embed_dim = 2, clip_value = null
Output: {"samples":[[1.765787,-1.152671],[0.468101,0.89931]],"pred_x0":[[[1.594648,-0.79624],[0.289775,0.948434]],[[1.881834,-1.28839],[0.248787,1.053894]],[[1.765787,-1.152671],[0.468101,0.89931]]]}
Explanation: The schedule gives alpha_bars of 0.9, 0.72 and 0.504, and the loop visits t = 2, 1, 0 using noise[0] and noise[1]. The last step at t = 0 returns its posterior mean, which equals that step's predicted clean sample, so noise[2] is never used.
Input: x_T = [[2.0,-1.5],[-0.4,1.2],[0.0,0.0]], betas = [0.05,0.25,0.5,0.5], noise = [[[0.1,0.2],[-0.3,0.4],[0.5,-0.6]],[[1.0,0.0],[0.0,1.0],[-1.0,0.5]],[[0.3,-0.3],[0.2,0.2],[-0.4,0.1]],[[0.9,0.9],[0.9,0.9],[0.9,0.9]]], params = {"W1":[[0.6,-0.4],[0.2,0.5],[0.3,-0.1],[-0.2,0.4],[0.1,0.1]],"b1":[0.1,-0.1],"W2":[[0.7,-0.2],[0.3,0.6]],"b2":[0.0,0.0]}, embed_dim = 3, clip_value = 1.0
Output: {"samples":[[1.0,-1.0],[-1.0,1.0],[-0.040924,-0.336405]],"pred_x0":[[[1.0,-1.0],[-1.0,1.0],[0.131976,-0.079674]],[[1.0,-1.0],[-1.0,1.0],[0.64493,-0.670506]],[[1.0,-0.998199],[-1.0,1.0],[0.061717,-0.38619]],[[1.0,-1.0],[-1.0,1.0],[-0.040924,-0.336405]]]}
Input: x_T = [[0.5,-0.5]], betas = [0.2], noise = [[[3.0,-3.0]]], params = {"W1":[[0.5,-0.3,0.2],[0.1,0.4,-0.2],[0.3,0.0,0.1],[-0.2,0.2,0.5]],"b1":[0.0,0.1,-0.1],"W2":[[0.4,-0.1],[0.2,0.3],[-0.5,0.2]],"b2":[0.0,0.05]}, embed_dim = 2, clip_value = null
Output: {"samples":[[0.535208,-0.563034]],"pred_x0":[[[0.535208,-0.563034]]]}
Build alpha_bars once with torch.cumprod and treat the value before index 0 as 1.
Iterating with enumerate over range(T - 1, -1, -1) gives both the step index for noise and the timestep t.
torch.cat of the cos, sin and zero blocks builds one embedding row, and .expand(N, embed_dim) repeats it for every sample.
tensor.clamp(-c, c) clips values.
Accepts: array
Accepts: array
Accepts: array
Accepts: object
Accepts: integer
Accepts: number, null