Natural Language Autoencoders for Model Audits
Audit natural-language autoencoder explanations with separate reconstruction, causal-edit, coverage, and confabulation receipts before trusting fluent prose.
Natural language autoencoders can turn hidden activations into readable explanations, but fluent prose is not audit evidence. This guide builds four independent checks—reconstruction, causal edits, coverage, and confabulation—before an explanation can be promoted.
Natural language autoencoders need an evidence threshold
A fluent explanation is the beginning of an interpretability investigation, not its conclusion. Natural language autoencoders map internal activations into words and reconstruct an activation from those words, but legibility can conceal several different errors. A sentence may sound specific while recovering the wrong direction, covering only easy examples, or adding claims that no activation feature supports.
Write the promotion rule before anyone reads the generated prose. This article uses four separate gates: reconstruction, causal edit consistency, coverage, and confabulation. Reconstruction asks whether the decoded text retains enough signal to approximate the held-out activation. Causality asks whether editing a named concept changes the reconstruction in the predicted direction. Coverage asks which evaluated activation regions receive supported explanations. Confabulation flags phrases whose claimed feature is absent from the fixture.
No weighted average may hide a failed gate. A high cosine score cannot compensate for unsupported claims, and broad coverage cannot excuse an edit that moves opposite its prediction. This follows the principle of freezing the evidence contract before scoring explanations. The contract makes a natural language autoencoders audit falsifiable before the writing style has a chance to persuade the reviewer.
- Activation explanation loop with residual custody
- A source activation passes through verbalization and reconstruction while the residual, versions, and digests remain visible.
- Identify the source activation, layer, example, and digest.
- Version the verbalizer and retain its complete explanation.
- Version the reconstructor and retain its vector.
- Compare direction and magnitude while preserving the residual.
Trace the activation reconstruction loop
The complete loop has four named objects: a source activation, a verbalizer output, a reconstructed activation, and a residual. The verbalizer turns a vector or activation slice into an explanation. The reconstructor turns that explanation back into the model's activation space. Natural language autoencoders are useful only when the identities of those objects survive the trip. That custody chain is what makes activation-to-text interpretability inspectable instead of merely eloquent.
Record the example identifier, layer or hook location, source-vector digest, explanation text, reconstructor version, reconstructed-vector digest, and metric configuration. Without that custody record, a later score can accidentally compare examples from different layers or revisions. The first figure shows the residual returning beside the source rather than disappearing into a single green check.
The fixture in this article uses seeded generated vectors and a deliberately simple explanation vocabulary. It does not call a model provider and does not contain production activations. That boundary is useful: every result can be recomputed, and a corrupted sentence can be inserted without implying anything about a deployed model. For real work, keep the same receipt shape while replacing the synthetic generator, and audit whether condensed evidence drops causal detail before a summary enters the review record.
Keep fidelity metrics separate
Cosine similarity and root-mean-square error answer different questions. Cosine similarity measures directional alignment and ignores overall magnitude. RMSE exposes coordinate-scale disagreement but can look acceptable when many quiet dimensions dilute a few important misses. A natural language autoencoders review should publish both values, their thresholds, and the raw paired vectors needed to reproduce them.
Choose thresholds on a development split, then lock them before evaluating the audit split. Report the distribution, not only the mean: median, lower tail, and count below threshold reveal whether a system explains common states while abandoning rare ones. If the reconstructor is trained on the same examples used for the audit, label that leakage instead of treating the score as held-out evidence.
Sparse-autoencoder evaluation offers a useful warning: reconstruction, downstream behavior, sparsity, and interpretability cannot be collapsed without losing meaning. The OpenAI sparse-autoencoder study evaluates multiple properties rather than crowning one scalar. Natural language autoencoders add prose-specific failure modes, so the same discipline matters even more. The activation reconstruction score is one ledger column, never the verdict. The audit matrix keeps each axis visible and treats any threshold as an explicit product policy rather than a universal scientific constant.
- Four independent evidence gates
- Reconstruction, causal edits, coverage, and confabulation occupy separate axes with named failure bands; no average hides a failure.
| Gate | Measure | Failure cannot be rescued by |
|---|---|---|
| Reconstruction | Cosine and RMSE | Fluent prose |
| Causal edit | Predicted versus observed direction | High reconstruction |
| Coverage | Passing rows / declared population | Omitting hard rows |
| Confabulation | Unsupported named claims | Broad coverage |
Intervene on the explanation
Reconstruction alone can reward a sentence that paraphrases correlations without identifying a controllable concept. Add a paired intervention: edit one supported phrase, reconstruct both versions, and compare the observed activation delta with a predeclared feature direction. A natural language autoencoders audit passes this check only when the direction and sign agree within tolerance.
The edit must be narrow. Replacing “warm hue” with “cool hue” is interpretable when the fixture defines a hue direction; rewriting the whole sentence changes too many variables. Store the original text, edited span, predicted direction, observed delta, cosine agreement, and decision. The third figure places supported and unsupported spans beside the resulting vector change so the linguistic and numeric evidence cannot drift apart.
An intervention does not prove the explanation caused behavior in the original model. It tests a property of the explanation–reconstruction loop. Stronger causal claims require interventions on the model computation and outcome measurements designed for that model. The primary Natural Language Autoencoders publication motivates activation verbalization, reconstruction, and intervention, while also documenting limitations. Keep those levels of evidence named, and calibrate any model-assisted explanation grader separately.
Expose coverage gaps and unsupported prose
Coverage begins with an evaluation population. Partition the examples by activation norm, cluster, label, cohort, or another predeclared slice, then count explanations that clear every required gate. Natural language autoencoders can appear reliable when a report silently omits hard activation regions; a denominator makes that omission visible.
Confabulation needs an equally concrete test. In the generated fixture, each explanation may name only features present in a frozen vocabulary for that example. The corrupted control adds a feature claim that is absent from the source record. The auditor identifies the exact unsupported phrase and fails the NLA confabulation gate. A real system may need human annotation or a second verified probe, but “sounds plausible” is never the oracle.
Publish abstentions as outcomes. If the verbalizer cannot produce a supported explanation, an honest “unexplained” row improves the evidence ledger because it preserves the gap. Do not manufacture generic text to maximize coverage. Projects such as Gemma Scope demonstrate the value of open interpretability resources, yet a resource boundary is not an assurance claim. Natural language autoencoders still need a scoped population, a counted denominator, and an explicit unsupported-claim policy.
Run the seeded audit and corrupted control
The runnable artifact generates six small activation records from a fixed seed. Each record carries a supported feature set, a templated explanation, a reconstruction vector, and a declared edit direction. It computes cosine similarity, RMSE, intervention agreement, coverage, and unsupported-claim flags. Repeating the same seed must produce the same receipt digest.
Then the artifact replaces one supported phrase with “metallic texture,” which the corresponding source record does not contain. That corrupted natural language autoencoders case must fail the named confabulation gate even if its reconstruction remains numerically close. This is an important hostile control: it demonstrates that the policy does not let vector similarity wash away textual invention. A second hostile case reverses an edit direction and must fail causal consistency.
The output is JSON followed by a concise PASS line. The JSON contains the generated provenance, thresholds, individual cases, failures, and digest, so a reviewer can recompute the summary rather than trusting a preset boolean. Use the known-bad row as you would keep a known-bad explanation canary in the release gate. The fixture validates audit math and reporting, not the scientific quality of any real NLA.
- Explanation edit ledger
- Supported and unsupported text spans align with predicted and observed activation deltas for one deliberately corrupted explanation.
| Case | Text evidence | Vector evidence | Verdict |
|---|---|---|---|
| Baseline | Focused form is supported | Aligned reconstruction | Pass |
| Corrupted | Metallic texture absent | Similarity cannot rescue it | Fail confabulation |
| Edit | Warm span removed | Observed delta matches prediction | Pass |
| Reversed | Same edit label | Observed sign is reversed | Fail causality |
Runnable artifact — The generated fixture tests audit math and reporting only. It is not a real natural-language autoencoder, a production-model measurement, or proof of interpretability.
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
const canonical=value=>JSON.stringify(value,(_,item)=>item&&typeof item==="object"&&!Array.isArray(item)?Object.fromEntries(Object.entries(item).sort(([a],[b])=>a.localeCompare(b))):item);
const sha=value=>createHash("sha256").update(ArrayBuffer.isView(value)?Buffer.from(value.buffer,value.byteOffset,value.byteLength):typeof value==="string"?value:canonical(value)).digest("hex");
const parseSeed=value=>{if(!/^[1-9][0-9]{0,9}$/.test(String(value)))throw new Error("seed-must-be-an-integer-1..4294967295");const seed=Number(value);if(!Number.isSafeInteger(seed)||seed>4294967295)throw new Error("seed-must-be-an-integer-1..4294967295");return seed};
const seedIndex=process.argv.indexOf("--seed"),seed=parseSeed(seedIndex<0?"905":process.argv[seedIndex+1]);
const directions={focus:[1,0,0,0],warm:[0,1,0,0],edge:[0,0,1,0],motion:[0,0,0,1]};
const phrases={focus:"focused form",warm:"warm hue",edge:"hard edge",motion:"motion trace"};
const plans=[["focus","warm"],["edge"],["motion","focus"],["warm","edge"],["focus"],["motion"]];
function generateFixture(inputSeed){let state=inputSeed>>>0,index=0;const drawOrder=[];const draw=label=>{state^=state<<13;state^=state>>>17;state^=state<<5;const u32=state>>>0;drawOrder.push({index:index++,label,u32});return u32/4294967296};const rows=plans.map((features,rowIndex)=>{const target=[0,0,0,0];for(const feature of features)directions[feature].forEach((value,i)=>target[i]+=value);const norm=Math.hypot(...target)||1;const activation=target.map((value,axis)=>Number((value/norm+(draw("row-"+(rowIndex+1)+"-axis-"+axis)-.5)*.028).toFixed(6)));const explanation=features.map(feature=>phrases[feature]).join(" with ");return{id:"a"+(rowIndex+1),features:[...features],activation,explanation}});const core={generator:{version:"xorshift32-v1",seed:inputSeed,drawOrder},rows};return{...core,fixtureHash:sha(core)}}
const fixture=generateFixture(seed),sameFixture=generateFixture(seed),differentFixture=generateFixture(seed===4294967295?seed-1:seed+1);
const lexicon={focused:"focus",focus:"focus",warm:"warm",edge:"edge",motion:"motion",metallic:"metallic"};
function claims(text){return[...new Set(text.toLowerCase().split(/[^a-z]+/).map(word=>lexicon[word]).filter(Boolean))]}
function reconstruct(text){const found=claims(text).filter(name=>directions[name]);const vector=[0,0,0,0];for(const name of found)directions[name].forEach((value,i)=>vector[i]+=value);const norm=Math.hypot(...vector)||1;return vector.map(value=>value/norm)}
const cosine=(a,b)=>a.reduce((sum,value,i)=>sum+value*b[i],0)/((Math.hypot(...a)*Math.hypot(...b))||1);
const rmse=(a,b)=>Math.sqrt(a.reduce((sum,value,i)=>sum+(value-b[i])**2,0)/a.length);
function audit(row,text=row.explanation){const reconstructed=reconstruct(text),named=claims(text),unsupported=named.filter(name=>!row.features.includes(name));return{id:row.id,text,sourceFeatures:row.features,activation:row.activation,reconstructed,cosine:cosine(row.activation,reconstructed),rmse:rmse(row.activation,reconstructed),unsupported}}
const thresholds={cosineMinimum:.9,rmseMaximum:.28,editCosineMinimum:.9,coverageMinimum:.95,unsupportedMaximum:0};
const baseline=fixture.rows.map(row=>audit(row));
const covered=baseline.filter(row=>row.cosine>=thresholds.cosineMinimum&&row.rmse<=thresholds.rmseMaximum&&row.unsupported.length===0).length;
const editSource=fixture.rows[0],before=reconstruct(editSource.explanation),after=reconstruct("focused form"),observed=before.map((value,i)=>value-after[i]),predicted=directions.warm;
const intervention={id:"remove-warm",before,after,observed,predicted,cosine:cosine(observed,predicted)};
const corrupted=audit(fixture.rows[1],fixture.rows[1].explanation+" with metallic texture");
const reversedObserved=observed.map(value=>-value),reversed={id:"reversed-direction-control",observed:reversedObserved,predicted,cosine:cosine(reversedObserved,predicted)};
const gates={reconstruction:baseline.every(row=>row.cosine>=thresholds.cosineMinimum&&row.rmse<=thresholds.rmseMaximum),causalEdit:intervention.cosine>=thresholds.editCosineMinimum,coverage:covered/baseline.length>=thresholds.coverageMinimum,confabulation:baseline.every(row=>row.unsupported.length<=thresholds.unsupportedMaximum)};
const hostile={corruptedFails:corrupted.unsupported.includes("metallic"),reversedEditFails:reversed.cosine<thresholds.editCosineMinimum};
const replay={sameSeedFixtureHash:sameFixture.fixtureHash,differentSeed:differentFixture.generator.seed,differentSeedFixtureHash:differentFixture.fixtureHash,sameSeedEqual:fixture.fixtureHash===sameFixture.fixtureHash,differentSeedUnequal:fixture.fixtureHash!==differentFixture.fixtureHash};
assert.ok(Object.values(gates).every(Boolean));assert.ok(Object.values(hostile).every(Boolean));assert.equal(replay.sameSeedEqual,true);assert.equal(replay.differentSeedUnequal,true);
const receiptCore={schema:"nla-audit-fixture-v2",fixture,provenance:"Activation vectors and explanation rows generated by the recorded xorshift32-v1 seed and draw order; no provider or production-model data.",claimBoundary:"Audit math and reporting only; not a trained NLA or proof of interpretability.",thresholds,baseline,coverage:{covered,total:baseline.length,ratio:covered/baseline.length},intervention,corrupted,reversed,gates,hostile,replay};
console.log(JSON.stringify({...receiptCore,receiptHash:sha(receiptCore)},null,2));
console.log("PASS: seeded NLA fixture replays, changes across seeds, and rejects corrupted explanation controls");
Publish an explanation evidence ledger
A useful ledger gives every explanation one durable row. Include activation identity, source digest, explanation, supported spans, unsupported spans, reconstruction metrics, intervention metrics, coverage slice, verdict, and the versions of both verbalizer and reconstructor. Natural language autoencoders change quickly; versioned evidence prevents a polished new sentence from inheriting an old score.
Keep human review beside deterministic measurements without merging them. A reviewer can note whether the prose is understandable, precise, and useful for the audit question. The receipt can show whether the vectors and declared features agree. These observations may inform one decision, but they are not interchangeable. If a reviewer overrides a gate, record who did so, why, and what risk was accepted.
The ledger also needs negative space. List excluded layers, unevaluated cohorts, unavailable interventions, and any explanation types that the reconstructor cannot parse. A dashboard that shows only passing examples becomes a gallery, not an audit. For natural language autoencoders, the strongest artifact is often the row that says exactly why an attractive explanation was not promoted. That row teaches future reviewers what evidence is still missing and keeps a model internals audit from overstating its sampled boundary.
Decide what the audit can certify
This protocol can certify that a particular explanation pipeline met a frozen set of reconstruction, edit, coverage, and confabulation checks on a named dataset. It cannot certify that the model “understands” the prose, that every internal feature is represented, or that changing an explanation would change downstream model behavior. Natural language autoencoders remain a measurement instrument with a bounded calibration domain.
State the decision that the evidence unlocks. A team might allow explanations into a debugging interface, prioritize examples for expert review, or compare two verbalizer revisions. Safety-critical attribution demands additional model-level interventions, domain expertise, and governance. The audit should not quietly stretch when the consequence becomes larger.
Schedule a revisit when evaluation protocols, public weights, or material failure findings change. Until then, preserve the raw receipt and the corrupted controls with the report. The practical rule is simple: fluent text earns attention, while separate falsifiable measurements earn promotion. Run the corrupted control before promoting a natural language autoencoders explanation to audit evidence.