Nodes/ComfyUI-StyleGan/Discover GANSpace Directions
ComfyUI Node

Discover GANSpace Directions

Find the knobs nobody labelled

By dfl·Created 2 years ago·Updated 18 days ago· 0
Discover GANSpace Directions
  • stylegan_model
  • STYLEGAN_DIRECTIONS
◄num_samples5000►
◄num_components10►
◄seed0►

Every diffusion trick you know for "make her smile" needs either a prompt, a LoRA, or a reference image. StyleGAN has no prompt and usually no LoRA, but it does have a latent space with structure you can measure. This node measures it: sample a bunch of latents, run PCA over them, and hand you the axes along which StyleGAN faces vary most. No labels, no training, no attribute dataset.

The mechanism, briefly

GANSpace (Harkonen et al.) is the "just look at the distribution" method. The node draws num_samples random z vectors, pushes them through the mapping network to get W, stacks them, centers them, and runs a low-rank PCA. What comes out is a set of orthogonal directions in W-space ordered by how much variance they explain - component 0 is the single biggest thing that varies across these faces, component 1 the next, and so on down.

One implementation detail that matters for reading your results: it keeps only the first W layer (w[:, 0, :]) from each sample, so the direction is a single w_dim vector that gets broadcast across all layers when you apply it. The other detail is scaling - the code multiplies each component by its standard deviation, so directions land at roughly "1 sigma" units. That's why strength values of ±1–3 in ApplyStyleGANDirection correspond to meaningful edits here, and it's the number to remember when you're used to SeFa's much larger scale.

It returns a STYLEGAN_DIRECTIONS bundle. The mean it computed along the way is thrown away - the node only exports the components.

What you set

stylegan_model is the STYLEGAN output of LoadStyleGAN - same checkpoint you'll render with, or the directions won't correspond to anything. num_samples defaults to 5000, which is a decent statistical basis and runs in seconds because mapping is cheap; dropping to 300 gets you noisier, less clean axes, and raising it to 20000+ mostly buys you stability rather than new information. num_components defaults to 10 - that's ten candidate knobs, and honestly you'll find something usable in the first few. seed seeds the sampling, and because PCA has a sign ambiguity, a different seed can flip a component's direction and reorder near-equal ones. If a direction seems to have inverted, that's not a bug in your workflow.

Output: one STYLEGAN_DIRECTIONS, wired into ApplyStyleGANDirection (to use it) or StyleGANDirectionSweep (to look at it).

The workflow this belongs to

Discovery is step one of three, and the pack is opinionated about the order: discover, then look with StyleGANDirectionSweep, then apply. Neither discovery node tells you what a component does. There is no label, no preview, no name - the axes come out numbered and you have to eyeball what component_04 changes before you commit to it. That is the honest cost of unsupervised discovery, and it's why the sweep node exists.

If you want the result to survive a restart, you have two options: keep the discovery node in the graph (it's fast, deterministic for a given seed, and re-runs on execution) or dump the bundle offline with the script the pack ships, which writes a .safetensors you can load with LoadStyleGANDirections:

python discover_directions.py model.safetensors --method ganspace --num-samples 5000

That script drops the file next to the model's folder by default (models/stylegan_directions/<model>_ganspace_directions.safetensors), which is exactly where the loader's picker looks.

Install

ComfyUI Manager → search ComfyUI-StyleGan (publisher dflfd), or:

cd ComfyUI/custom_nodes
git clone https://github.com/dfl/ComfyUI-StyleGan

Restart, drop a model in ComfyUI/models/stylegan/. The pack has only four pip requirements (numpy, ninja, safetensors, packaging) - the real install cost is the runtime-compiled CUDA ops, which need CUDA Toolkit, ninja and MSVC/GCC. Good news: discovery doesn't touch the synthesis network, so this node works even on a machine where the plugin build is still broken. The pack's own docs make that distinction - discovery only touches G.mapping, rendering is what needs the compiled kernels.

Where people get burned

  • Every component looks the same. Usually num_samples too low, or you're judging at strength 1.0 - check with a sweep from -3 to 3.
  • The best direction vanishes on rerun. Different seed, different PCA sign/ordering. Pin the seed, or export the bundle to a file.
  • Editing pushes past "good". These are the dominant variance axes, not semantic sliders; at high strength you get the ghosting/doubling that shows up in the pack's README example past ~7–8. Find the knee and stop there.
  • On Apple Silicon, the README warns StyleGAN3 synthesis output can shift between PyTorch versions on MPS. If a sweep looks wrong in a way that feels like the model, not the direction, that's a place to look.
CategoryStyleGAN/directions

Inputs (4)

NameTypeDefaultDescription
stylegan_modelSTYLEGAN—
num_samplesINT5000100–1000000—
num_componentsINT101–512—
seedINT00–18446744073709550000—

Outputs (1)

NameTypeDescription
STYLEGAN_DIRECTIONSSTYLEGAN_DIRECTIONS—