$ the-wire · showcase
SAELens eval metrics stopped lying about float16 and sparse tensors
By RepoJournal · Filed · About Interpretability · Composed from the cited sources · methodology
SAELens fixed three evaluation paths that were silently or loudly wrong: overflowed float16 reconstruction metrics, crashes on sparse COO inputs to the synthetic-data eval, and a zero-ablation baseline compared against a different set of tokens than the SAE run.
fix: promote low-precision activations before computing eval metrics jbloomAus/SAELens
get_sparsity_and_variance_metrics did its input-space arithmetic in the activation dtype, so in float16 any token whose activation norm exceeded 256 had its squared norm overflow 65504 and mse came out as inf. The arithmetic is now promoted to low-precision-safe precision before the metric is computed, covering mse, l2_norm_in, l2_norm_out, l2_ratio, relative_reconstruction_bias and explained_v...
fix: densify sparse tensors in eval_sae_on_synthetic_data jbloomAus/SAELens
eval_sae_on_synthetic_data crashed with NotImplementedError in two configurations you may already be running: an ActivationGenerator built with use_sparse_tensors=True, or a TopK SAE with use_sparse_activations=True whose sae.encode() returns sparse latents. Sparse COO tensors are now densified before the L0, dead-latent and classification calculators see them, so those supported setups evaluat...
fix: skip excluded tokens in the zero-ablation baseline jbloomAus/SAELens
A follow-up to the excluded-token change: get_recons_loss now leaves original activations in place at BOS, EOS and PAD, but the zero-ablation reference still zeroed every position, so ce_loss_score and kl_div_score compared two runs that did not touch the same tokens. The zero-ablation baseline now skips excluded tokens too, which means ce_loss_score values from these runs are not comparable to...
docs: say a block can see one step past a stop on vLLM ndif-team/nnsight
vLLM's async scheduling, on by default, can schedule a request's next step before the last step's token is known, so a block under tracer.iter or tracer.all() sees one forward past a stop. On gpt2 the docs record a stop token giving 7 tokens and 8 block steps, a stop string 1 token and 3 steps, with max_tokens exact; the behavior is documented rather than disabled, so size any activation buffer...
vllm: refuse Ray's compiled-graph executor ndif-team/nnsight
Setting VLLM_USE_RAY_V2_EXECUTOR_BACKEND=0 selects Ray's compiled-graph executor, which runs the forward on its own thread; a greenlet can only be resumed from the thread it runs on, so tracer.result fails with "parent cannot be on a different thread" and the request's counts leak. nnsight now refuses that executor, which means anything relying on it needs the default RayExecutorV2.
Action items
- → Update SAELens before quoting float16 reconstruction evals, and re-run any numbers produced above activation norm 256 jbloomAus/SAELens [plan]
- → Unset VLLM_USE_RAY_V2_EXECUTOR_BACKEND=0 in any nnsight vLLM config ndif-team/nnsight [plan]