Blog
hedwigaihedwigaihedwigai

Writing

The scale of visual intelligence

We took a structured-extraction-from-images task from a 235-billion-parameter teacher down to a 2-billion-parameter student without losing accuracy. The 2B reads as well as the 8B of the same Qwen vision-language family once it can see the digits: on this task, intelligence scale saturates early. Perception does not. This post is how we found that saturation point, and why we stopped there. The 2B now serves in place of the 8B, 2.4× faster on the same GPU.

Brains come in sizes

Nervous systems span eight orders of magnitude, and each one is big enough for the life it leads. A nematode finds food and avoids harm with 302 neurons. A honeybee navigates, learns flowers and dances directions with under a million.

OrganismNeuronsSynapsesWhat it manages
Nematode (C. elegans)302~7,500Chemotaxis, avoidance, simple learning
Larval zebrafish100,000—Hunting prey by sight
Fruit fly150,000—Flight, courtship, odour memory
Honeybee960,000~1 billionNavigation, flower learning, the waggle dance
House mouse71 million~1 trillionMapping space, social behaviour
Human86 billion—Language, mathematics, writing blog posts

A synapse is the closest biological cousin of a model parameter: a learned connection strength. The analogy is loose, but the lesson carries over. Evolution does not give a bee a mouse’s brain, because a bee’s tasks are already saturated at a million neurons.

Every task has a saturation point

We use intelligence scale to mean a model’s parameter count. For any one task, accuracy rises with intelligence scale and then goes flat. The flat part is the saturation point: past it, more parameters buy nothing for that task.

The practical question is where a given task saturates. Answer it, and you can serve the smallest model that does the job, on cheaper hardware, at lower cost. Our claim, from one vision task: the curve can look unsaturated when the real limit is somewhere else. Fix that limit, and a small model sits on the plateau.

A vision model has a second scale. We use perception scale to mean how finely the model samples its input: here, how many vision patches cover each character. The two scales saturate separately. A model can sit past its intelligence saturation point yet short of its perception one, and then its errors look like a lack of intelligence.

Task: structured extraction from images

The task is structured extraction from photographs. Given a photo and a list of fields, the model returns each field’s exact value as JSON. The test set has photographs with digital, analog and hybrid data, with 18 values per photograph set to capture.

The photographs are hard: faded signals, shadows and oblique angles.

Step one: 235B to 8B

We did not start small. The first reader was Qwen3-VL-30B-A3B, a mixture-of-experts model with about 3B parameters active per token. The teacher was Qwen3-VL-235B-A22B, which labelled the training photographs. Scored on about 510 check-verified fields:

ReaderCheck-verified fields correct
Qwen3-VL-30B-A3B, reading the whole photograph71.9%
Qwen3-VL-235B-A22B, the teacher81.1%
Qwen3-VL-8B, fine-tuned on the repaired labels94.9%

The student scored above its teacher. It trained on the teacher’s answers after they were checked and repaired, not on the raw answers.

From here the reference is that 8B student, fine-tuned with LoRA on about 4,400 labelled photographs. On 50 held-out photograph sets, counting all 613 values, it reads 94.6% correctly.

Step two: 8B to 2B, and a false floor

We distilled the 8B into Qwen3-VL-4B and Qwen3-VL-2B: same training data plus 156 photographs the 8B labelled, three epochs each. The 4B reached 93.3% and the 2B 91.5%. On its own, that looks like the familiar story: halve the parameters, lose accuracy.

The errors told a different story. Of the 2B’s 52 wrong values, 35 differed from the truth by a single digit: 8 read as 0, 5 as 3, 6 as 4. The model found the right field and read the right number of characters. It confused shapes that differ by a few pixels.

Looking inside the 2B

The 2B’s decoder was doing its job; the evidence never reached it. We replayed 22 distinct misread digits, each paired with a neighbouring digit the model read correctly, and measured the model’s preference for the right digit over the wrong one.

MeasurementMisread digitsCorrect digits
Logit margin, right minus wrong digit−1.6+8.4
Right digit is the model's second choice18 of 22—
Attention on image tokens, decoder layers 17–250.24–0.28same
Fixed by upsampling the photo 1.5×, no retraining13 of 220 of 22 broken
Fixed by upsampling the photo 2×, no retraining17 of 220 of 22 broken

Three readings follow:

  • It looks in the right place. Attention on the image is the same whether the digit comes out right or wrong.
  • It decides late, and only with evidence. A logit lens (projecting each layer’s state onto the vocabulary) shows correct digits locking in at layers 20–23 of 28. On misreads, the right digit never pulls ahead.
  • The information is in the photo. Upsampling adds no new detail, yet it fixed 77% of misreads and broke none. The model could not resolve what was already there.

It was the eyes

A digit in the hybrid signal of our photographs is smaller than the patch the vision encoder reads it through. Qwen3-VL cuts an image into 16×16-pixel patches, then merges each 2×2 block into one token for the language model.

WhatSize in a 900×1,600 photo
One digit, hybrid signal~7 px wide, ~8 px tall
Line spacing~15 px
One vision patch16 × 16 px, about 2 characters
One language-model token32 × 32 px, about 4–5 characters across 2 lines

So an 8 and a 0 that differ in a few pixels can land in the same patch and blur together before the decoder ever sees them. Upsampling the photo 2× gives each digit about 2×2 patches. The pixels are the same; the encoder simply samples them finely enough.

This is a sensory limit, not a cognitive one. A hawk does not need a bigger brain to spot a mouse; it needs a denser retina.

The curve after the fix

At the original resolution, accuracy climbs with size and looks unsaturated. Read the same photos at 2×, with no retraining, and every size lands on the same plateau: 96.7% for the 2B and the 8B, 97.4% for the 4B. For this task, the plateau starts at or below 2 billion parameters.

Set side by side, the two scales move accuracy by different amounts:

Values read correctly, 50 held-out photograph sets, 613 values; 1.5× and 2× are the same photographs resampled
Intelligence scalePerception 1×Perception 1.5×Perception 2×
2B91.5%94.8%96.7%
4B93.3%not tested97.4%
8B94.6%not tested96.7%

Quadrupling parameters at 1× gains 3.1 points. Doubling the sampling of the same 2B gains 5.2. At 2× the intelligence axis is flat: the 4B gains 0.7 points over the 2B, and the 8B reads exactly what the 2B reads, 593 of 613 values. The perception axis was the one still climbing.

Retraining the 2B on 2× photographs added nothing: 96.4% against 96.7% for the same model simply shown 2× photographs. The gain is all in what the model is given to look at.

Real pixels did no better than resampled ones. The original photographs carry 1.4× the pixels of the copies above. Read at the same image-token budget they score 96.6%; enlarged 2×, at about 7,800 tokens, 97.2%, three values more. Perception saturates too, at about this budget.

Inside the 8B: most of it idles

With half of its MLP neurons switched off, the 8B still reads 98.3% of digits right. The 2B, cut the same way, falls to 34.9%. The larger model is not using its size on this task.

We gave all three models the same 150 photographs and the same target text (the 8B’s answers) and recorded every layer on about 13,700 answer tokens. Then we switched parts off and measured what was lost.

ModelResidual widthDirections holding 90% of the variance (median layer)Share of the widthLayers removable one at a time (≤ 1 pt digit loss)
8B4,0961513.7%19 of 36
4B2,5601345.2%33 of 36
2B2,0481225.9%15 of 28

The task lives in about 120 to 150 directions, whatever the width; the participation ratio is about 38 in all three. The 8B spends 4,096 dimensions on what fits in 151. Its extra size buys spare copies, not new features: half its MLP can go and the reading holds, where the 2B has no slack at all. In every model only the first layer is irreplaceable.

Two cautions. The target text is the 8B’s own, so its starting accuracy (99.8%) is flattered; compare the drops, not the starting points. And the activations are dense: 74–82% of neurons carry 90% of the activation mass in every model, so the spare capacity shows only when parts are removed, not when activity is counted.

Serving it: the small model was slow until the engine changed

On the same GPU, the 2B at 2× first read a photograph set in 29 s, slower than the 8B’s 24 s. A serving engine took it to 10 s.

The time was not in the model. Per photograph, the vision encoder took 1.0 s and the prefill 0.4 s; then decoding ran at 25 ms a token. Reading 2B bf16 weights once per token takes about 5 ms on that card. The other 20 ms was the generation loop launching hundreds of small GPU kernels from Python, one after another. A large model hides that overhead behind real work in each kernel; a 2B model cannot.

A serving engine (vLLM) records a whole decode step once as a CUDA graph and replays it with a single launch. It also batches the three photographs of a set as they arrive, and drops each one as its answer ends. A set then takes about as long as its longest photograph, not the sum. Batching in the old loop made things worse (38 ms a token), because it pads every answer to the longest.

Setup, one A10 GPUPer photograph set, warmPer set, from coldValues read correctly
8B, plain generation loop24 s~45–50 s94.6%
2B at 2×, plain generation loop29 s—96.7%
2B at 2×, serving engine10 s~105 s96.7%
2B at 2×, serving engine + GPU snapshot10 s14–19 s96.6%

A serving engine is slow to start: loading weights and capturing graphs took about 105 s, and the reader scales to zero between sets. The fix is a GPU memory snapshot of the warmed engine, taken while it sleeps, with its weights parked in CPU memory and its empty KV cache dropped. A cold start restores the snapshot and wakes it.

The answers did not move. The served 2B makes the same 20 errors as the offline run. Between runs, about 6 of 1,250 raw values differ, all on faint photographs, because results depend slightly on which requests share a batch.

The GPU time billed per photograph set fell from about 120 s for the 8B to 45–65 s for the 2B, so a set costs less than half as much. Most of what remains is the platform keeping each container up about 44 s after its last read, whatever idle window we set.

Why we stopped at 2B

Warm, the served 2B spends about 1.75 s on each photograph before its first output token, then 12 ms per token. Nearly all of that 1.75 s is the GPU looking at the photograph.

Step, per photographTime
Decode and enlarge the JPEG (CPU)0.07 s
Image preprocessing (CPU)0.28 s
Vision encoder and prefill (GPU), to the first token~1.45 s
Writing the answer (GPU)12 ms a token: 0.4 s for 34 tokens, 3.1 s for 263

At 2× a photograph becomes about 22,000 vision patches and 6,000 tokens. By our estimate that is around 9×1013 operations, which keeps an A10 busy for most of those 1.45 s.

We tried three more ways to go faster without losing accuracy. None was worth shipping:

  • Speculative decoding from the prompt (n-gram lookup): 12 → 9.6 ms a token, but a set only 9.3 → 8.9 s, at 96.6% against 96.9%.
  • Cropping to the foreground: the background is only 16% of the area, and accuracy fell to 96.2%.
  • CPU instead of GPU: 126 s to the first token for one photograph on 8 cores, then 0.47 s a token, about 10 minutes a set.

A smaller student would not help much either. By our estimate about 70% of the work per photograph is the vision encoder, which is the same size in every model of the family. Shrinking the language model below 2B would save perhaps 3 s a set and restart the accuracy question.

In production, the first clean requests on the 2B took 27 s and 33 s end to end from a cold start, against 64–131 s with the 8B. About 10 s of that is reading; most of the rest is the GPU container starting.

How we found the saturation point

  1. Step down until accuracy drops. 8B 94.6%, 4B 93.3%, 2B 91.5%: it looked like the familiar size curve.
  2. Read the errors. 35 of the 2B’s 52 misses were one digit off, in the right field, at the right length.
  3. Look inside. On misreads the right digit was the second choice 18 times in 22, with the same attention on the image: the evidence was not reaching the decoder.
  4. Raise perception scale alone. Reading the same photographs at 2× fixed 17 of 22 misreads, broke none, and took the 2B to 96.7%.
  5. Check from above. The 8B still reads 98.3% of digits with half its MLP neurons off; the 2B has no such slack. The 2B sits at the edge of the plateau.
  6. Stop where the next step saves little. Below 2B only the language model would shrink, while the vision encoder does about 70% of the work.

What it means

Before buying a bigger brain, check the eyes. If a smaller model’s errors are near-misses on fine detail, its limit is perception, and resolution is cheaper than parameters.

  • Read the errors before the score. A one-digit substitution and a wrong field are different failures with different fixes.
  • Test the input before the architecture. Upsampling at inference cost us nothing to try and moved accuracy more than doubling the model did.
  • Measure the serving stack, not just the model. At 2× the 2B sees 4× the image tokens, and in a plain generation loop it ran slower than the 8B. The loop’s overhead, not the model, set the speed: a serving engine made the same 2B 2.4× faster than the 8B on the same GPU.
  • Stop where the curve goes flat. At 2× the 2B reads exactly what the 8B reads, at less than half the GPU time per set. Below it, the part that dominates the work, the vision encoder, would not shrink.
  • List of animals by number of neurons, Wikipedia — neuron and synapse counts.
  • Model results: our own evaluation, 50 held-out photograph sets, 613 values, scored against hand-checked and cross-verified truth.

hedwigai

More head-to-head evals

Ten models plan a change to a spreadsheet: which do it in under a minute, traced call by callTen models drive one agent harness through the same spreadsheet request; six write the plan, timed and traced call by call.
MeasureQwen3 235BGLM-5.2Gemini 3.8 FlashClaude Opus 5
Seconds to the plan, median27485794
Plans written, of three runs2333
Read the comparison
SubQ, jev, Perplexity's Decider and Bespoke's Nimble on biotech diligence memos: finding the sentences a column is aboutFour decision models judge every sentence of ten biotech diligence memos for five columns, scored against sentences a person marked.
MeasureSubQjevDeciderNimble
Found, mean of five columns at section length64%65%66%68%
Mechanism of action, found at section length57%51%61%54%
Read the comparison
Leads with a reason to write: hedwigai ask, Apollo and treg on one brief40 leads each, every one checked: the right person, an inbox that accepts, and a dated reason to write.
MeasureaskApollotreg
Usable leads13 of 407 of 406 of 28
Cost per usable lead$0.037$0.27$0.23
Read the comparison
Self-hosted decisions for ask: Perplexity's open Decider in place of jev on 92 company questionsThe decisions inside hedwigai ask made by Perplexity's open Decider on two NVIDIA RTX 3090s, against jev.
Measureask with jevask with Decider
Questions right, of 928989
Wrong answers12
Read the comparison
Clinical decisions: jev and ask on System One, PubMedQA, SciFact and a 370-decision setEdgeEvals' System One board, PubMedQA, SciFact, and a clinical set built to System One's rules.
Measurejevask
Our 370 clinical decisions, right94.6%93.0%
PubMedQA, right (best EdgeEvals scored: 62.2%)77.0%74.4%
Read the comparison
Executive lookup for US-listed companies: Claude Opus 5.5 and ask on 95 questionsWho runs a public company, and how to email them: a frontier model from memory against hedwigai ask.
MeasureaskClaude Opus 5.5
Questions right, of 955963
Small companies right, of 20139
Read the comparison
Rental comps: floor-plan rents and amenities on 14 listings, five assistants comparedRent per floor plan and amenities for US rentals: hedwigai realestate-us against Claude, GPT, Gemini and Perplexity with web search.
Measurerealestate-usBest of four assistants
Floor-plan rents right, of 262623
Amenities claimed the listing doesn't state12129
Read the comparison
Company screening from SEC filings: jev, Vela 2.0 and ask on 92 yes/no questionsYes-or-no questions about public companies, answered by two decision models alone and by hedwigai ask.
Measureaskjev
Right, of the questions answered98%79%
Wrong answers, of 92219
Read the comparison
Defect localization in industrial images: four frontier models and a trained localizerFour frontier models asked to put a box around what they just described.
MeasureTrained localiserBest of four frontier models
Mean overlap with the defect (IoU, 0 to 1)0.4210.109
Read the comparison