The capstone: build it the hard way once
You already saw the GAN as a clean train_step() override. This lesson does the same model as a fully manual loop — no fit(), no train_step() — for one reason: to feel the weight of everything fit() was carrying. When you write the epoch loop, the two tapes, the metric printing, and the checkpoint logic by hand, the value of the higher rungs stops being an abstract claim and becomes a line count.
What the manual GAN loop actually does
The mechanics don't change — only who's responsible for them. Each step still trains the discriminator on a mixed real+fake batch, then trains the generator to fool it, with a separate optimizer per network. The skeleton below shows the two-tape core; in a real run you'd wrap it with your own progress reporting, periodic sample-image dumps, and checkpointing — all the things the override version inherited for free.
- Train the discriminator on real + fake images together
- Train the generator by trying to fool the discriminator
- Use a separate optimizer for each network
- Monitor both losses — healthy training has them oscillating in tension, not collapsing to zero