VerifiedarXiv:2605.1093825 min
Generative models · Language modeling

ELF: Embedded Language Flows

Generate text by flow matching in a frozen encoder's embedding space, and turn the vectors into tokens only once, at the last step.

ELF trains one transformer to denoise T5 embeddings of a whole 1,024-token passage and, at the final step, to read them out as tokens. Techniques from image diffusion carry over without change, and the 105M-parameter model reaches a GPT-2 Large perplexity of 24 in 32 sampling steps.

Explaining the paperELF: Embedded Language FlowsHu, Qiu, Lu, Zhao, Li, Kim, Andreas, He · MIT · arXiv 2026 · arXiv:2605.10938 ↗

This page builds ELF from the flow-matching update: an x-prediction Euler step in a 2-D toy you can drive, the noise schedule, the single decoding pass, and how self-conditioning supplies the “condition” that classifier-free guidance needs when there are no labels. The results are read next to their entropy, and two places where the official code differs from the paper's pseudocode are flagged.

Discrete and continuous diffusion for text

A diffusion language model (DLM) generates a whole passage at once by starting from noise and refining every position over a number of steps, instead of writing left to right like GPT. Two families exist. Discrete DLMs corrupt the tokens themselves: MDLM replaces tokens with a [MASK] symbol and learns to unmask them, and Duo replaces them with random vocabulary items and learns to put the right ones back. Continuous DLMs map tokens to vectors, add Gaussian noise to the vectors, and learn to remove it, the way image diffusion models such as DDPM remove noise from pixels.

The continuous family includes Diffusion-LM, CDCD and DiffuSeq (2022 to 2023), but most recent progress has come from discrete models, which report the stronger results. The ELF paper attributes part of the gap to how continuous models handle the boundary between vectors and tokens. Most of them add a token-level cross-entropy loss at every denoising step, or round each intermediate state to the nearest token vector during sampling, or both; the latent-diffusion variants avoid that but train a separate decoder network. Each choice ties the continuous trajectory to the vocabulary or adds a component.

ELF keeps the trajectory continuous until the end. A frozen T5 encoder turns the training text into one vector per token; a transformer learns to denoise those vectors with flow matching, the method behind recent image models; and the same transformer, told by a mode token that it is now decoding, turns the final vectors into tokens with one cross-entropy-trained readout. Nothing is discretized at intermediate steps, and no separate decoder exists at inference.

The embedding space: frozen T5 encoder outputs

A training passage from OpenWebText is tokenized with the T5 tokenizer and cut to L=1024L = 1024 tokens (sequences are packed, so a passage can span document boundaries). The token ids go through the encoder of T5-small, a 35M-parameter pretrained bidirectional transformer covered in the T5 explainer, whose output is one 512-dimensional vector per token. The code divides every coordinate by 0.2, its estimate of the standard deviation of the encoder outputs, so the clean data xx is a 1024×5121024 \times 512 array with roughly unit-variance entries.

These vectors are contextual: the vector for “bank” depends on the whole passage, because every encoder layer attends over all 1,024 positions. The encoder is never trained, and for unconditional generation it runs only during training, where it defines the target space. The paper compared five choices of space (Figure 5a). Pretrained contextual T5 outputs gave the best trade-off between quality and diversity, a T5-style encoder trained from scratch on OpenWebText came close behind, and the non-contextual options (T5's token embedding table, a frozen random Gaussian table, a table learned jointly with the denoiser) were worse, with the learned table worst.

How ELF trains the denoiser: flow matching with x-prediction

Flow matching defines a path from noise to data. Draw a clean array xx, a Gaussian noise array ϵ\epsilon of the same shape, and a time t∈[0,1]t \in [0, 1], and form the straight-line mixture

zt=t x+(1−t) ϵ,v=dztdt=x−ϵz_t = t\,x + (1 - t)\,\epsilon, \qquad v = \frac{dz_t}{dt} = x - \epsilon

At t=0t = 0 the array is pure noise and at t=1t = 1 it is the data. The velocity vv is constant along each straight path. A network that predicts, at every point ztz_t, the expected velocity over all noise-data pairs whose paths pass through it defines an ordinary differential equation (ODE), and integrating it from fresh noise at t=0t = 0 to t=1t = 1 produces new samples. ELF's code draws ϵ\epsilon with standard deviation 2 instead of 1; the paper mentions this as a noise scale of 2 in its appendix. All numbers on this page use the code's scale.

Standard flow matching trains the network to output vv directly. ELF follows JiT (Li and He, 2025) and has the network output a guess of the clean data, xθ(zt,t)x_\theta(z_t, t), then converts it to a velocity. Solving zt=tx+(1−t)ϵz_t = t x + (1-t)\epsilon for ϵ\epsilon and substituting gives v=(x−zt)/(1−t)v = (x - z_t)/(1 - t), so the predicted velocity is vθ=(xθ−zt)/(1−t)v_\theta = (x_\theta - z_t)/(1 - t). The loss compares velocities:

LMSE=Et,x,ϵ ∥vθ(zt,t)−v∥2=Et,x,ϵ 1(1−t)2 ∥xθ(zt,t)−x∥2\mathcal{L}_{\text{MSE}} = \mathbb{E}_{t,x,\epsilon}\,\|v_\theta(z_t,t) - v\|^2 = \mathbb{E}_{t,x,\epsilon}\,\frac{1}{(1-t)^2}\,\|x_\theta(z_t,t) - x\|^2LMSE=Et,x,ϵ ∥vθ(zt,t)−v∥2=Et,x,ϵ 1(1−t)2 ∥xθ(zt,t)−x∥2\begin{aligned} \mathcal{L}_{\text{MSE}} &= \mathbb{E}_{t,x,\epsilon}\,\|v_\theta(z_t,t) - v\|^2 \\ &= \mathbb{E}_{t,x,\epsilon}\,\frac{1}{(1-t)^2}\,\|x_\theta(z_t,t) - x\|^2 \end{aligned}
(1)

The second form follows because ztz_t cancels in vθ−vv_\theta - v, leaving (xθ−x)/(1−t)(x_\theta - x)/(1 - t). The network is an x-predictor trained with a weighted x-loss whose weight grows near the data end. The code clips 1−t1 - t at 0.05, which caps the weight at 400.

Take one training passage at the median time the schedule draws, t=0.18t = 0.18. Each coordinate of ztz_t is 0.18 times a unit-scale clean value plus noise with standard deviation 0.82×2=1.640.82 \times 2 = 1.64, nine times larger. The network sees this 1024×5121024 \times 512 array, outputs a 1024×5121024 \times 512 guess xθx_\theta, and the loss weight is 1/0.822=1.491/0.82^2 = 1.49.

Why predict xx rather than vv? JiT's argument is geometric. Clean data occupies a small, structured subset of the space (for embeddings: the vectors an encoder produces for real text), while noise and velocity fill all 512 dimensions per token. A network that outputs a point near that subset has less to represent than one that must reproduce full-dimensional noise. ELF's Appendix D.1 tests this with T5-small, T5-base and T5-large encoders (512, 768 and 1,024 dimensions): x-prediction stays usable in all three, v-prediction is competitive at 512 and degrades above it, and noise prediction collapses at every size. The second reason is specific to ELF and comes back in the decoding section: at t=1t = 1 the network must output clean embeddings for the token readout, and an x-predictor already does.

Following JiT, the network also squeezes its input through a bottleneck: a linear map from 512 to 128 dimensions per token, then up to the 768-wide hidden size. Of the bottlenecks the authors tried (32, 128, 512), 128 gave the best balance; 32 reached lower perplexity at lower diversity and 512 the reverse.

Sampling: each Euler step moves part of the way to the guess

Generation starts from z0z_0, a 1024×5121024 \times 512 array of noise, and integrates the ODE with Euler steps on a grid of times 0=t0<t1<⋯<tN=10 = t_0 < t_1 < \dots < t_N = 1. One step from tt to t′t' is zt′=zt+(t′−t) vθz_{t'} = z_t + (t' - t)\,v_\theta. Substituting the x-prediction form of vθv_\theta and collecting terms:

zt′=zt+(t′−t) x^−zt1−t=1−t′1−t zt+t′−t1−t x^z_{t'} = z_t + (t' - t)\,\frac{\hat{x} - z_t}{1 - t} = \frac{1 - t'}{1 - t}\,z_t + \frac{t' - t}{1 - t}\,\hat{x}zt′=zt+(t′−t) x^−zt1−t=1−t′1−t zt+t′−t1−t x^\begin{aligned} z_{t'} &= z_t + (t' - t)\,\frac{\hat{x} - z_t}{1 - t} \\ &= \frac{1 - t'}{1 - t}\,z_t + \frac{t' - t}{1 - t}\,\hat{x} \end{aligned}

where x^=xθ(zt,t)\hat{x} = x_\theta(z_t, t) is the network's current guess. The new point lies on the straight segment from ztz_t to the guess, a fraction (t′−t)/(1−t)(t' - t)/(1 - t) of the way along. With four uniform steps, the step from 0.25 to 0.5 goes 0.25/0.75=1/30.25/0.75 = 1/3 of the way to the guess, and the last step, from 0.75 to 1, goes all the way: z1=x^z_1 = \hat{x}. The final Euler step of any grid that ends at 1 returns the network's last guess.

At t=0t = 0 the input contains no information about the data, so the best possible guess is the average of all clean data, the same point for every starting noise. A one-step sampler therefore sends every sample to that average, which is not itself a plausible embedding. More steps let the guess sharpen as the signal in ztz_t grows. Figure 1 runs this with an exact denoiser in two dimensions, so every error on screen comes from the step size.

Figure 1 · an x-prediction Euler sampler in two dimensions

step 1: t = 0.000 → 0.125; z' sits 0.125 of the way from z to the guess
samples ending inside a cluster: 40 of 44

Six small amber clusters stand in for clean embeddings; the cross marks their mean. Gray dots are 44 noise draws (standard deviation 2, as in ELF's code) and teal lines are their Euler paths on a uniform grid, using the exact posterior-mean denoiser. The highlighted path shows one step: from zz along the dashed segment toward the guess x^\hat{x}. Drag the step slider through the run, set N to 1 to see every sample land on the cross, and click any path to highlight it.

At N = 1 all 44 samples end on the cross. At N = 2 the second step starts at t=0.5t = 0.5, where the noise standard deviation is 1.0 and the gap between neighbouring clusters, scaled by 0.5, is only 0.68 to 0.76, so each guess is still a blend of several clusters and none of the 44 samples ends inside one. With 4 steps 19 do, with 8 steps 40, with 16 steps 43. Step through a run and the guesses of the early steps all sit near the cross, then spread toward individual clusters as tt grows.

ELF does not space its steps uniformly. It draws training times from a logit-normal distribution, t=σ(u)t = \sigma(u) with u∼N(−1.5,0.82)u \sim \mathcal{N}(-1.5, 0.8^2) and σ\sigma the sigmoid, which puts the median at 0.18; at sampling time the code draws N−1N - 1 times from the same distribution, sorts them, and adds 0 and 1. Figure 2 plots both training distributions and the resulting grid.

Figure 2 · where training draws and sampling steps fall

grid: 23 of 31 interior points below t = 0.3; the last step covers 46% of the time axis
denoiser draws with t < 2/3 (noise std above signal): 99.7% · median t 0.18 · decoder median p 0.69, noise ×5

Teal: density of the denoiser's training times; violet: the decoder's per-token corruption level pp (next section). Lines give the signal coefficient tt and the noise standard deviation 2(1−t)2(1-t), which cross at t=2/3t = 2/3. The strip below shows the sampling grid; its shaded part is the final step. Change N, switch to the uniform grid, or redraw the random logit-normal grid.

Under this schedule 99.7% of training draws have t<2/3t < 2/3, where the noise standard deviation exceeds the signal coefficient, and 3% have t>0.5t > 0.5. The sampling grid follows the same shape: with N = 32 the largest interior time averages 0.53 and ranges from about 0.35 to 0.75 between draws, so most steps are spent below t=0.3t = 0.3 and the final step, which returns the guess, spans roughly the second half of the time axis. The network commits to its answer from a state that is still about two parts noise to one part signal per coordinate. A likely reason this works, which the paper does not test directly, is that each guess pools evidence over 1,024 positions of 512 coordinates each, against the two coordinates of Figure 1. The paper's Appendix D.6 reports that this grid gives lower perplexity than a uniform one at every step count it tried, with the largest gain at few steps.

Decoding with the same network

After the last Euler step, z1z_1 is a 1024×5121024 \times 512 array that should look like T5 encoder output for some passage. ELF needs token ids. A latent diffusion model would train a separate decoder for this; ELF reuses the denoiser. The final time step is treated as a decoding step: the network is called once more at t=1t = 1 with a mode input set to “decode”, and its output goes through a projection to 32,100 logits per position, one per T5 vocabulary entry. The argmax at each position is the generated token.

Training the decode mode needs inputs. At t=1t = 1 the flow-matching input equals the clean data, so training on it would teach a lookup that never sees an imperfect embedding. ELF corrupts the clean embeddings with a separate schedule, per token:

z~=p x+(1−p) 5ϵ′,p=σ(u), u∼N(0.8, 0.82)\tilde{z} = p\,x + (1 - p)\,5\epsilon', \qquad p = \sigma(u),\ u \sim \mathcal{N}(0.8,\, 0.8^2)z~=p x+(1−p) 5ϵ′,p=σ(u), u∼N(0.8, 0.82)\begin{gathered} \tilde{z} = p\,x + (1 - p)\,5\epsilon', \\ p = \sigma(u),\ u \sim \mathcal{N}(0.8,\, 0.8^2) \end{gathered}

and trains with a per-token cross-entropy loss against the true tokens ss:

LCE=Ez~[CrossEnt(Wxθ(z~), s)]\mathcal{L}_{\text{CE}} = \mathbb{E}_{\tilde{z}}\left[\text{CrossEnt}\big(W x_\theta(\tilde{z}),\, s\big)\right]
(2)

Every token gets its own pp, so one passage mixes nearly clean tokens with heavily corrupted ones. At the median p=0.69p = 0.69, a token's vector is 0.69 times its clean value plus noise of standard deviation 0.31×5=1.550.31 \times 5 = 1.55; about 16% of tokens get p<0.5p < 0.5. A heavily corrupted token can be read only from its neighbours, which the transformer attends to, so the decode mode learns to use context to clean up embeddings. The paper corrupts the inputs because the embeddings the sampler hands over at t=1t = 1 are never exact.

Eq. (2) writes the readout as a matrix WW applied to the predicted clean embedding. In the released code the logits instead come from the transformer's last hidden state, through a small two-layer head (768 to 512 with a GELU, then 512 to 32,100), in parallel with the layer that outputs xθx_\theta. The shared part is the 12-layer transformer; the Provenance panel records the difference.

Each training step uses one of the two branches: the denoising loss (1) with probability 0.8, the decoding loss (2) with probability 0.2. In the code the choice is one random draw per device per step, so at any step about a fifth of the devices train the decoder while the rest train the denoiser. The paper tested other splits (Appendix D.3); giving the denoiser less than 0.8 hurt, most under the SDE sampler. It also trained the alternative with a separate decoder: first a T5-sized decoder learns to reconstruct tokens from masked and noisy T5 embeddings, then a separate denoiser is trained against the frozen pair. The two reached a similar trade-off, with the shared network reaching lower perplexity at its low-diversity end (Figure 5b) and needing one training stage instead of two.

Shared weights also favour x-prediction: in decode mode the network must output a clean embedding, and in denoise mode an x-predicting network already outputs one, so both losses train the shared weights to output the same kind of quantity (a clean embedding). A v-predicting network would have to output a velocity in one mode and a clean embedding in the other; the paper reports that v-prediction works poorly with shared weights.

Self-conditioning, and guidance without labels

Two more pieces come from earlier diffusion work. Self-conditioning (Chen, Zhang and Hinton, 2023) gives the network its own previous guess as an extra input. During training, half the examples get a zero array in that slot. For the other half, the network first runs once with the zero input, its output x^′\hat{x}' is detached from the gradient, and the network runs again with [zt,x^′][z_t, \hat{x}'] concatenated along the feature axis (1,024 features, projected back to 512 by a linear layer). Only the second pass is trained. At sampling time the previous step's guess fills the slot, so self-conditioning costs no extra passes.

Classifier-free guidance (CFG) trades diversity for quality in conditional image models by extrapolating from an unconditional prediction past a conditional one. In the flow-matching form ELF uses,

vcfg(zt∣c)=ω v(zt∣c)+(1−ω) v(zt∣∅)v_{\text{cfg}}(z_t \mid c) = \omega\, v(z_t \mid c) + (1 - \omega)\, v(z_t \mid \varnothing)

where cc is the condition, ∅\varnothing its absence, and ω\omega the scale. At ω=1\omega = 1 this is the conditional prediction; at ω=3\omega = 3 it is 3v(zt∣c)−2v(zt∣∅)3v(z_t|c) - 2v(z_t|\varnothing), twice the conditional-minus-unconditional difference beyond the conditional prediction. (Ho and Salimans write the scale as w=ω−1w = \omega - 1.) Unconditional text generation has no class label to condition on. ELF uses the self-conditioning input as the condition: the “conditional” prediction sees the previous guess, the “unconditional” one sees zeros. Guidance with ω>1\omega > 1 pushes each step further in the direction that the network's own earlier guess moves it, which the paper finds lowers perplexity and entropy together.

Standard CFG costs two network passes per step. ELF uses training-time guidance instead, following improved MeanFlow (Geng et al., 2025): the guidance scale ω\omega becomes an input of the network, and the network is trained to output the guided velocity directly. The regression target for the self-conditioned examples is

vtarget=x−ϵ+(1−1ω)(vθcfg(zt∣t,c,ω)−vθcfg(zt∣t,∅,ω))v_{\text{target}} = x - \epsilon + \left(1 - \frac{1}{\omega}\right)\big(v^{\text{cfg}}_\theta(z_t \mid t, c, \omega) - v^{\text{cfg}}_\theta(z_t \mid t, \varnothing, \omega)\big)vtarget=x−ϵ+(1−1ω)(vθcfg(zt∣t,c,ω)−vθcfg(zt∣t,∅,ω))\begin{aligned} v_{\text{target}} &= x - \epsilon + \left(1 - \frac{1}{\omega}\right)\big(v^{\text{cfg}}_\theta(z_t \mid t, c, \omega) \\ &\quad - v^{\text{cfg}}_\theta(z_t \mid t, \varnothing, \omega)\big) \end{aligned}
(5)

with the two network terms evaluated with gradients stopped. The examples without self-conditioning keep the plain target x−ϵx - \epsilon, so the network's zero-input prediction stays the unguided v(zt∣∅)v(z_t|\varnothing) at every ω\omega. To see why (5) gives the guided field: regressing onto x−ϵx - \epsilon alone makes the output converge to its average over all training pairs that match the inputs, which is v(zt∣c)v(z_t|c). If the network already outputs the guided field, its two outputs in (5) differ by ω (v(zt∣c)−v(zt∣∅))\omega\,(v(z_t|c) - v(z_t|\varnothing)), so the target averages to v(zt∣c)+(ω−1)(v(zt∣c)−v(zt∣∅))v(z_t|c) + (\omega - 1)(v(z_t|c) - v(z_t|\varnothing)), which is vcfgv_{\text{cfg}}: the guided field is a fixed point of training. At ω=1\omega = 1 the correction term vanishes.

Each training example draws its own ω\omega from [0.5, 5.0], log-uniformly in 1+ω1 + \omega, so the median is 2 and about 21% of examples get ω<1\omega < 1, which moves the prediction toward the unconditional one. At inference the scale is a free input: the system-level runs use ω=3\omega = 3, and changing it needs no retraining and no second pass.

During training, x^′\hat{x}' is computed from ztz_t alone, so it carries no information about xx that ztz_t lacks, and a network that computed the exact posterior would give v(zt∣c)=v(zt∣∅)v(z_t|c) = v(z_t|\varnothing); the guidance term would then be zero. For a real network the one-pass and two-pass predictions differ, and guidance scales up that difference. The paper does not analyse what the difference represents; its evidence that the scale helps is the measured trade-off in Figure 3 below.

The time, the guidance scale and the mode reach the network as extra tokens. Four learned time tokens carry the embedding of tt, four carry the embedding of ω\omega, and four mode tokens are switched on only in decode mode, so ELF-B's transformer reads a sequence of 12+1024=103612 + 1024 = 1036 vectors of width 768 and drops the first 12 at the output. This replaces the adaLN-Zero conditioning layers of the DiT architecture it otherwise follows, and cuts ELF-B from 148M to 105M parameters with a small improvement in samples (Appendix D.4). The blocks use SwiGLU, RMSNorm, rotary position embeddings and query-key normalization.

The SDE-style sampler

The deterministic sampler follows one trajectory per starting noise, and an error made early is carried to the end. Stochastic samplers for diffusion models re-inject a little noise at each step so later steps can correct it. ELF adds a simple version. At each step from tt to t′t', with a scale γ\gamma, the code first steps backward toward noise:

α=1−γ (t′−t),tb=α t,zb=α zt+(1−α) 2e\alpha = 1 - \gamma\,(t' - t), \qquad t_b = \alpha\,t, \qquad z_b = \alpha\,z_t + (1 - \alpha)\,2eα=1−γ (t′−t),tb=α t,zb=α zt+(1−α) 2e\begin{gathered} \alpha = 1 - \gamma\,(t' - t), \qquad t_b = \alpha\,t, \\ z_b = \alpha\,z_t + (1 - \alpha)\,2e \end{gathered}

with fresh noise ee, and then takes an ordinary Euler step from zbz_b at tbt_b to t′t' using the guess xθ(zb,tb)x_\theta(z_b, t_b). With γ=0\gamma = 0 it is the ODE sampler. Take a 32-step run at t=0.10t = 0.10, t′=0.12t' = 0.12, γ=1.5\gamma = 1.5: then α=0.97\alpha = 0.97 and tb=0.097t_b = 0.097, so the state gives up 3% of itself to fresh noise and the step covers 0.023 of time instead of 0.02. The signal coefficient of zbz_b is exactly αt=tb\alpha t = t_b, but its noise is a little below what the path formula expects at tbt_b: for a state with the exact noise level 2(1−0.10)=1.802(1 - 0.10) = 1.80, the backed-off state has standard deviation (0.97⋅1.80)2+(0.03⋅2)2=1.747\sqrt{(0.97 \cdot 1.80)^2 + (0.03 \cdot 2)^2} = 1.747 where 2(1−0.097)=1.8062(1 - 0.097) = 1.806 would be consistent. The paper calls the sampler “SDE-inspired” for this reason. The code always takes the last step, the one that lands on the guess, as a plain Euler step.

Algorithm 6 in the paper writes a different update: it evaluates the network at the noised state but then moves the original, un-noised ztz_t. That version never puts the fresh noise into the trajectory. The Provenance panel records the mismatch; this page follows the code. In the experiments, the SDE sampler reaches much lower perplexity than the ODE sampler at few steps (Figure 5c) at slightly lower entropy, and γ\gamma trades the two against each other (Appendix D.6). The paper gives error correction as its hypothesis for the gain.

The training step and the sampler in code

The listing below is one ELF-B training example, condensed from the released JAX code with this page's names; every constant is the OpenWebText configuration. Only the last network call of each branch receives a gradient. The self-conditioning pass and the two passes that build the guided target run with gradients stopped, so in this condensed form a self-conditioned denoising example costs three forward passes and one backward pass.

# One ELF-B training example (unconditional, OpenWebText).
# s: 1024 token ids. Shapes per example; the batch adds a leading 512.
x = t5_small_encoder(s) / 0.2          # (1024, 512), frozen, never trained
if rand() < 0.8:                       # denoising branch, 80% of steps
    t = sigmoid(0.8 * randn() - 1.5)   # one t per sequence, median 0.18
    e = 2.0 * randn_like(x)            # noise scale 2
    z = t * x + (1 - t) * e
    v = (x - z) / max(1 - t, 0.05)     # target velocity, = x - e
    w = sample_cfg_scale(0.5, 5.0)     # guidance scale fed as an input
    x0 = stopgrad(net(cat(z, 0), t, w, mode="denoise"))   # no self-cond
    if rand() < 0.5:                   # self-conditioned example
        xs = stopgrad(net(cat(z, x0), t, w, mode="denoise"))
        v_c = (xs - z) / max(1 - t, 0.05)
        v_u = (x0 - z) / max(1 - t, 0.05)
        target = v + (1 - 1 / w) * (v_c - v_u)       # Eq. (5)
        x_pred = net(cat(z, x0), t, w, mode="denoise")
    else:
        target = v
        x_pred = net(cat(z, 0), t, w, mode="denoise")
    loss = mean(((x_pred - z) / max(1 - t, 0.05) - target) ** 2)
else:                                  # decoding branch, 20% of steps
    p = sigmoid(0.8 * randn(1024, 1) + 0.8)    # one p per token
    zt = p * x + (1 - p) * 5.0 * randn_like(x)
    logits = net(cat(zt, 0), t=1, w, mode="decode")  # (1024, 32100)
    loss = cross_entropy(logits, s)
loss.backward()                        # every branch updates the same net

Sampling for the headline 32-step result, with γ=1.5\gamma = 1.5 and ω=3\omega = 3, is 32 denoising passes and one decoding pass:

# Sampling (generation_utils.py / sampling_utils.py), N = 32, SDE.
ts = [0] + sorted(sigmoid(0.8 * randn(N - 1) - 1.5)) + [1]
z = 2.0 * randn(1024, 512)
x_prev = zeros(1024, 512)              # self-conditioning input
for t, t2 in pairs(ts[:-1]):           # first N - 1 intervals
    a = clip(1 - gamma * (t2 - t), 0, 1)      # gamma = 1.5 at 32 steps
    tb = a * t                                # step back toward noise
    zb = a * z + (1 - a) * 2.0 * randn_like(z)
    x_prev = net(cat(zb, x_prev), tb, w=3, mode="denoise")
    z = zb + (t2 - tb) * (x_prev - zb) / (1 - tb)
t = ts[-2]                             # last interval: plain Euler to t = 1
x_prev = net(cat(z, x_prev), t, w=3, mode="denoise")
z = z + (1 - t) * (x_prev - z) / (1 - t)      # = x_prev
tokens = argmax(net(cat(z, 0), t=1, w=3, mode="decode"))

ELF-B trains with the Muon optimizer at a learning rate of 0.002 (AdamW, the subject of the decoupled weight decay explainer, did worse in Appendix D.5 at its own tuned rate of 1e-4), batch size 512, no weight decay, a constant learning rate after half an epoch of warmup, and an exponential moving average of the weights with decay 0.9999 that is used for sampling. Five epochs of OpenWebText are about 95K steps and took 1.5 hours per epoch on 64 TPU v5p chips.

What the experiments show

Unconditional results follow the protocol of MDLM and Duo: generate 1,000 samples of 1,024 tokens, score each with GPT-2 Large, and report the generative perplexity (Gen. PPL, the exponentiated average negative log-likelihood GPT-2 Large assigns; lower means more predictable to GPT-2) together with the average unigram entropy of each sample (higher means a more varied mix of tokens). The two have to be read together. Repetitive text scores a low Gen. PPL, so a sampler can lower its perplexity by lowering its entropy; the paper's appendix figures shade entropy below 5.0 as degenerate, and the Duo paper puts samples from an autoregressive model at about 5.6.

The guidance scale ω\omega moves a model along that trade-off. Figure 3 plots the paper's Table 10: three model sizes, both samplers, 64 steps, ω\omega from 0.5 to 4.

Figure 3 · quality against diversity as guidance increases

Gen. PPL @ entropy at ω = 3
B SDE 19.72 @ 5.10 · ODE 26.62 @ 5.15

M SDE 21.69 @ 5.18 · ODE 28.80 @ 5.24

L SDE 23.31 @ 5.28 · ODE 26.57 @ 5.29

Each point is 1,000 samples (paper Table 10, 64 steps). Teal ELF-B, amber ELF-M, violet ELF-L; filled points and solid lines are the SDE sampler, hollow points and dashed lines the ODE sampler. Down is more fluent to GPT-2, right is more varied. Slide the scale or click a point; the readout lists all six values at that scale.

Raising ω\omega from 0.5 to 3 moves every curve down and to the left: ELF-B's SDE samples go from 36.77 at entropy 5.28 to 19.72 at 5.10. Above 3 the B and M models reverse (ELF-B at ω=3.5\omega = 3.5 jumps back to 37.56), and only ELF-L keeps improving, to 21.37 at ω=4\omega = 4. Larger models sit to the right at a given perplexity: at ω=3\omega = 3 ELF-L's SDE samples have entropy 5.28 against ELF-B's 5.10, with Gen. PPL 23.31 against 19.72. At the same ω\omega, SDE samples have lower perplexity and lower entropy than ODE samples, and at matched entropy the SDE curve is lower: ELF-B's SDE samples at entropy 5.14 score 22.53, its ODE samples at 5.15 score 26.62. In the ODE rows at ω=0.5\omega = 0.5, where entropy reaches 5.51 to 5.52, the perplexities are 68 to 104.

The system-level comparison uses ELF-B with the SDE sampler and ω=3\omega = 3. Averaged over six evaluation seeds it reaches 67.32 at 8 steps, 33.66 at 16 and 24.08 at 32 (standard error 0.16), at entropy 5.14 to 5.16. The baselines (MDLM, Duo, and the concurrent continuous models FLM and LangFlow, all around 170M parameters) are plotted in the paper's Figure 7a without a table. For reference, the Duo paper reports undistilled 32-step values of 96.19 for Duo at entropy 5.57 and 196.79 for MDLM at 5.75. ELF-B's lowest perplexity comes with an entropy about 0.4 below those, and its own 64-step ODE samples at entropy 5.51 score 104.29, so at matched diversity the margin over Duo is not established by the reported numbers.

Distilled baselines are a second comparison. MDLM+SDTT, Duo+DCD and FMLM add a distillation stage to sample in fewer steps. The authors distill ELF too (Appendix B): five rounds of progressive distillation (Salimans and Ho, 2022) take a 64-step teacher to a 16-step student, then 8, 4, 2 and 1. In each round the student regresses onto

x~=zt+1−tr−t (zr−zt)\tilde{x} = z_t + \frac{1 - t}{r - t}\,(z_r - z_t)
(3)

where zrz_r is where the teacher's substeps take ztz_t by time rr. By the Euler formula above, x~\tilde{x} is the guess that makes one student step from tt land exactly at zrz_r. Figure 4 has the few-step numbers.

Figure 4 · generative perplexity at 1 to 32 steps

Gen. PPL (entropy) at 8 steps
MDLM+SDTT 112.66 (5.41)

Duo+DCD 118.21 (5.41)

FMLM 86.50 (5.36)

ELF+PD 23.18 (5.07)

ELF-B, no distillation 67.32 (5.14)

Paper Tables 4 and 9, OpenWebText. The dashed amber line is ELF-B with no distillation (reported at 8, 16 and 32 steps); teal is ELF+PD after five distillation rounds. Pick a step count with the slider or by clicking the plot; the readout lists each method's Gen. PPL with its entropy in parentheses.

At 8 steps, undistilled ELF-B (67.32) is below MDLM+SDTT (112.66), Duo+DCD (118.21) and FMLM (86.50). ELF+PD is lowest at every budget: 136.10 at one step against FMLM's 168.30, and 23.18 at 8 steps. The entropy column moves the other way. ELF+PD's entropy falls from 5.26 at one step to 5.04 at 32, just above the 5.0 degenerate line, while the discrete baselines stay between 5.34 and 5.43 from 2 steps up.

The baselines train for 1M steps of 512 sequences of 1,024 tokens, 524.3B tokens, plus distillation. ELF-B trains for 5 epochs of OpenWebText: 45.2B tokens by the paper's Table 8, or 49.8B by its step count, about a tenth either way. The authors report that training longer did not improve ELF further.

For conditional generation the source text is encoded by T5, prepended to the noisy target as clean embeddings that are never noised, and dropped (zeroed) for 10% of training examples so that standard CFG on the source is available. With a 64-step ODE sampler, self-conditioning scale 1 and source-guidance scale 2, ELF-B scores 26.4 BLEU on WMT14 German-to-English, against 25.2 for a 99M autoregressive model and 24.8 for E2D2 (both numbers from the E2D2 paper) and 24.9 for CDCD. On XSum summarization it scores ROUGE-1/2/L of 36.0/12.2/27.8 against 33.4/11.6/25.8 for MDLM and 30.5/10.2/24.4 for the autoregressive model, all baselines reproduced by the authors. The generated outputs are 64 tokens, and the autoregressive baselines are small (99M); neither result is a comparison with a production translation or summarization system.

Limitations

The unconditional comparisons are in Gen. PPL and unigram entropy only, and ELF's best numbers sit at lower entropy than the baselines'. The paper has no held-out likelihood, because computing a flow model's likelihood takes an integral of the velocity field's divergence along each trajectory, so it cannot be compared with autoregressive models on perplexity of real text. The largest model is 652M parameters, and the scaling result (Figure 6) covers three sizes.

Generation length is fixed by the array shape: 1,024 positions for OpenWebText, 64 for the conditional tasks. The method depends on a pretrained encoder for its embedding space, and the authors' ablations show noticeably worse results without a contextual one. Few-step generation still needs distillation: Appendix B reports that ELF+PD below 8 steps loses quality, with Gen. PPL rising from 23.18 at 8 steps to 34.33 at 4 and 136.10 at 1.

Provenance Verified against primary literatureHow we verify
Lipman et al. (2023); Liu, Gong & Liu (2023)Flow matching and rectified flow: the straight path z_t = t x + (1 - t) eps and the velocity x - eps. ELF uses the rectified-flow convention, t = 0 noise and t = 1 data.
Li & He (2025), "Back to Basics" (JiT)Source of x-prediction with a velocity loss: v_theta = (x_theta - z_t)/(1 - t) and L = E ||v_theta - v||^2 = E (1 - t)^-2 ||x_theta - x||^2, the same form as ELF Eq. (1). JiT motivates it by the manifold assumption (clean data low-dimensional, noise and velocity not) and reports that a bottleneck projection can help, which ELF adopts (512 -> 128).
Chen, Zhang & Hinton (2023), Analog BitsSelf-conditioning: with probability 50% set the extra input to 0, otherwise run a first pass, stop its gradient, and feed its x estimate back in. At sampling time the previous step's estimate is reused, so it adds no passes.
Ho & Salimans (2021); Geng et al. (2025), improved MeanFlow, Eq. 13 and appendixGuidance written as omega v(c) + (1 - omega) v(empty), so omega = 1 is unguided; Ho & Salimans' w equals omega - 1. The training-time target v = (e - x) + (1 - 1/omega)(u_cfg(c) - u_cfg(empty)) and the idea of feeding omega to the network as a condition are iMF's; ELF writes the same target for its sign convention v = x - eps as Eq. (5).
ELF code, src/train_step.pyNoise is N(0, 2^2) (denoiser_noise_scale = 2.0, add_noise in sampling_utils.py line 15); embeddings are divided by latent_std = 0.2; 1 - t is clipped at t_eps = 0.05 (line 102); the decoder branch draws one p per token and scales its noise by 5 (lines 93-99); the branch is chosen with one Bernoulli(0.2) draw per device per step (line 89), not by a per-example mask; the guided target is stop-gradient and applied only to self-conditioned examples (lines 164-172).
ELF code, src/utils/sampling_utils.py and generation_utils.pyThe guidance scale is sampled log-uniformly on 1 + omega over [0.5, 5] (sample_cfg_scale), so about 21% of examples get omega < 1 and the median is 2; the paper calls it a power distribution. The logit-normal sampling grid is N - 1 sorted random draws plus 0 and 1, redrawn per run. The last interval always uses a plain Euler step, then one decode pass: N + 1 network evaluations for N steps.
Salimans & Ho (2022), progressive distillationELF+PD Eq. (3), x~ = z_t + (1 - t)/(r - t)(z_r - z_t), is the x prediction for which a single Euler step from t lands where K teacher steps landed at r. Five rounds take a 64-step teacher to 16, 8, 4, 2 and 1 student steps.
Sahoo et al. (2025), Duo, Table 5 and Sec. 5Undistilled 32-step Gen. PPL: Duo 96.19 at entropy 5.57, MDLM 196.79 at 5.75; autoregressive samples sit near entropy 5.6. ELF-B's 24.08 is at 5.15, and ELF Table 10 puts ELF-B at 104.29 when its entropy is raised to 5.51 (64-step ODE, omega = 0.5).
ELF Table 8 and Sec. 4Table 8 counts 5 x 9.04B = 45.2B training tokens, 11.6x fewer than the 524.3B baselines. Sec. 4 reports about 95K steps at batch 512 and length 1024, which is 49.8B tokens (10.5x). 9.04B is the usual GPT-2-tokenizer count for OpenWebText; ELF uses the T5 tokenizer. Both give the paper's "10x".
ELF Appendix D.4The in-context versus adaLN-Zero comparison is cited as Fig. 15; it is Fig. 14 (Fig. 15 is the optimizer comparison).
correctionTwo places where the official code (github.com/lillian039/ELF) and the paper's pseudocode compute different things. (1) The SDE step. Algorithm 6 evaluates the network on the perturbed state z_back at t_back but then updates the ORIGINAL state, z <- z + dt (x_hat - z)/(1 - t), so no noise ever enters the trajectory. The code (sampling_utils.py _sde_step, lines 241-254) moves from the perturbed state: z <- z_back + (t_next - t_back)(x_hat - z_back)/(1 - t_back), with the re-injected noise scaled by 2 like the training noise, and generation_utils.py runs the final interval as a plain Euler step. This page teaches the code. (2) The decoding head. Eq. (2) applies a learnable matrix W to the predicted clean embedding x_theta. In the code (model.py lines 141-156) the logits come from the transformer's last hidden state through a two-layer head, GELU(h W1 + b1) W2 + b2 with 768 -> 512 -> 32,100, in parallel with the layer that outputs x_theta; what the two objectives share is the transformer, not the output projection.

Questions you might still have

?

Is ELF a latent diffusion model?
Partly. Like latent diffusion it runs the generative process in the output space of a pretrained encoder, here the frozen T5-small encoder. Unlike it, there is no compression (each of the 1,024 tokens keeps its own 512-dimensional vector) and no separate decoder: the denoising network itself is trained, under a different mode token, to turn clean embeddings into tokens. The paper's survey table lists eight latent text diffusion models, from LD4LG to Cola DLM, and every one of them trains a separate latent-to-text decoder.

?

Why not round each intermediate state to the nearest token embedding, as Diffusion-LM does?
Rounding at every step forces the trajectory through token-shaped states and needs a per-step cross-entropy loss to keep the embeddings separable. ELF's embeddings are contextual, so there is no fixed table of token vectors to round to, and the paper's design keeps every intermediate state continuous so that image-diffusion tools (Euler and SDE samplers, guidance, distillation) apply unchanged. The paper does not run an ablation that adds per-step rounding to ELF, so the size of this effect is not measured.

?

Does ELF need the T5 encoder when it generates?
Not for unconditional generation: sampling starts from Gaussian noise and the network's decode mode produces tokens. For translation and summarization it does, because the source sentence is encoded by T5 and prepended as clean embeddings. That is why Table 1 lists ELF as 105M (+35M).

?

How many network passes does one 32-step sample cost?
Thirty-three for unconditional generation: 32 denoising passes and one decoding pass. Self-conditioning reuses the previous step's prediction and the self-conditioning guidance scale is an input token, so neither adds a pass. Guidance on an input condition (translation, summarization) is applied the standard way, with a second pass that has the condition zeroed, so a 64-step conditional sample costs 128 denoising passes plus the decode.

?

Does a lower generative perplexity mean better text?
Only at matched diversity. Gen. PPL is the perplexity GPT-2 Large assigns to the samples, and repetitive or bland text scores low, which is why every result is reported with unigram entropy. ELF-B reaches 24 at entropy 5.15, while the undistilled discrete baselines report their numbers near 5.55 to 5.75 and autoregressive samples sit near 5.6. When ELF-B is pushed to entropy 5.51 its Gen. PPL is 104, so part of the headline gap comes from operating at lower entropy.

?

Can ELF report a perplexity on held-out text, like a GPT model?
Not in this paper. A flow model's likelihood has to be computed by integrating the divergence of the velocity field along the trajectory, and the authors note that accurate likelihoods for flow models can require additional likelihood-specific training. They report generation metrics only, as MDLM and Duo also do in the comparison.

?

Why does the network predict the clean embedding instead of the velocity?
Two reasons, one per objective. Clean embeddings lie on a much lower-dimensional set than noise, so a network of fixed width finds them easier to output; in the paper's Appendix D.1, x-prediction stays usable at 512, 768 and 1,024 dimensions while v-prediction degrades above 512 and noise prediction fails at all three. And the decoding mode needs a clean embedding at t = 1, which is exactly what an x-predicting network already outputs, so the same weights serve both losses. With v-prediction under weight sharing, the paper reports that training works poorly.

?

Could ELF learn its own embeddings instead of using T5?
It can, and that variant performs worst in the paper's Figure 5a. A learnable embedding table trained jointly with the denoiser is a moving target for the regression loss; the authors normalize the table every step to keep training stable. Frozen random Gaussian embeddings do better than learned ones, frozen T5 token embeddings better still, and contextual T5 encoder outputs best. A T5-style encoder trained from scratch on OpenWebText comes close to the pretrained one.

Footnotes & further reading

  1. The paper: Hu, Qiu, Lu, Zhao, Li, Kim, Andreas, He, ELF: Embedded Language Flows (2026), and the official JAX code at github.com/lillian039/ELF.
  2. x-prediction and the bottleneck: Li, He, Back to Basics: Let Denoising Generative Models Denoise (2025).
  3. Flow matching: Lipman et al., Flow Matching for Generative Modeling (2023), covered in the flow matching explainer; Liu, Gong, Liu, Flow Straight and Fast: Rectified Flow (2023).
  4. Self-conditioning: Chen, Zhang, Hinton, Analog Bits: Generating Discrete Data using Diffusion Models with Self-Conditioning (2023).
  5. Guidance: Ho, Salimans, Classifier-Free Diffusion Guidance (2021), covered in the classifier-free guidance explainer; training-time guidance with the scale as an input: Geng et al., Improved Mean Flows (2025).
  6. The discrete baselines and the evaluation protocol: Sahoo et al., Simple and Effective Masked Diffusion Language Models (MDLM, 2024); Sahoo et al., The Diffusion Duality (Duo, 2025), Table 5 for the undistilled numbers quoted above.
  7. Earlier continuous text diffusion: Li et al., Diffusion-LM Improves Controllable Text Generation (2022), covered in the Diffusion-LM explainer; latent diffusion, whose encoder-space idea ELF borrows: Rombach et al. (2022), in the latent diffusion explainer.
  8. Distillation: Salimans, Ho, Progressive Distillation for Fast Sampling of Diffusion Models (2022).