A Practical Guide to Sol, Lune, and Epsilon Prediction
Overview
This document covers three distinct prediction paradigms used in diffusion and flow-matching models. Each was designed for different purposes and requires specific sampling procedures.
The model learns to identify and remove noise from corrupted images.
The Formula (Simplified)
TRAINING:
x_noisy = √(α) * x_clean + √(1-α) * noise
↓
Model predicts: ε̂ = "what noise was added?"
↓
Loss = ||ε̂ - noise||²
SAMPLING:
Start with pure noise
Repeatedly ask: "what noise is in this?"
Subtract a fraction of predicted noise
Repeat until clean
Reading the Math
α (alpha): "How much original image remains" (1 = all original, 0 = all noise)
"Predict the straight-line direction from noise to data"
Lune uses true rectified flow matching where data travels in straight lines through latent space.
The Formula (Simplified)
TRAINING:
x_t = σ * noise + (1-σ) * data (linear interpolation)
v = noise - data (constant velocity)
↓
Model predicts: v̂ = "straight line to noise"
↓
Loss = ||v̂ - v||²
SAMPLING:
Start at σ=1 (noise)
Walk OPPOSITE to velocity (toward data)
End at σ=0 (clean image)
x_t = σ·noise + (1-σ)·data: Linear blend between noise and data
v = noise - data: The velocity is CONSTANT along the path
Shift function: σ' = shift·σ / (1 + (shift-1)·σ)
Biases sampling toward cleaner images (spends more steps refining)
Key Difference from Sol
Aspect
Sol
Lune
Interpolation
DDPM (α, σ from scheduler)
Linear (σ, 1-σ)
Velocity meaning
Complex (α·ε - σ·x₀)
Simple (noise - data)
Sampling
Convert v→ε, use scheduler
Direct Euler integration
Output
Geometric skeletons
Detailed images
Training Process
python
1# Linear interpolation (NOT DDPM schedule!)2noise = torch.randn_like(latents)3σ = torch.rand(batch)# Random sigma in [0, 1]45# Apply shift during training6σ_shifted =(shift * σ)/(1+(shift -1)* σ)7σ = σ_shifted.view(-1,1,1,1)89x_t = σ * noise +(1- σ)* latents
1011# Velocity target: direction FROM data TO noise12v_target = noise - latents
1314# Model predicts velocity15v_pred = model(x_t, σ *1000)# Timestep = σ * 10001617loss = MSE(v_pred, v_target)
Sampling Process (Direct Euler)
python
1# Start from pure noise (σ = 1)2x = torch.randn(1,4,64,64)34# Sigma schedule: 1 → 0 with shift5sigmas = torch.linspace(1,0, steps +1)6sigmas = shift_sigma(sigmas, shift=3.0)78for i inrange(steps):9 σ = sigmas[i]10 σ_next = sigmas[i +1]11 dt = σ - σ_next # Positive (going from 1 toward 0)1213 timestep = σ *100014 v_pred = model(x, timestep)1516# SUBTRACT velocity (v points toward noise, we go toward data)17 x = x - v_pred * dt
1819# x is now clean image latent
Why SUBTRACT the Velocity?
v = noise - data (points FROM data TO noise)
We want to go FROM noise TO data (opposite direction!)
So: x_new = x_current - v * dt
= x_current - (noise - data) * dt
= x_current + (data - noise) * dt ← Moving toward data ✓
Utility & Behavior
What Lune learned: Rich textures, fine details, realistic rendering
Visual output: Full detailed images with lighting, materials, depth
Training focus: Portrait/pose data with caption augmentation
Use case: High-quality image generation, detail refinement
Comparison Summary
Training Targets
EPSILON (ε): target = noise
"What random noise was added?"
VELOCITY (Sol): target = α·noise - σ·data
"What's the DDPM-weighted direction?"
VELOCITY (Lune): target = noise - data
"What's the straight-line direction?"
Sampling Directions
EPSILON: x_new = scheduler.step(ε_pred, t, x)
Scheduler handles noise removal internally
VELOCITY (Sol): Convert v → ε, then scheduler.step(ε, t, x)
Must translate to epsilon for DDPM math
VELOCITY (Lune): x_new = x - v_pred * dt
Direct Euler integration, subtract velocity
Visual Intuition
EPSILON:
"There's noise hiding the image"
"I'll predict and remove the noise layer by layer"
→ General-purpose denoising
VELOCITY (Sol):
"I know which direction the image is"
"But I speak through DDPM's noise schedule"
→ Learned structure, outputs skeletons
VELOCITY (Lune):
"Straight line from noise to image"
"I'll walk that line step by step"
→ Learned detail, outputs rich images