CycleGAN learns two mappings, G: A→B and F: B→A, between two unpaired image domains — here 3×3-pixel toy "images" drawn from an X-shaped template domain A and an O-shaped template domain B, each with random per-pixel noise. Two small discriminators DB and DA try to tell real domain pixels from generated ones, and G/F are trained to fool them:
L_GAN(G,D_B) = E_b[log D_B(b)] + E_a[log(1 − D_B(G(a)))]
L_GAN(F,D_A) = E_a[log D_A(a)] + E_b[log(1 − D_A(F(b)))]
With only the adversarial loss, G could map every a to a single realistic-looking b (mode collapse) with no relation to the input. CycleGAN fixes this with a cycle-consistency loss: translating there and back should return you close to where you started.
L_cyc(G,F) = E_a‖F(G(a)) − a‖₁ + E_b‖G(F(b)) − b‖₁
L_total = L_GAN(G,D_B) + L_GAN(F,D_A) + λ·L_cyc(G,F)
- λ slider — weight of the cycle term. Set it to 0 (or hit the ablation button) and watch the reconstructed images (light blue / light orange grids) fail to settle back onto the originals as G and F stop being trained as inverses of each other.
- Ablation: cycle loss OFF — forces λ=0 regardless of the slider, so you can directly compare the cycle-loss curve with and without the constraint on the same running network.
- Learning rate / steps per frame — control how fast the tiny 9→16→9 generator networks and 9→16→1 discriminator networks converge; both use real backpropagation computed every frame, not a scripted animation.
- Reset weights — re-initialises all four networks from fresh random weights and restarts the step counter and loss curve.
This is the same principle CycleGAN/StyleGAN-family models use for unpaired image-to-image translation (e.g. photo↔painting, horse↔zebra) — swap the 3×3 toy grids for real pixel grids and the loss terms above are unchanged.