All models

EEG reconstruction · fp32 profiles

ZUNA1.1 · Core ML

Missing channels, estimated on device.

Zyphra’s ZUNA1.1 on Apple platforms: EEG denoising, missing-channel reconstruction, and spatial superresolution in Core ML.

Open on Hugging Face
Upstream
Zyphra ZUNA1.1 · 380M
Window
5 s at 256 Hz
Precision
fp32 only
Default profile
14 channels, EPOC X layout
License
Apache-2.0
Updated
18 Aug 2026

Overview

ZUNA1.1 is Zyphra’s masked diffusion autoencoder for scalp EEG. Given a subset of channels and their 3D electrode positions, it denoises what was measured, estimates what was not, and can predict signals at new positions on the scalp.

This release brings the pretrained model to Apple platforms as fixed Core ML profiles. The default profile matches the 14-channel Emotiv EPOC X layout, so a consumer headset’s recording can be cleaned and extended on the device that receives it.

Fig. 01 · Illustration

Fourteen electrodes, three missing

ZUNA takes the channels that were recorded, with their 3D positions, and estimates the ones that were not by iterative denoising.

5 cmTop view · t = 3.53 s

Denoising step 20/20
F3measured
F4estimated
T7estimated
P8measured
O2estimated

Seconds · synthetic, not recorded EEG

The head is the FreeSurfer fsaverage average scalp, seen from above and drawn to scale, with the real EPOC X electrode positions (MNE standard_1005). Traces and scalp field are synthetic, drawn to show the task: not recorded EEG and not model output. The field is a spherical-spline interpolation at one instant, t = 3.53 s, chosen for illustration. The green discs around T7, F4 and O2 are a drawing convention for emphasis, not the model’s region of influence.

How it works

Fig. 02 · Inference

Encode once, denoise N times

Diagram of ZUNA inference, drawn for the 14-channel EPOC X profile. A five-second EEG window of C channels at 256 Hz, 1,280 samples per channel, in which T7, O2 and F4 were not recorded, is cut into tokens of 32 samples, 40 per channel, shape [1, C·40, 32]: 560 tokens for 14 channels. Each token carries an index, tok_idx = {x, y, z, t}: its electrode position in metres and its place in time; the tokens of the missing channels are masked and keep only their positions. The ZunaEncoder Core ML package encodes the tokens once, and its encoding is reused at every step. The ZunaDecoderStep package performs one denoising step on the latent z and returns v; the host applies the Euler update z ← z − dt·v; the new z goes back into the step, N times. The final z is turned back into a [C, 1280] signal: measured channels denoised, missing channels estimated. Traces are synthetic.

01

EEG window

[C, 1280]

C channels × 1,280 samples: five seconds at 256 Hz. Drawn for the 14-channel EPOC X profile, with T7, O2 and F4 not recorded.

Tokenizeevery 32 samples

02

Tokens

[1, C·40, 32]

Forty tokens of 32 samples per channel; 560 for 14 channels. Each carries tok_idx = {x, y, z, t}. The rows of T7, O2 and F4 are masked: position only.

AF3 · token 12 of 40

values
32 samples, 1.375–1.500 s
x, y, z · position
AF3: −0.034, 0.077, 0.021 m
t
12 of 40 in time

Tokens + tok_idx

03

Encode once, denoise N times

The encoder reads the tokens once. The decoder then denoises a latent z, one step per call. N is the host’s choice.

Core MLZunaEncoderruns once per window
encodingreused each step
Core MLZunaDecoderStepone denoising step
v
Hostz ← z − dt·vEuler update
zlatent, refined each step
× Nsteps

Back to samplesz after N steps

04

Signal

[C, 1280]

z after N steps, back in samples: measured channels denoised; T7, O2 and F4 estimated from their positions.

measured, denoisedestimated

Electrode names and positions are the real EPOC X layout (MNE standard_1005). Traces are synthetic, drawn to show the task. Throughput depends strongly on N: fewer steps are faster and coarser.

Each channel’s five-second window is cut into 40 coarse time tokens of 32 samples. A token’s index carries its electrode position and time, {x, y, z, t}, which is why coordinates are part of the input contract. The encoder runs once; the decoder then denoises a latent over a fixed number of diffusion steps before the tokens are turned back into signal.

Why fp32 only

The original ZUNA runs in fp16: its 14-, 16-, 32- and 64-channel fp16 profiles pass their parity gates. ZUNA1.1 does not. The base model was trained in bf16, and its decoder activations exceed the fp16 range, so no fp16 profile passes parity. Every ZUNA1.1 profile ships in fp32; the 14-channel profile is the default.

A proposed fix for Core ML itself

The port surfaced a bug in coremltools. Its rms_norm translation rescales the input by its maximum before squaring, to protect fp16 on the Neural Engine, but adds epsilon after the rescale. Algebraically the epsilon is inflated by max(|x|)². On spiky activations, which are common in transformer residual streams, that changes outputs by whole percents rather than rounding error, even at fp32 on the CPU.

It was reported as apple/coremltools#2821, with a proposed fix in #2822: rescale epsilon by 1/m², clamp the scale so all-zero rows no longer divide 0 by 0, and add regression tests for both.

Fig. 03 · The bug, in one line

Epsilon, inflated by the rescale

What the conversion computed

rms = √( mean((x / m)²) + ε ) · m = √( mean(x²) + ε · m² )

After the fix

m ← max(m, 1),  ε ← ε / m² ⇒ √( mean(x²) + ε )

m = max |x|. When one activation is much larger than the rest, m² is large and the added term stops being negligible.

Source: the proposed fix in apple/coremltools#2822, commit “Fix rms_norm eps inflation from max-rescale; guard zero input”.

Input contract

Sampling rate
256 Hz
Window
5 seconds, 1,280 samples
Tokens
32 samples each, 40 per channel
Positions
3D electrode coordinates in meters, part of every token
Normalization
Aligned with upstream inference, data_norm = 10
Default profile
14ch-fp32, EPOC X channel order

Know the boundaries

  • Reconstructed and superresolved channels are estimates. Do not present them as measurements.
  • Reconstruction is not decoding. This model does not infer intent, commands, or language.
  • Research and engineering use only. Not validated for diagnosis, treatment, or clinical decisions.
  • Keep the exact preprocessing: the pretrained weights were optimized for it.

About this page

Summarized from the public model card and its published files. Repository updated 18 Aug 2026; reviewed 26 Sep 2026. The Hugging Face card is the source of truth for licenses and current details.

Upstream: Zyphra / ZUNA1.1