Weight a batch of per-sample diffusion losses with the Min-SNR strategy and return the weighted mean loss.
snri=1−αˉtiαˉti,wi=⎩⎨⎧min(snri,γ)/snrimin(snri,γ)min(snri,γ)/(snri+1)epsilonx0v L=B1i=1∑BwimiHere per_sample_mse holds the unweighted losses mi of shape (B,), timesteps gives each sample its timestep ti, and αˉti is alpha_bars at index ti. The value snri is the signal to noise ratio of sample i, gamma is the cap γ, and prediction_type names the network target, which picks the row of the weight formula.
Return a dict with three keys. The keys "snr" and "weights" hold PyTorch tensors of shape (B,) with the dtype of per_sample_mse, and "loss" holds L as a Python float.
Input: per_sample_mse = [0.5,0.2,0.8], timesteps = [0,1,2], alpha_bars = [0.9,0.5,0.2], gamma = 5.0, prediction_type = "epsilon"
Output: {"snr":[8.999998,1.0,0.25],"weights":[0.555556,1.0,1.0],"loss":0.425926}
Explanation: The first sample has SNR 0.9 / 0.1 = 9, which is clipped to gamma = 5, so its noise prediction weight is 5 / 9, about 0.556. The other two samples have SNR at most 1 and keep weight 1, and the loss is the mean of the weighted errors. The inputs are float32, so the SNR of 9 prints as 8.999998.
Input: per_sample_mse = [1.0,0.4], timesteps = [0,3], alpha_bars = [0.99,0.8,0.5,0.1], gamma = 5.0, prediction_type = "x0"
Output: {"snr":[99.000099,0.111111],"weights":[5.0,0.111111],"loss":2.522222}
Explanation: The inputs are float32, so the first SNR of 0.99 / 0.01 = 99 prints as 99.000099. It is capped at gamma = 5, which is the x0 weight, while the second SNR of 0.1 / 0.9 stays below gamma.
Input: per_sample_mse = [0.3,0.6], timesteps = [1,1], alpha_bars = [0.95,0.75], gamma = 1.0, prediction_type = "v"
Output: {"snr":[3.0,3.0],"weights":[0.25,0.25],"loss":0.1125}
torch.clamp(x, max=gamma) caps a tensor from above.
.mean().item() turns a one-element mean into a Python float.
Accepts: array
Accepts: array
Accepts: array
Accepts: number
Accepts: string
Weight a batch of per-sample diffusion losses with the Min-SNR strategy and return the weighted mean loss.
snri=1−αˉtiαˉti,wi=⎩⎨⎧min(snri,γ)/snrimin(snri,γ)min(snri,γ)/(snri+1)epsilonx0v L=B1i=1∑BwimiHere per_sample_mse holds the unweighted losses mi of shape (B,), timesteps gives each sample its timestep ti, and αˉti is alpha_bars at index ti. The value snri is the signal to noise ratio of sample i, gamma is the cap γ, and prediction_type names the network target, which picks the row of the weight formula.
Return a dict with three keys. The keys "snr" and "weights" hold PyTorch tensors of shape (B,) with the dtype of per_sample_mse, and "loss" holds L as a Python float.
Input: per_sample_mse = [0.5,0.2,0.8], timesteps = [0,1,2], alpha_bars = [0.9,0.5,0.2], gamma = 5.0, prediction_type = "epsilon"
Output: {"snr":[8.999998,1.0,0.25],"weights":[0.555556,1.0,1.0],"loss":0.425926}
Explanation: The first sample has SNR 0.9 / 0.1 = 9, which is clipped to gamma = 5, so its noise prediction weight is 5 / 9, about 0.556. The other two samples have SNR at most 1 and keep weight 1, and the loss is the mean of the weighted errors. The inputs are float32, so the SNR of 9 prints as 8.999998.
Input: per_sample_mse = [1.0,0.4], timesteps = [0,3], alpha_bars = [0.99,0.8,0.5,0.1], gamma = 5.0, prediction_type = "x0"
Output: {"snr":[99.000099,0.111111],"weights":[5.0,0.111111],"loss":2.522222}
Explanation: The inputs are float32, so the first SNR of 0.99 / 0.01 = 99 prints as 99.000099. It is capped at gamma = 5, which is the x0 weight, while the second SNR of 0.1 / 0.9 stays below gamma.
Input: per_sample_mse = [0.3,0.6], timesteps = [1,1], alpha_bars = [0.95,0.75], gamma = 1.0, prediction_type = "v"
Output: {"snr":[3.0,3.0],"weights":[0.25,0.25],"loss":0.1125}
torch.clamp(x, max=gamma) caps a tensor from above.
.mean().item() turns a one-element mean into a Python float.
Accepts: array
Accepts: array
Accepts: array
Accepts: number
Accepts: string