Engineering Architecture · September 2026
Building FloraFang: A 4-Layer Defense Against Neural Network Overconfidence
A few weeks into testing FloraFang on physical hardware, we ran into an uncomfortable reality: an image classifier outputting 86% confidence was misidentifying a brown recluse as a huntsman spider when shown a photograph on an LCD monitor with screen glare. Worse, when pointed at photos displayed on computer screens, the model became stubbornly confident about answers that were completely wrong.
To an untrained eye, that looks like a broken model. But if you understand the mathematics of deep learning, it is the exact expected behavior of modern neural networks. The problem was not the training data, it was our naive trust in the number coming out of the softmax layer.
“The number 86% is not a probability that the answer is right. It is the output of a softmax normalization layer over a closed-world distribution, and understanding what that actually computes explains why it was so confidently wrong.”
1. The Softmax Lie and Closed-World Trap
Neural networks do not output probabilities; they output unconstrained numerical scores called logits. To turn those numbers into percentages that look intuitive in a mobile UI, frameworks run them through a softmax function:
P(i) = exp(z_i) / Σ exp(z_j)
Notice the denominator: it forces all classes to sum to exactly 1.0 (100%). Our Core ML model has ten spider classes and zero options for “none of these.” If you point the camera at a shoe, a carpet, or a blurry monitor with screen glare, the network cannot say “I have never seen this.” It is mathematically forced to distribute 100% across those ten classes. Whichever class is least unlike the noise wins, often by an overwhelming numerical margin.
Furthermore, modern deep networks with batch normalization are systematically miscalibrated. Guo et al. documented that modern networks frequently report 85%+ confidence on predictions where empirical accuracy is barely 60%. On out-of-distribution inputs, confidence stays high while accuracy collapses.
2. Asymmetric Risk in Medical Applications
In consumer apps, errors are asymmetrical. If a music app suggests the wrong song, you skip it. But in FloraFang, the cost of an error is wildly unbalanced:
- False Positive (calling a harmless wolf spider a possible recluse): A user exercises caution and uses a cup to relocate it. Minor inconvenience.
- False Negative (calling a Black Widow or Brown Recluse harmless): A user attempts to pick it up or lets their child near it. A medical emergency.
Treating an uncalibrated 86% score as permission to declare an organism “safe” is fundamentally irresponsible. We needed an architecture that makes confident false negatives virtually impossible.
3. The Four-Layer Defense in Depth
To solve this without sacrificing offline speed, we engineered a four-layer Defense in Depth pipeline directly into FloraFang's inference cascade:
Layer 1: Out-of-Distribution & Shannon Entropy Filter
When an image contains high-frequency optical noise, motion blur, non-biological surfaces, or subpixel moiré patterns from computer monitors, the network often scatters probability across multiple classes. We compute Shannon Entropy across the 10-class distribution:
H = -Σ p_i * log2(p_i)
For 10 classes, theoretical maximum confusion is log2(10) ≈ 3.32 bits. If entropy exceeds 2.35 and top probability is below 0.55, the model is exhibiting diffuse uncertainty. The gate halts inference immediately and issues an honest refusal: “Spider: group not determined. Retake from a direct angle on a natural surface.”
The critical limitation: Shannon entropy catches diffuse confusion (“the model does not know”). It cannot catch confident misclassifications (“the model is confidently wrong”). A misclassified widow with an 86% spike has low entropy (~1.03 bits) and sails right through. That is why Layer 1 cannot stand alone, and why downstream layers exist.
Layer 2: Empirical Temperature Scaling (T = 1.53) & Agreement Veto
Rather than letting raw softmax outputs dictate decisions, we post-process the probability vector using temperature scaling:
P_calibrated(i) ∝ P(i)^(1 / T) where T = 1.53
Temperature scaling softens artificial probability spikes while preserving class ranking. Crucially, T cannot be guessed; it must be an empirically fitted parameter. By minimizing Negative Log Likelihood (NLL) over 1,946 unseen holdout observations, we fitted T = 1.53, reducing Expected Calibration Error from 10.14% down to 2.74% and establishing benignFloor = 0.86. To eliminate remaining false reassurances, Layer 2 pairs this with a secondary 3-class agreement veto model.
Layer 3: Dual-Tier Corroboration (Foundation Models Shield)
Core ML is a specialized CNN, but Apple Intelligence provides an on-device multimodal language model (SystemLanguageModel). In our cascade, a benign call is never accepted on Core ML's vote alone on supported devices (iOS 27+).
Both models evaluate the organism independently. If Core ML suggests a benign huntsman but Apple Intelligence spots ambiguous red abdominal spots or violin markings, the system automatically escalates to maximum caution. Exclusions of Widows or Recluses are strictly impossible without full corroboration across both tiers.
Layer 4: Honest Clinical UX Framing
We eliminated the words “Harmless” and “Generally safe” across the entire app. They were replaced with the clinical toxicology standard: “Not medically significant.” Every benign card includes an explicit reminder: “While this species has no venom of medical concern to humans, wild spiders can still deliver a defensive bite if pinched. Leave undisturbed.”
4. The Empirical Holdout Sweep: What the Data Revealed
To measure the model's true calibration and establish defensible operating thresholds, we pulled an isolated holdout set of 1,946 research-grade iNaturalist observations across all 10 classes. The fetch script explicitly read every observation ID already on disk and excluded it, ensuring the model had never encountered any of these images.
We then ran calibrate.py over the entire holdout set. The findings grounded our theoretical architecture in hard empirical numbers:
A 73% Reduction in Calibration Error
Before calibration (T = 1.0), raw softmax confidence was systematically disconnected from reality. In the 80 to 90% confidence range, actual accuracy was barely 66.2% (a +18.9% overconfidence gap). By grid-searching the temperature that minimizes Negative Log Likelihood, the optimizer converged at T = 1.53 (NLL 1.2014).
| Confidence Bucket | Raw Accuracy (T=1.0) | Calibrated Accuracy (T=1.53) | Calibrated Gap |
|---|---|---|---|
| 0.2 to 0.3 | 20.0% | 30.0% | -0.034 |
| 0.3 to 0.4 | 30.1% | 35.4% | -0.003 |
| 0.4 to 0.5 | 31.8% | 44.4% | +0.005 |
| 0.5 to 0.6 | 45.0% | 57.1% | -0.022 |
| 0.6 to 0.7 | 50.2% | 64.3% | +0.009 |
| 0.7 to 0.8 | 57.9% | 73.1% | +0.021 |
| 0.8 to 0.9 | 66.2% | 84.0% | +0.013 |
| 0.9 to 1.0 | 86.6% | 93.3% | +0.024 |
Under T = 1.53, Expected Calibration Error (ECE) plunged from 0.1014 down to 0.0274. In the critical 0.8 to 0.9 confidence band where our 0.86 benign floor operates, the calibrated model closely aligns with empirical reality: mean confidence of 85.3% corresponds to 84.0% accuracy (a +0.013 gap), eliminating the raw model's 18.9 percentage point overconfidence gap.
Crucially, calibration does not create uniform perfection across every bucket. The top 0.9 to 1.0 bucket still carries a small residual overconfidence gap (+0.024, running at 95.8% mean confidence against 93.3% accuracy). Temperature scaling dramatically improves reliability in the decision zone, but residual gaps are why a single probability score cannot stand alone as a safety authority.
Deriving the Benign Floor: 0.86
In medical toxicology, telling someone an organism is benign is the claim that causes injury if wrong. We derived benignFloor as the minimum calibrated confidence where benign predictions achieve at least 95% precision. The data demonstrated that our earlier 0.55 threshold was far too permissive: benign calls only become 95% reliable when calibrated confidence reaches 0.86. We updated ConfidenceGate.swift accordingly.
Controlling False Reassurance: 0 of 346 with the Agreement Veto
Crucially, calibration and thresholds control the false reassurance rate. Across 346 held-out real widows and recluses under T = 1.53, a permissive 0.38 floor emits a benign reassurance on 82 of 346 (23.7%). Raising the threshold to our derived 0.86 benign floor drops false reassurance to 1 of 346 (0.29%). The variable here is the threshold floor, not temperature scaling alone.
By pairing the primary 10-class model with a secondary 3-class agreement veto on confident benign calls, that single caught edge case was intercepted, reducing holdout false reassurance to 0 of 346 (0.00%) at a cost of 15 benign scans converted to cautious refusals.
Every one of the first five errors was a recluse, and the single 0.86 failure was a recluse too (recluse_301073617.jpg at 0.911 predicted as huntsman, which the secondary agreement veto catches as a permanent regression baseline). While widows fail more often in aggregate due to lower recall, the failures that survive above the floor are brown wanderers misread as harmless spiders at high confidence.
Stated honestly: zero of 346 rests on one caught case in one holdout dataset. It is a measurement on a benchmark, not an absolute guarantee, and any future gate model must be retested against this benchmark rather than inheriting the score.
Why Multi-Model Defense Is Mandatory
The most consequential discovery came when deriving the dangerous-class recall floor. The script checked whether any confidence threshold could capture ≥95% of real Widows and Recluses:
“Even at zero threshold the model only classifies 66.5% of real widows and recluses into a dangerous class. The ceiling is the model, not the threshold.”
On 33.5% of real dangerous specimens, the vision classifier ranked a harmless family (such as huntsman or wolf spider) as its #1 choice. Because temperature scaling is strictly monotonic, no threshold adjustment on top-1 confidence can ever recover those misclassifications.
This proves why multi-model defense is mandatory. On device today across all supported iOS versions, the dual-model agreement veto pairs two independently trained Core ML models to catch dangerous false negatives before they can be shown to the user. For devices running iOS 27+, Layer 3 (Apple Intelligence Foundation Models) adds an anatomical visual screen to corroborate physical markings.
Hierarchical Triage: Three Attempts and Majority Class Collapse
During architecture optimization, we explored collapsing harmless spiders into a single class to build a dedicated 3-class primary gate (hazard3: widow, recluse, not medically significant). Three controlled runs tested this hypothesis on the same holdout:
| Benign to Dangerous Ratio | Training Images | Dangerous Recall | Holdout Outcome |
|---|---|---|---|
| ~1 to 1 | 3,013 | 68.5% | Best of three, 2 points over baseline |
| 3 to 1 | 3,341 | 57.8% | More benign data, worse recall |
| 12 to 1 | 8,814 | 8.1% | Textbook majority class collapse |
The 12 to 1 run exposed the limits of Create ML. Because it minimizes symmetric cross-entropy with uniform sample weights, when 85% of samples were benign, the optimizer minimized loss by predicting benign 99% of the time. Holdout accuracy read 82.3% while dangerous recall collapsed to 8.1% and standalone false reassurance skyrocketed to 91.9%.
Volume is not the bottleneck; unweighted benign data actively degrades safety. The 3-class model was therefore repurposed into a one-direction agreement veto, where its orthogonal error profile stops false reassurances without acting as a triage authority.
The 11.3-Point Preprocessing Discovery: Stretched vs. Letterboxed
While testing inference preprocessing, we uncovered a striking demonstration of train/test mismatch. An initial intuition was that we should letterbox photos (.scaleToFit) to avoid squashing spiders and preserve their 8-leg geometry. But when we evaluated both approaches across the exact same 1,946 holdout images, changing only this single variable, the numbers diverged dramatically:
| Preprocessing Method | Holdout Accuracy | Dangerous Class Recall | Fitted T (NLL) |
|---|---|---|---|
Stretched (.scaleToFill) | 60.9% | 66.5% | 1.53 (1.2014) |
Letterboxed (.scaleToFit) | 56.2% | 55.2% | 1.64 (1.3323) |
Letterboxing caused an 11.3 percentage point collapse in dangerous class recall. Why? Because Apple's Create ML training pipeline squashes training images to 299×299 rather than letterboxing. The black padding bars introduced border artifacts the convolutional filters never saw in training, while shrinking the spider's pixel resolution. Changing request.cropAndScaleAction to .scaleToFill to match training recovered those 11.3 points instantly: a vivid reminder that preprocessing alignment often impacts medical recall far more than model hyperparameters.
5. The Plant Model: Same Method, a Harder Failure
Everything above was built for the spider path. The plant toxicity model, PlantHazard.mlmodel, had never been run against a holdout at all until this pass, so we pointed the same methodology at it: a 1,711-image leakage-protected holdout, temperature fitted by grid search, thresholds derived from the calibrated numbers rather than guessed.
Uncalibrated accuracy came back at 76.4%, ECE 0.095. Fitting temperature converged at T = 1.62, cutting ECE to 0.019, in line with what temperature scaling did for the spider model.
Applying that fix surfaced a real bug, not just a missing number. The spider classifier applies temperature scaling on device before any threshold ever sees the result. The plant classifier didn't: it compared its species-naming threshold against raw, uncalibrated softmax, so the number derived from calibration and the number actually being checked in the app lived in two different spaces. Caught by reading the two classifiers side by side, not by a test failing.
| Version | Threshold space | namingFloor | Species accuracy | Toxic recall, named calls |
|---|---|---|---|---|
| Before | Raw, uncalibrated | 0.45 | 80.5% | 93.1% |
| After | Calibrated (T = 1.62) | 0.82 | 95.0% | 58.0% |
That is a trade, not a strict win: raising the floor to make a named species 95% reliable costs 35 points of recall on named calls. Worth it, because a specific wrong species name sends someone down the wrong path with a toxic plant. But it means 42% of real toxic plants that used to get a (often wrong) name now get no name at all.
The natural next question is what happens to that discarded 42%. The model's top-1 guess lands on some toxic class, right species or wrong, for 97.5% of real toxic holdout images; only 2.5% land on the benign class. So most of what the floor throws away was still correctly flagging "this is toxic," just unsure which one, and today that signal is discarded along with the bad guess. A middle tier, something like "likely toxic, species unclear," looks like the obvious fix.
We tried building that tier directly from the model's own output, two different ways: summing probability mass across every toxic class, and simply checking whether the top-1 guess was any toxic species at all, regardless of confidence. Both fail the same way. 61.5% of the 200 genuinely benign plants in the holdout still get a toxic species as the model's top-1 guess, at any confidence threshold, including zero. The model's own benign class just isn't well separated. A middle tier built on top of it would flag most harmless garden plants as possibly toxic, trading one credibility problem for a worse one.
The spider path avoids this exact failure with a second, independently trained model, SpiderHazardGate.mlmodel, that votes on a completely different class structure and only ever vetoes a benign call, never asserts one. Two models that fail differently and happen to agree is real information. Reading one model's own output two different ways is not. The plant path has no equivalent second model yet; building one, or substantially growing and diversifying the benign training class, is the actual fix, and it is not built.
The Takeaway
Good machine learning engineering is not about celebrating high accuracy numbers in a notebook; it is about engineering safety systems around how models fail in the real world. By accepting that neural networks are fundamentally overconfident, measuring our model's limits on unseen data, and requiring multi-model consensus, we replaced blind trust in a single number with an architecture that protects real people in the field. The plant model is the honest counterexample: it doesn't have that second model yet, and Section 5 is what that gap actually looks like once you go measure it instead of assuming the architecture generalizes for free.