vlm-probe / docs /methods /sae /API.md
gexinh's picture
Update vlmprobe to 1.0.1 with SAE methods, guides, and technical report
31246a6 verified
|
Raw History Blame Contribute Delete
15 kB
# SAE API
[SAE hub](README.md) · [Complete runnable example](examples/README.md) ·
[Pretrained loading without fitting](loading.md)
## Use existing weights
The snippets in this reference assume `probe` is a `Prober` bound to your loaded
backbone and processor, and `inputs` is a prepared input batch. The linked
[complete loading example](loading.md) constructs all three from scratch.
```python
# Native dictionary saved by this library; no fitting is needed.
method = probe.sae.load("outputs/dictionary", device="cpu")
result = method.run(inputs)
# Published GPT-2 layer-0 TopK recipe; downloads and converts the author weights.
# The already-loaded backbone/tokenizer must match this recipe exactly.
method = probe.sae.from_pretrained(
"sae-6783018355728933dae6d812", cache_dir="outputs/sae_cache", device="cpu",
)
result = method.run(inputs)
```
The [complete inference-only example](loading.md) includes the matching
backbone, tokenizer, fresh input and visualization. `from_pretrained` accepts
only implemented conversion recipes. A catalog record alone does not imply
automatic source-format or backbone compatibility.
| Loading parameter | Default | Meaning |
| --- | --- | --- |
| `card_id` | Required | Published model ID with an implemented automatic loading recipe. |
| `cache_dir` | `None` | Source checkpoint download cache and converted native-artifact cache; defaults to the Hugging Face cache root. |
| `device` | `"cpu"` | Device for the loaded SAE dictionary; backbone placement remains caller-owned. |
## Configure and fit a new dictionary
Here `probe`, `train_inputs` and `validation_inputs` are constructed in a
method's complete example, such as [ReLU SAE](relu.md#complete-live-example).
```python
from vlmprobe.sae import SAETrainingConfig
method = probe.sae.topk(layer=0, tokens="visual", d_sae=1024, k=32)
history = method.fit(
train_inputs, validation_inputs, output_dir="outputs/fit",
training=SAETrainingConfig(max_steps=200, batch_size=128),
preprocessing_id="my-independent-training-split-v1",
)
method.save("outputs/dictionary", model_card=None, registry_dir=None)
loaded = probe.sae.load("outputs/dictionary", tokens=None, binding=None,
registry_dir=None, artifact_dir=None, device="cpu")
result = loaded.run(validation_inputs[0])
```
Every named factory is also available through
`probe.sae.method("topk", layer=0, tokens="visual", d_sae=1024, k=32)`.
`.fit(...)` trains the SAE encoder/decoder and any method-specific learned
parameters on activations from the frozen backbone. It does not fine-tune that
backbone. Loading a trained dictionary and calling `.run(...)` performs
inference without optimizer updates. A pretrained backbone and a pretrained SAE
are separate sets of weights; one does not supply the other. See the
[inference-only guide](loading.md) for complete loading examples.
`layer` is one zero-based residual layer from `describe()`. `tokens` accepts the
common token selector (`all`, `visual`, `text`, `last_prompt`, positions or a
boolean mask). A saved batch-specific selector needs matching coordinates at
inference; it is not a dataset-independent image region description.
`d_sae` defaults to four times the inferred activation width;
`expansion_factor=4` controls that default. An omitted `k` is capped at the
inferred dictionary width; an explicitly invalid `k` raises.
`train_inputs` and `validation_inputs` are finite native model input batches or
ProbeInputs. Actual model forwards capture detached CPU float32 activations.
Each split has a configurable `max_cache_bytes` payload cap. It is not a hard
total-RAM limit: concatenation temporarily retains both chunks and their joined
tensor, plus the other split; the trainer also uses in-memory tensors. `train_ids` and `validation_ids`, when provided, must
be disjoint source groups. Exact repeated complete batches are independently
rejected; this does not infer patient/slide overlap for you.
Fit hashes loaded model tensors and processor configuration, records the exact
adapter hook and token selection, and derives a calibration fingerprint from
inputs/activations/source IDs. `preprocessing_id` must describe your actual
external transforms; its default explicitly records that they are unverified.
Load verifies actual model tensors, architecture/configuration, numerical-stack
versions and processor/tokenizer behavior when fingerprints are present.
The frozen backbone is assumed unchanged between method calls; verification
is performed at fit/load, rather than rehashing a large backbone on every run. Source artifacts
without automatic fingerprints require a caller-supplied verified binding;
width matching alone is rejected as an automatic compatibility claim.
Loading creates an inference method. Calling `.fit()` on that loaded object
is rejected: it would otherwise silently discard weights or recipe settings.
To resume training, recreate the original factory/configuration and call fit
with its matching output directory; warm-start fine-tuning is not yet provided.
Resaving modified dictionary weights invalidates inherited numerical/semantic
evidence and marks earlier training metrics as stale.
Torch and explicit loader/sampler RNG states are preserved during collection.
Arbitrary Python/NumPy transforms and persistent worker processes need their own
deterministic data or caching protocol.
## Dictionary hyperparameters
The model-bound factory forwards keyword arguments to `SAEConfig` after inferring
`d_in`. Methods share these fields, but only relevant algorithm options affect
the selected method. Explicit recipe defaults and mathematical scope appear in
the [method inventory](ALGORITHMS.md).
| Parameter | Default | Meaning |
| --- | --- | --- |
| `architecture` | `required` | Native algorithm name; see the method inventory. |
| `d_in` | `required` | Captured activation width; inferred by the model-bound fit workflow. |
| `d_sae` | `required` | Dictionary feature count; fixed for the artifact. |
| `k` | `32` | Positive per-vector TopK count, or batch budget as selected below; pursuit defaults to this many iterations. |
| `l1_coefficient` | `0.01` | Coefficient for L1 sparsity in ReLU/Gated or explicit JumpReLU L1 recipe. |
| `seed` | `0` | Local dictionary initialization seed; does not reset caller RNG. |
| `normalization` | `None` | Optional named normalization override: rms, none, layer_norm, constant_norm_rescale. |
| `input_normalization` | `'scalar'` | Internal coordinate recipe: scalar, none, layer_norm or constant_norm. |
| `normalization_eps` | `1e-05` | Positive stability constant for per-input normalization. |
| `normalization_std_correction` | `0` | Standard-deviation correction: 0 (population) or 1 (sample). |
| `apply_decoder_bias_to_input` | `True` | Subtract decoder bias before encoding normalized inputs. |
| `apply_b_dec_to_input` | `None` | Optional source-format alias of apply_decoder_bias_to_input. |
| `use_decoder_bias` | `True` | Whether reconstruction includes the learned decoder bias. |
| `normalize_decoder` | `True` | Apply per-atom decoder normalization after optimizer steps. |
| `rescale_acts_by_decoder_norm` | `False` | Explicit source recipe that rescales feature values using decoder norms. |
| `auxk_coefficient` | `0.0` | Optional dead-feature auxiliary reconstruction weight; 0 disables it. |
| `auxk_k` | `None` | Number of dead features considered by AuxK; None uses the documented method default. |
| `dead_feature_steps` | `100` | Number of training steps without firing before a feature is dead for AuxK. |
| `jumprelu_threshold` | `0.1` | Positive starting threshold for each JumpReLU feature. |
| `jumprelu_bandwidth` | `0.05` | Rectangle surrogate width for threshold derivatives. |
| `l0_coefficient` | `0.01` | Weight on JumpReLU L0 surrogate sparsity. |
| `jumprelu_sparsity` | `'l0'` | Explicit JumpReLU sparsity recipe: l0 or l1. |
| `jumprelu_ste_to_input` | `False` | Whether threshold surrogate gradients also reach encoder preactivations. |
| `batch_budget` | `'average'` | average: k times number of vectors; global: k across the entire minibatch. |
| `threshold_ema` | `0.99` | EMA decay for BatchTopK inference thresholds. |
| `threshold_init` | `'first_batch'` | Initialize inference threshold from first_batch or zero_ema. |
| `matryoshka_widths` | `()` | Increasing prefix widths ending at d_sae; empty selects half/full widths. |
| `matryoshka_weights` | `()` | Positive weights for each nested reconstruction loss; empty means equal weights. |
| `dictionary` | `'learned'` | learned or archetypal; archetypal method names select the latter. |
| `archetypal_candidates` | `128` | Maximum number of training-only anchor vectors. |
| `archetypal_delta` | `1.0` | Bound on the archetypal dictionary relaxation component. |
| `pursuit_iterations` | `None` | Maximum greedy support additions; None uses k. |
| `residual_tolerance` | `0.01` | Residual stopping tolerance in pursuit. |
| `stop_on_duplicate_support` | `True` | Stop matching pursuit when no new support is added. |
| `omp_nnls_iterations` | `32` | Projected-gradient refit steps for nonnegative OMP; finite approximation, not exact NNLS. |
| `quantization_levels` | `4` | Number of learned scalar code levels; QSAE is experimental. |
| `hard_quantization` | `False` | Use discrete quantization rather than the soft code path. |
## Training parameters
`SAETrainingConfig` is shared by all algorithms. The `normalization` field here
chooses whether the training-only RMS scale is fitted for scalar-normalized
models (`rms`) or disabled (`none`); per-input dictionary normalization takes
precedence. These are not different source-specific trainers.
| Parameter | Default | Meaning |
| --- | --- | --- |
| `epochs` | `10` | Maximum epochs unless a step/vector budget is chosen. |
| `lr` | `0.001` | Adam learning rate. |
| `batch_size` | `256` | Number of activation vectors per optimizer minibatch. |
| `patience` | `3` | Stop after this many epochs without min_delta validation-loss improvement. |
| `min_delta` | `0.0001` | Minimum validation-loss improvement for best-model selection. |
| `seed` | `0` | Local dictionary initialization seed; does not reset caller RNG. |
| `normalization` | `'rms'` | Fit train-only scalar RMS (rms) or disable it (none); per-input model normalization takes precedence. |
| `max_steps` | `None` | Optional exact optimizer-step budget; mutually exclusive with max_vectors. |
| `max_vectors` | `None` | Optional exact cumulative training-vector budget; mutually exclusive with max_steps. |
| `device` | `'cpu'` | Dictionary training device (cpu or cuda); the caller owns backbone placement. |
| `resume` | `True` | Resume matching optimizer/RNG/cursor/method state from output_dir. |
| `grad_clip` | `5.0` | Positive maximum gradient norm applied before Adam updates. |
| `progress_every` | `20` | Progress/checkpoint write interval in optimizer steps. |
## Probe operations and outputs
| Call | Parameters | Tensors |
| --- | --- | --- |
| `method.run(inputs)` | Native input batch | `features[N,F]`, `activation[N,D]`, `reconstruction[N,D]`, `reconstruction_error[N,D]`, `l0[N]`, `positions[N,2]` |
| `method.profile(top_k=10).run(inputs)` | Positive top count per feature; ranks absolute values and retains signs | Feature mean/variance/firing frequency/min/max; `top_activation_values[K,F]`, `top_positions[K,F,2]` |
| `method.reconstruct().run(inputs, metric=None)` | Optional task metric | Baseline/edited logits or representation outputs; optional baseline/edited score and score change |
| `method.edit(feature_ids=[...], scale=0., mode="error_preserving").run(inputs, metric=None)` | Unique valid IDs; finite scaling; error_preserving or reconstruction | Same output/score comparison as above, with explicit intervention metadata |
`N` packs selected batch/token positions, `F=d_sae`, `D=d_in`; the two position
columns are batch and native expanded-token index. Signed features count as
active when nonzero. Profiles rank absolute activation, retaining negative
values. Representation outputs remain vectors; they are not fabricated logits.
Default feature editing uses `x + decode(z_edited) - decode(z)` with the same
per-input normalization context reused for both decodes. `scale=1` returns an
exact no-op, including native bf16 precision. Reconstruction is deliberately a
separate control. Generic low-level operations remain available as
`probe.sae.features/profile/reconstruct/edit(layer=..., sae=..., binding=...)`.
## Lower-level training, artifacts and discovery
```python
from vlmprobe.sae import (SAEConfig, SparseAutoencoder, SAETrainingConfig,
fit_sae, list_methods, list_models, get_model_card,
load_artifact, save_artifact, import_checkpoint)
```
`fit_sae(model, train_vectors, validation_vectors, output_dir, training=..., provenance=...)`
uses the same engine as model-bound fitting. Vectors must be finite floating
`[N,D]` in the bound native coordinate system. Legacy `train_sae(...)` is only a
compatibility adapter to this engine.
`save_artifact(model, path, model_card=None, registry_dir=None)` writes either
config.json/weights.pt/model_card.json or the same schema in a safe `.pt`
envelope. `load_artifact(path, expected_binding=None, device="cpu")` validates
checksums, types, exact state, config and optional binding. Inference weights
and optimizer resume state are separate. Browse `list_models(...)` and `get_model_card(id, ...)`;
see [model cards](models/README.md) for local registration, published pretrained
cards and explicit source checkpoint conversion.
### Model discovery parameters
```text
list_models(*, modality=None, method=None, status=None, query=None,
artifact_kind="sae", registry_dir=None, include_builtin=True, limit=None)
get_model_card(card_id, *, registry_dir=None)
```
| Parameter | Meaning |
| --- | --- |
| `modality` | Filter language, vision or multimodal resources. Unreported source metadata remains unspecified. |
| `method` | Filter an algorithm name such as relu, topk or jumprelu. |
| `query` | Case-insensitive search over model, hook, release and other card metadata. |
| `artifact_kind` | `"sae"` selects dictionary weights; `"backbone"` selects activation-extraction models; `None` includes both. |
| `registry_dir` | Optional directory containing your saved artifact/model cards. |
| `include_builtin` | Include the packaged author checkpoint catalog; use False to browse only local runs. |
| `status` | Optional artifact metadata filter, for example published or trained. |
| `limit` | Optional positive maximum result count. |
Cards provide source model/hook/configuration, dimensions when reported, direct
checkpoint links, and a link to our model information page. `load_model(...)`
restores a registered native artifact; source weights use the explicit
checkpoint conversion interface before model-bound probing.