Noise, Precision and Calibration

Ask a digital INT8 multiplier for 73 \times 41 a billion times and you get 2993, a billion times. Ask an analog photonic MAC and you get a billion slightly different answers: a distribution, centred (if you have calibrated well) on the truth, with a width set by physics. Digital arithmetic pays for its exactness up front, in the quantisation grid you studied in quantization for inference and the rounding model of floating-point error. Analog arithmetic pays as it goes, in noise — and this lesson is about computing the exchange rate. The currency is the effective number of bits (ENOB), and the headline, worth stating before the derivation: every demonstrated analog photonic processor delivers roughly 4 to 8 effective bits, the cost of each additional bit is in photons (or time), and the reason photonic AI is viable at all is that inference — uniquely among computing workloads — can often live inside that budget.

From noise to bits: the ENOB argument

Two noise floors matter at a photodetector. Shot noise is the fundamental one: light arrives as photons, photon counts are Poisson-distributed, and a Poisson variable with mean N has variance N — so the power signal-to-noise ratio of a detection event that collects N photons is \mathrm{SNR} = N. Thermal (Johnson) noise comes from the receiver electronics; it is a fixed floor, independent of the light, which dominates at low optical power (shot noise takes over at high power). To turn an SNR into bits, borrow the converter engineer's yardstick — an ideal b-bit quantiser has \mathrm{SNR_{dB}} = 6.02\,b + 1.76 — and read it backwards:

Work the budget at \lambda = 1550 nm, where a photon carries 1.28\times10^{-19} J. Eight effective bits needs \log_2 N = 2(8 + 0.29) \approx 16.6, i.e. N \approx 10^5 photons — about 13 fJ of light per detection, before any electronics. Four bits needs only N \approx 380 photons — 0.05 fJ. Precision is exponentially expensive; that single fact shapes every design decision in this field, and it is why the energy ledger of lesson 7 will treat "how many bits?" as its first question.

Watch a network drown: noise injection in code

How much of this noise can a neural network actually absorb? Below is a complete, fixed two-layer network — 4 inputs, 6 ReLU hidden units, 3 classes — classifying noisy samples of three prototype patterns. Every single MAC result receives fresh Gaussian noise of standard deviation \sigma (the analog accelerator model: weights and signals are order-1 numbers, so \sigma = 0.1 loosely mimics a ~3-bit-noisy multiplier). The PRNG is seeded, so your runs are reproducible. Sweep \sigma and watch the accuracy and the output drift:

// Deterministic PRNG (mulberry32) + Box–Muller, so runs reproduce exactly. let seed = 42; function rand(): number { seed = (seed + 0x6d2b79f5) | 0; let t = Math.imul(seed ^ (seed >>> 15), 1 | seed); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; } function gauss(): number { return Math.sqrt(-2 * Math.log(Math.max(rand(), 1e-12))) * Math.cos(2 * Math.PI * rand()); } // Three orthogonal 4-dim prototypes; class c samples cluster around p[c]. const p = [ [1, 1, -1, -1], [1, -1, 1, -1], [1, -1, -1, 1] ]; // Fixed 2-layer net: hidden_i = ReLU(±p_i · x), logit_c = hidden_c − hidden_{c+3}. // (So the clean network computes exactly logit_c = p_c · x — but through real MACs.) const W1 = [ ...p, ...p.map((row) => row.map((w) => -w)) ]; // 6×4 const W2 = [ [1, 0, 0, -1, 0, 0], [0, 1, 0, 0, -1, 0], [0, 0, 1, 0, 0, -1], ]; // 3×6 function noisyMatvec(W: number[][], x: number[], sigma: number): number[] { return W.map((row) => { let acc = 0; for (let j = 0; j < row.length; j++) acc += row[j] * x[j] + sigma * gauss(); // noise per MAC return acc; }); } const relu = (v: number[]): number[] => v.map((a) => (a > 0 ? a : 0)); const forward = (x: number[], sigma: number): number[] => noisyMatvec(W2, relu(noisyMatvec(W1, x, sigma)), sigma); const argmax = (v: number[]): number => v.indexOf(Math.max(...v)); // A fixed test set: 300 samples, 100 per class. const data: { x: number[]; label: number }[] = []; for (let c = 0; c < 3; c++) for (let i = 0; i < 100; i++) data.push({ x: p[c].map((a) => a + 0.5 * gauss()), label: c }); console.log("sigma accuracy rms logit drift"); for (const sigma of [0, 0.05, 0.1, 0.2, 0.5, 1.0, 2.0]) { let correct = 0, drift2 = 0, count = 0; for (const d of data) { const clean = forward(d.x, 0); const noisy = forward(d.x, sigma); if (argmax(noisy) === d.label) correct++; for (let c = 0; c < 3; c++) { drift2 += (noisy[c] - clean[c]) ** 2; count++; } } const acc = (100 * correct / data.length).toFixed(1); const rms = Math.sqrt(drift2 / count).toFixed(3); console.log(sigma.toFixed(2) + " " + acc + "% " + rms); }

The shape of the result is the whole story of analog AI hardware. Small \sigma costs essentially nothing — the class margins are wide, and a per-MAC wobble of a few percent vanishes inside them. Then, once the accumulated noise (\sigma\sqrt{K} per dot product, compounding through two layers) becomes comparable to the margin between the top two logits, accuracy falls off a cliff. Networks tolerate low precision up to a workload-dependent threshold, and fail fast beyond it — the same phenomenon that makes INT8, and often INT4, quantisation nearly free for inference while training stays in high precision. An analog accelerator's job is to keep the whole chain, end to end, on the safe side of that cliff.

Calibration: what you can fix, and what you can't

Not all error is noise, and the distinction decides what engineering can do about it. Systematic error — fabrication offsets in coupler ratios, phase-shifter miscalibration, thermal crosstalk between neighbours, detector mismatch — is repeatable: the same wrong answer every time. Repeatable means measurable, and measurable means correctable: that is the entire business of mesh calibration, and of the ring-locking loops from last lesson. Stochastic noise — shot, thermal, laser intensity noise — is fresh on every pass; no lookup table can subtract it. Your only levers are more photons, more averaging (4× per bit, paid in throughput), or a network trained to shrug it off — which is precisely the "noise-aware training" idea the next lesson develops. The honest engineering summary: calibration moves the error distribution's centre onto the truth; physics fixes its width.

Because both are quoted in "bits", it is tempting to treat a 6-ENOB analog MAC as interchangeable with INT6 arithmetic. They are different animals. Quantisation error is deterministic: the same input always rounds the same way, the network was (or can be) fine-tuned around exactly those roundings, and a quantised model is perfectly repeatable — run it twice, ship it anywhere, same answer. Analog noise is stochastic: the same input gives different outputs on every pass, so a marginal sample near a decision boundary flickers between classes — maddening for testing, certification and any system that must reproduce its decisions. The flip side: averaging m passes improves noise by \sqrt{m} but does nothing whatsoever for quantisation bias, and noise-aware training can flatten the loss landscape against random perturbations far better than against a fixed grid. When a photonic paper reports "8-bit-equivalent accuracy", always ask: equivalent in distribution centre, or per single shot? The two claims differ by exactly the averaging factor — and the averaging factor is paid in throughput, which was the product's selling point.

The quantiser yardstick \mathrm{SNR_{dB}} = 6.02\,b + 1.76 looks like numerology but is two lines of statistics. A b-bit quantiser spans its full-scale range with steps of size q = \mathrm{FS}/2^b, and rounding scatters each sample uniformly within \pm q/2 — a uniform error of variance q^2/12. For a full-scale sine wave (signal power \mathrm{FS}^2/8), the ratio works out to \tfrac{3}{2}\cdot 4^{\,b}; in decibels, 10\log_{10}(\tfrac{3}{2}) + b\cdot10\log_{10}4 = 1.76 + 6.02\,b. So "6 dB per bit" is just 4^b in logarithmic clothing, and the 1.76 is the sine wave's crest factor — a convention inherited from ADC datasheets. It is a slightly arbitrary yardstick for a neural network's signals, but the field uses it because the ADCs bounding every photonic accelerator are specified with it — and, as lesson 7 will show, those ADCs usually are the accelerator's precision bottleneck.

Where this goes next

We now know the analog substrate's honest resolution: a handful of bits, centred by calibration, widened by physics. The next question is how to make a network at home there. Training on a perfect digital twin and downloading the weights turns out to fail in a characteristic way — and the fixes, from hardware-in-the-loop gradients to physics-aware training, are the subject of the next lesson.