Skip to content
AI360Xpert
Beta

Conditional GAN

A conditional GAN feeds a label into both generator and discriminator, so you can order up a specific digit or object instead of accepting whatever appears.

Feeding the same label to generator and discriminator turns random generation into on-demand generation of the requested class
Feeding the same label to generator and discriminator turns random generation into on-demand generation of the requested class

Why Does This Exist?

Unconditional GANs are slot machines. You pull the noise lever and get a bedroom, or a face, or a blur, with no say in the matter. For every practical use, generating a specific thing, the missing steering wheel mattered more than raw quality.

Conditioning adds the wheel with almost no new machinery. Concatenate a label yy onto the noise going in and onto the image going into the discriminator, and the game becomes per-class: the generator must fool the critic specifically as a seven, and the critic learns what real sevens look like. The unconditional template it plugs into is DCGAN, and its paired-image descendant is Pix2Pix.

Think of It Like This

A diner grill versus an order ticket kitchen

An unconditional kitchen grills whatever the cook feels like and serves it. A conditional kitchen runs on order tickets: the ticket saying "pancakes" travels with the batter to the griddle and travels with the plate to the inspector, who checks it against pancake standards specifically.

The label is the ticket. Without it the inspector can only judge generic food-ness, and the cook never learns any dish properly. The system fails when tickets lie, mismatched labels teach the inspector the wrong standard for every dish.

How It Actually Works

Both networks take the condition yy, a class ID, an attribute vector, even another image:

min⁡Gmax⁡D  Ex[log⁡D(x∣y)]+Ez[log⁡(1−D(G(z∣y)))]\min_G \max_D \; \mathbb{E}_{x}[\log D(x \mid y)] + \mathbb{E}_{z}[\log(1 - D(G(z \mid y)))]

D(x∣y)D(x \mid y) scores image-label pairs, not images alone. In practice yy enters as an embedding concatenated with zz in the generator and tiled as extra channels, or a projection term, in the discriminator. The discriminator must reject two kinds of fakes: bad images, and good images with the wrong label. That second duty is what forces the generator to respect the condition.

Why both sides need the label

Condition only the generator and the discriminator scores realism alone; the generator discovers it can ignore yy and emit one beautiful image for every label. Condition only the discriminator and the generator never receives the request. The conditioning must be symmetric or the unsupervised side routes around it.

Worked example

Two real sevens score D=0.9D = 0.9 and 0.850.85 given label 77; two generated sevens score 0.30.3 and 0.40.4. Generator loss is −(log⁡0.3+log⁡0.4)/2=(1.204+0.916)/2=1.06-(\log 0.3 + \log 0.4)/2 = (1.204 + 0.916)/2 = 1.06. Swap one label to 33 while keeping the image and a trained critic drops its score toward 0.10.1, loss contribution −log⁡(1−0.1)≈0.105-\log(1 - 0.1) \approx 0.105 for the critic but a strong gradient telling the generator that right-image-wrong-label is a losing play.

Code

Conditioning by concatenation, the five lines that convert any GAN into a cGAN.

def condition(z: list[float], label_id: int, n_classes: int = 10) -> list[float]:    """Append a one-hot label to a noise vector."""    y = [0.0] * n_classes  # all zeros except the requested class    y[label_id] = 1.0    return z + y

print(len(condition([0.4, -0.7], 7)))  # -> 12 two noise numbers plus ten label slots

Watch Out For

The generator silently ignoring the condition

The classic cGAN failure: every label produces the same sharp image. The generator found that one image fools the realism check and the label pathway atrophied. Samples look great in aggregate and the model is useless for control.

Test per-class diversity explicitly: generate fifty sevens and check they differ. If they match, strengthen label conditioning with projection discrimination or an auxiliary classifier loss on yy.

Mismatched label noise between the two networks

If the generator sees clean labels while the discriminator trains on noisy ones, or embedding tables differ between the two sides, the pair semantics break and training oscillates without converging.

Use one shared label encoding path and identical preprocessing on both sides. Log label histograms per batch on each side when debugging.

The Quick Version

  • A conditional GAN feeds the label yy to both generator and discriminator.
  • The critic judges image-label pairs, rejecting good images with wrong labels.
  • Conditioning must be symmetric or the unconditioned side routes around it.
  • Our toy batch gives generator loss (1.204+0.916)/2=1.06(1.204 + 0.916)/2 = 1.06.
  • Test per-class diversity or silent condition-ignoring goes unnoticed.