DRAM-Native &|~ Classification

CIFAR-10 — DRAM-Native Binary Classifier

Best single-config: 64.9% — H=1024, EN=1, ep=10, --maj 1 --encoding-sizeN 32 (694s, 2026-07-24)
Best ensemble (beam-search over 19,707 archives): 69.99% — 116 members (2026-08-01)
Best beam-selected 4-way comparison: 66.88% — M1-FLT32, 92 members (2026-08-06)

Andreas Otto — 6 August 2026 · Status Report August 2026 →

The Otto Score classifier is a purely bit-logic MLP for DRAM-native inference. A frozen random binary projection (W0) via MAJ3 (majority-of-3 random containers) produces binary hash bits. A trainable Bayes log-Score layer accumulates per-class log-odds via iterative target correction — no backprop, no multiply-accumulate. On CIFAR-10 the single-config ceiling is 64.9% (2026-07-24); the ensemble beam-search workflow (train all channel×encoding×xform members, export scores, select the optimal subset) reaches 69.99% (2026-08-01). The August precision work — exact 64-bit score accumulation, .ens v12/v13, IFC v7 — makes the whole pipeline deterministic and reproducible, with a beam-selected 4-way comparison of 66.88% (maj1 + float counters + double accumulation).

Contents

1. Experiment Data

2. Leaderboard (2026-08-06)

#EvalTypeHMembersTimeConfig
169.99%ensemble beam-search256116M3+M3.add, 19,707 archives (2026-08-01)
266.88%beam-selected 4-way25692M1-FLT32, maj1+double (2026-08-06)
364.9%single-config102460694s--encoding performance --xform performance --maj 1 --encoding-sizeN 32 (2026-07-24)
464.7%single-config51260296s--encoding performance --xform performance --maj 1 --encoding-sizeN 16
564.4%single-config102485621s--encoding latest --xform all (5 tested)
664.3%single-config51285304s--encoding latest --xform all (5 tested)
763.7%single-config102451538s--encoding ey-b,ey-a,ey-h,ey-s-1,ey-s-2
863.5%single-config51251272sspatial channels only (ref)

Note: the 69.99% and 66.88% rows are ensemble-selection results (beam-search over stored per-member score archives), not single-config records. The 64.9% single-config record is the ceiling for one training run. See Status Report August 2026 for the 4-way comparison (maj1/maj3 × int32/flt32) and the precision findings.

2.1 Ensemble Search Breakthrough (2026-07-31 → 08-01)

The stored-score beam-search workflow breaks the 64.9% training ceiling: every channel×encoding×xform member is trained once and exported, then a beam search selects the optimal subset. Over 19,707 archives this reaches 69.99%:

CorpusArchivesevalMembers
M1 (maj1, INT32)10,58868.62%36
M3 (maj3, FLT32)10,56169.36%109
M3 + M3.add19,70769.99%116

Important (2026-08-06): the float32 score accumulator drifts on large sums (scores ~1e9 > 2²⁴) — the float merge found 29 members/66.79% where exact int64/double accumulation finds 44/67.72%. With exact 64-bit accumulation the merge is deterministic (--max beam-as-a-whole, --tries adds nothing) and the .ens archive follows the internal format (v12 double / v13 int64).

3. Architecture

Input:  3072 px → 11 encoding blocks × 256 uint32 = 2816 containers
Layer 0: W0 (frozen, random MAJ3): NC_slice × H
Layer 1: Bayes log-Score: H → K=10 (target + offset)
Voting:  Σ_members score[k]  →  argmax

Each W0 row picks 3 random containers, MAJ3 outputs 1 if ≥2 are set → frozen binary hash. The correction loop:

  1. Score: score[k] = Σ_active target[k][bit] + offset[k]
  2. Correct: If argmax ≠ true, target[true] += step, target[pred] −= step
  3. Iterate N epochs with cosine step decay

4. Key Findings

4.1 Frozen W0 = fixed hash

Each neuron computes a fixed MAJ3 hash. If it fires for 57% of class A and 43% of non-A, the corrector can upweight it but cannot suppress the 43% false positives. This is the fundamental limit of a frozen representation.

4.2 More H gives √H returns — new record at H=1024

All runs: EN=3, ep=10, --multi-correct --splitVN 2. Only H varies.

HEvalTrainTimeConfig
6452.4%71.1%10s--hiddenN 64
12856.4%82.7%20s--hiddenN 128
25658.6%91.1%39s--hiddenN 256
51259.8%95.8%85s--hiddenN 512
102461.4%98.1%182s--hiddenN 1024
204861.2%98.9%367s--hiddenN 2048

Accuracy scales with √H: each doubling of H adds roughly +2-4pp up to H=1024. Beyond H=1024, returns invert — H=2048 reaches only 61.2% (−0.2pp) at 2× the compute. With spatial channels (ey-s-1+ey-s-2), H=512 reaches 63.5% at 16 epochs — the new sweet spot.

4.3 EN=3+ is the only lever — each EN has its own optimum epoch

Different W0 seeds draw from the same distribution. Ensemble voting with independent projections is the only lever: 3× independent random features beat 3× more features from the same projection.

All runs: H=512, encoding=ey-b,ey-a,ey-h,ey-s-1,ey-s-2 (17 members). EN and epochs vary.

ENMembersEp 10Ep 12Ep 14Ep 16Ep 17OptimumTime
35162.663.163.363.563.5ep 16272s

Spatial channels need more epochs to converge (ep 16 vs ep 10 for color-only). splitVN=2 hurts spatial channels — they need full bit resolution.

From EN=3 onward, the ensemble–epoch correlation becomes visible. Each EN has its own optimum: EN=1 peaks at ep 8, EN=3 at ep 9, EN=7 at ep 10. More members suppress overfitting — the corrector can learn longer before eval stagnates.

Best choice: EN=3, ep=9 — 60.0% in 73s. EN=7 adds only +1.3pp for 2.6× the time.

4.4 splitVN — constant target bit-mass, only filter hardness changes

All V configurations have identical target bit-mass: 10 × H × 32/V × int32 = constant. When H is scaled inversely with V (e.g. H=256 at V=1, H=512 at V=2), the target matrix consumes the identical number of bits in memory. The only difference between V values is the filter hardness of the virtual neuron grouping.

All runs: EN=7, ep=10, --multi-correct. Only --splitVN and H vary. Target bit-mass is constant: H × 32/V = 8192 for all rows.

VFilterRetentionHBest evalTimeConfig
1soft majority~50%25660.2% 155s--splitVN 1
2AND225%51261.3% 187s--splitVN 2
3AND312.5%81959.8% 238s--splitVN 3
4AND46.25%102456.4% 222s--splitVN 4

V=2 at H=512 is the champion — 61.3% in 187s. The AND2 filter removes 75% of noise while preserving enough signal. V=1 (soft majority) reaches 60.2% at the same bit-mass but lets more noise through. V=3 (AND3) and V=4 (AND4) filter too aggressively — the corrector starves even with more neurons.

4.5 Target init — three classes, one decisive metric

Seven init modes fall into three distinct classes. The decisive metric is per-neuron variation — whether different neurons have different target values for the same class.

GroupModesPer-neuron varBest evalWhy
Normal (intelligent) count, dampen, inverse, laplace ✅ data-driven co-occurrence 57.2% True signal — corrector starts near the attractor
Random random ✅ noise (no structure) 55.2% Per-neuron variation suffices for learning, but −2pp vs structured
Constant uniform, prior ❌ identical across neurons 10.0% All scores equal → gap=0 → no correction fires → no learning

Normal (intelligent) is consistently ∼2pp better than random. Whether count, dampen, inverse, or laplace — any data-driven co-occurrence structure gives the corrector a genuine head start. Polarity (count vs inverse) is irrelevant — the corrector converges to the same attractor regardless of sign.

Random (any seed) always correlates worse. Random per-neuron variation does enable learning (55.2% vs 10% for constant), but the lack of co-occurrence structure costs a consistent 2pp — independent of the seed. Variance between different seeds is <0.5pp.

Constant does not work at all. When all targets are identical per class (uniform: all = 1, prior: all = n_k), every class gets the same score for every sample. The corrector checks gap = sc[pred] − sc[true], finds gap=0, and fires zero corrections. Result: 10.0% (random chance). The corrector requires per-neuron leverage to differentiate classes.

4.6 Step schedule — cos-time always beats error-based control

Three step schedule families were tested at H=256, EN=1, ep=20, --multi-correct:

ScheduleBest evalTrainGapWhy
cos-time (default)57.2%94.2%37pp Time-based decay — step independent of error, full learning budget
pow=556.5%86.8%30pp Train-error based — step shrinks as trn drops, limits both
pow-eval=0.5..6≤54.1%61-81%varies Eval-error based — step dies too early, eval never reaches ceiling

cos-time wins every time. The step follows a fixed cosine schedule independent of the current error. This gives the corrector the full learning budget — the step only decays at the very end, preventing late-stage oscillation without starving the early learning.

Pow (error-based) self-limits. pow=N computes step = step_init × (err/total)^N. As training error drops, the step shrinks — which limits further progress on both trn and evl. Higher N gives faster decay but lower peak accuracy. The best pow value (N=5) reaches 56.5%, still −0.7pp behind cos-time.

Pow-eval starves the corrector. Basing the step on eval error instead of training error sounded promising (auto-stop when eval plateaus), but eval error drops much faster than training error. The step collapses to near-zero by epoch 5-6, leaving 40-50% of the training budget unused. Even at very low power (0.5, giving step × √eval_err), the step stays high but oscillates — the corrector never stabilizes.

Conclusion: Time-based scheduling is the only safe choice. Error-based schedules (whether train or eval) limit the corrector prematurely. --gap-k (gap damping on step) can complement cos-time when overfitting needs to be suppressed.

4.7 Encoding repeat — diversity beats quantity

All runs: H=64, EN=1, ep=10, --multi-correct. Only the encoding repeat count varies.

Repeatey-aey-bey-cey-htop-rgblatest (mixed)
46.7%46.9%46.3%39.9%39.9%
50.4%51.2%50.2%44.9%43.5%
51.8%52.0%52.0%47.0%44.7%
52.7%53.0%53.0%48.5%45.5%
53.0%49.0%
48.9%
1× (mixed)54.5%--encoding latest = ey-b+ey-a+ey-h (3 encodings, 11 members)
4 diff55.1%ey-b,ey-a,ey-c,ey-h (4 different, 15 members)
4 mixed54.9%ey-b,ey-a,ey-b,ey-h (3 diff + repeat, 15 members)

ey-a, ey-b, ey-c are the same pattern permuted. All three use up+down+sig+sig on different raw color channels: ey-b → G, ey-a → B, ey-c → R. ey-a-2, ey-b-2, ey-c-2 are color-free variants that omit the raw color block (3 blocks instead of 4) — useful for testing whether color information drives performance, or whether opponent channels alone suffice. The performance alias combines ey-b-2,ey-a-2,ey-h,ey-s-2 for a 12-member color-free ensemble. After ey-a (B) and ey-b (G) are in the system, ey-c (R) adds no new encoding structure — only another projection onto the remaining raw color channel. The information from up+down+sig+sig on RGB is already captured by the first two combinations.

More members help — but only until the ceiling. Three different encodings (latest) reach 54.5% with 11 members, beating 5× repeat of any single encoding (53.0% max) which has only 4 members. Adding ey-c (15 members) improves to 55.1% — but the gain is from the extra members, not from encoding diversity. Repeating ey-b (15 members, 54.9%) gives almost the same improvement. At low H, any extra member helps.

At high capacity, more members saturate. Running the champion config (H=1024, EN=3, splitVN=2) with 4 encodings (ey-b,ey-a,ey-c,ey-h, 45 members) yields 61.2%worse than latest (61.4%, 33 members). The extra 12 members add noise, not signal. Ensemble scaling does not work beyond ∼62% — the member ceiling has been reached.

Strong encodings converge at 4× repeat — ey-a and ey-b plateau at 53% after 4 repeats. Weaker encodings (ey-h, top-rgb) saturate earlier and lower. The 4-block encodings (ey-a, ey-b, ey-c) consistently outperform the 3-block ones (ey-h, top-rgb) by 3-5pp.

latest (11 encodings) is the empirically optimal combination.

5. Geometric Transform Ensemble (--xform)

Introduced 2026-07-16. Each active image transform (8 D4 transforms: id, hflip, vflip, dflip1, dflip2, rot90, rot180, rot270) becomes a new dimension in the member grid — like adding an extra --ensembleN but with structured geometric variation instead of random seeds. Four aliases are available:

  • --xform all — all 8 D4 transforms
  • --xform shift — all 12 pixel shifts (= augmentation - all)
  • --xform performance — id, hflip, vflip, rot90 (4 transforms, faster experiments)
  • --xform augmentation — all + shift = 20 transforms total

Note: CIFAR-10 results below use 5 transforms (flips + transposes); the 3 pure rotations were added later and not yet benchmarked on CIFAR.

Grid: ENSEMBLE[EN] × XFORM[XF] × COLOR[C] × HN[H] = EN × XF × C × H members
Each xform gets its OWN W0 + Target + Offset — trained independently.

5.1 Xform vs EnsembleN

Both multiply the member count, but through fundamentally different mechanisms. EnsembleN adds stochastic diversity (different random projections of the SAME data). Xform adds structured diversity (the SAME projection applied to transformed versions of the data).

All runs: --encoding latest (17 channels), 10 epochs.

HEN=5, idEN=1, all 5 xformsΔ
12862.2%62.7%+0.5pp
25663.2%63.4%+0.4pp
51263.4%64.3%+0.9pp
102463.1%64.4%+1.3pp

Structured beats stochastic — xforms outperform ensembleN at every H. The gap widens with H: at H=1024, the five transforms can each express genuinely different features (+1.3pp).

5.2 Simple channels benefit most

ChannelsHidall 5Δ
ey-a (4 members)12848.1%56.1%+8.0pp
latest (17 members)12862.2%64.4%+0.5-1.3pp

Simple channel sets (ey-a = 4 members on B+opponents) gain massively (+8pp) because the transforms add genuinely new signal that the few channels cannot capture. The full latest encoding (17 channels covering color, opponent, spatial) already captures most of the geometric variation — xforms add only marginal diversity.

5.3 Architecture

  1. ki_xform_raw() transforms raw uint8 pixel data before channel computation (Sobel, LBP, DoG, etc. see the transformed image → different texture signatures).
  2. Each xform produces its own container buffer, independently cached via load_input_cached_xform().
  3. Members pick their buffer via mem->input_buf. Member m with xform_id=x uses X_xform[x] for h0/gb precomputation, training, and evaluation.
  4. No special eval path — the standard gb-cache mechanism works because each member's gb_buf was computed from its own xform's buffer.

5.4 Key Findings

  1. Xforms are structural, not augmentation. Each xform gets independent W0, target, offset. Training targets are specific to each transform's view of the data.
  2. All 8 transforms are pixel-verified — single-xform runs produce identical accuracy, proving the implementation correct.
  3. Diagonal flips preserve spatial structure. dflip1 (transpose) and dflip2 (anti-diagonal) are valid geometric operations on square images — they shuffle pixels without destroying layout.
  4. Gain scales with H. Small H limits per-xform capacity. H=1024 reaches +1.3pp over ensembleN (with 5 transforms).
  5. 64.5% is the ceiling. Even with geometric diversity, the frozen MAJ3 projection cannot exceed this limit.
  6. Xforms + encoding help low H, not the ceiling. More transforms or encoding members provide extra signal that matters most at low hiddenN — but they do not raise the ceiling. The ceiling is determined by H (hidden neurons), not by input diversity. The table below compares --xform all (8 D4) vs --xform performance (4 D4) at equal --encoding performance:
H8 xforms4 xformsΔ
51264.4%63.7%+0.7pp
25664.1%63.5%+0.6pp
12863.3%62.2%+1.1pp
6461.4%59.3%+2.1pp
3258.7%57.4%+1.3pp
1654.8%53.4%+1.4pp
848.8%47.1%+1.7pp

Interpretation: At H=8, doubling the transforms from 4→8 gives +1.7pp — the extra signal is meaningful because H is the bottleneck. At H=512, the same doubling gives only +0.7pp — H is no longer the bottleneck; the data ceiling dominates. More transforms or encoding members simply accelerate the convergence curve at each H — they cannot exceed the information capacity of H neurons.

Same pattern for encoding diversity: Section 4.7 shows that at H=64, more encoding members always help (54.5% with 11 members vs 53.0% with 5× repeat). But at H=1024 (Section 4.3), adding ey-c (15 members) reaches worse accuracy than latest (11 members) — the member ceiling has been reached. More members help only until H saturates.

5.5 Pure Rotations (rot90, rot180, rot270)

Added 2026-07-16. Three pure rotations complement the flip/transpose set, bringing the total to 8 transforms (--xform all):

TokenTransformFormula
rot90Rotate 90° clockwiseout[y][x] ← in[x][H-1-y]
rot180Rotate 180°out[y][x] ← in[H-1-y][W-1-x] (= hflip+vflip)
rot270Rotate 270° clockwiseout[y][x] ← in[W-1-x][y] (= rot90⁻¹)

rot180 preserves content while reversing all spatial gradients — especially promising for CIFAR where texture orientation matters (LBP, DoG, dir channels would see flipped patterns). Not yet benchmarked on CIFAR-10; the current 64.4% record uses 5 transforms (flips + transposes).

5.6 Pixel Shifts — Resolution Diversity

Added 2026-07-16. Twelve pixel shifts (up/down/left/right × 1/2/3 px) complement the D4 geometric set. Unlike D4 transforms (which permute pixels within the image), shifts move the MAJ3 projection window, exposing different 3×3 neighborhoods at each position. Vacated pixels are filled with 0 (black), making the shift visible to all channels (Sobel gradients, LBP texture, DoG edges all see the new border).

TokenTransformEffect
sft-u1/2/3Shift upRows 1-3 from top become 0
sft-d1/2/3Shift downRows 1-3 from bottom become 0
sft-l1/2/3Shift leftCols 1-3 from left become 0
sft-r1/2/3Shift rightCols 1-3 from right become 0

Key difference from D4: Shifts change the pixel content (some pixels lost to zero border), not just the arrangement. This creates resolution diversity — the corrector sees the same object at different sub-pixel alignments, forcing it to learn shift-invariant features. The --xform shift alias activates all 12 shifts at once. Combined with D4 transforms via --xform augmentation, the grid expands to 20 transforms × up to 17 channels = 340 members. Not yet benchmarked on CIFAR-10.

6. Ceiling Update: 64.9% Single-Config, 69.99% Ensemble Selection

Ceiling progression: encoding-only 61.4% → spatial channels 63.7% → geometric transforms 64.4%--maj 1 --encoding-sizeN 32 64.9% (2026-07-24) → ensemble beam-search 69.99% (2026-08-01). Each technique adds orthogonal information sources that the frozen MAJ3 projection can exploit — but the single-training ceiling is ~65%; only the stored-score ensemble selection exceeds it.

Spatial channels (2026-07-14) break through the 62% encoding-only ceiling. Six spatial members (LBP, DoG, Variance, Gradient Direction, Local Range, Color-LBP on RG) combine with 11 color members to reach 63.7% (H=1024, EN=3, ep=16).

Geometric transforms (2026-07-16) add another +0.7pp via --xform all (tested with 5 transforms: hflip, vflip, dflip1, dflip2; now 8 with rotations). Each transform creates a new member dimension with independent W0, target, offset. Best: 64.4% (H=1024, EN=1, latest, 10ep).

Every accuracy improvement has come from a better channel or transform, not from an algorithm tweak. Target init (7 modes tested), step schedule (cos-time, pow, pow-eval), multi-correct, splitVN — none of these moved the needle beyond the encoding-only ceiling of 61.4%. Only adding genuinely new information sources (LBP → 62.3%, dir+range+lbp-rg → 63.7%, geometric transforms → 64.4%) produced measurable gains.

Critical nuance: input diversity helps low H, not the ceiling. More transforms or encoding members provide a genuine boost at small H (up to +2.1pp at H=64) — but the gain shrinks as H grows (+0.7pp at H=512). The ceiling of ~65% is determined by the number of hidden neurons, not by how many transforms or encoding members feed them. This is because the corrector has only H×32 bits of target memory — information capacity scales with H, not with input diversity. See Section 5.4 for the full data.

  1. Frozen W0 — corrector can only reweight, not create features.
  2. √H scaling — after H=512, diminishing returns dominate.
  3. Geometric transforms: structured > stochastic — xforms add +0.4-1.3pp over ensembleN at equal member count.
  4. Xform gain scales with H — at H=1024, each of 5 transforms expresses genuinely different features (+1.3pp).
  5. Simple channels benefit most — ey-a (4 members) gains +8pp from 5 transforms. Latest (17 members) already captures most variation.
  6. Training W0 collapses MAJ3 — destroys hash distribution.
  7. Deeper layers lose information — 2-layer MAJ3 lost 4pp on MNIST.

6b. August 2026 Update — Precision, IFC v7, 4-way Comparison

Precision is the feature — the float32 accumulator drifts

Once the ensemble scores reach ~1e9 (far beyond float32's exact 2²⁴ range), the float32 score accumulator rounds on every addition and the beam's gain/argmax evaluations become noisy. The same corpus searched with different accumulators:

Merge SCORE_TYPEmemberseval
float322966.79%
int64 (-int32)4467.72%
double4467.72% (= int64 exactly)

The "32-bit is free / only top bits matter" assumption is refuted. The DRAM chip accumulates popcounts exactly in integer arithmetic — the exact behavior is chip-faithful, the float32 drift was an emulation artifact. SCORE_TYPE defaults to double. The .ens archive follows the internal format (v12 double / v13 int64), and the .meta records/validates the arithmetic types. All format logic is centralized in lib/ki-ens.h (EnsReader + ens_write + ens_verify — the trainer verifies every export at write time).

The 4-way technology comparison (xform=id, 377 members)

Four corpora built identically (H=256, EP=10, seed 42, uniform W0), selection via --beam 10 --max (deterministic with exact accumulation):

corpuscumulative (best-en)beam-selected
M1-INT32 (maj1, int32)62.63%66.36% (51)
M3-INT32 (maj3, int32)61.94%65.25% (88)
M1-FLT32 (maj1, float+double)62.70%66.88% (92)
M3-FLT32 (maj3, float+double)62.02%65.44% (55)
  • maj1 > maj3 consistently (+0.68-0.69pp cumulative, +1.11-1.44pp beam-selected).
  • flt32-double ≈ int32 (±0.07pp cumulative) — with exact 64-bit accumulation the container format is neutral: the Container Principle holds once the drift is gone.
  • Winner: M1-FLT32 = 66.88% (maj1 + float counters + double accumulation).

IFC v7 — the delivery tool handles heterogeneous ensembles

model.otto v6 could not represent a heterogeneous ensemble (the CIFAR import gave 12.81% = garbage). v7 adds per-member channel/encoding/ xform metadata; a second bug (missing enc-LUT init) gave exactly 10.0% = random. Both fixed — the IFC now runs the 51-member ensemble end-to-end: 66.36% == retrain == merge. --no-ens-cache provides real-live inference on new data (compute from raw, +814ms vs the file cache). Full details: Status Report August 2026.

7. Practical Recommendations

GoalConfigResult
Max eval--hiddenN 1024 --epochsN 10 --encoding latest --xform all64.4% in 621s
Best cost/benefit--hiddenN 512 --epochsN 10 --encoding latest --xform all64.3% in 304s
Spatial channels (no xform)--hiddenN 512 --ensembleN 3 --epochsN 16 --encoding ey-b,ey-a,ey-h,ey-s-1,ey-s-263.5% in 272s

All configs use default count target init and cos-time step schedule. latest = 17 encoding members. --xform all = 8 D4 transforms (id, hflip, vflip, dflip1, dflip2, rot90, rot180, rot270), giving up to 136 total members. --xform augmentation = all 8 D4 + 12 pixel shifts = 20 transforms, giving up to 340 total members. The transform ensemble is a pure structural multiplier — no special eval path needed. CIFAR-10 results above used 5 transforms (the rotation set was added later). Shifts have not yet been benchmarked on CIFAR-10.


Documentation Source
Markdown source: workflow.md | All docs: GitHub/docs
Source code: forward-prop/ | cifar/ (trainer + merge-ensemble + ifc)