TSPulseForReconstruction
TSPulseForReconstruction at 8 layers and hidden size 24. One published checkpoint has this shape.
Implementing it
How to read this sheet: method.
No forward was recorded for this shape, so the block is read from the published configuration, the checkpoint's tensor names, and TSPulseForReconstruction in granite-tsfm v0.3.9 — not transcribed from a run.
Generated from granite-timeseries-tspulse-r1.
# Two views of one series in a single grid. The spectrum is an input
# here, not a post-processing step.
# 1. RevIN — and its affine is not the identity (`revin_affine: true`).
std = sqrt(max(variance, 1e-3)) # `minimum_scale: 0.001`, clamped,
# not added: the smallest scale
# is 0.0316, and above the clamp
# the constant does nothing.
# `sqrt(var + 1e-3)` would turn
# 0.1000 into 0.1049 at var = 1e-2.
scaled = (series - mean) / std
scaled = scaled * affine_weight + affine_bias # learned scalars; the inverse
# removes these before
# undoing mean/std
# 2. The FFT is real and its halves are kept separately.
bins = rfft(scaled) # 512 samples -> 257 bins
bins = bins[:-1] # `fft_remove_component: last`
re, im_ = Re(bins), Im(bins)
re /= (max(|re|) + 1e-3) # each half by its own max-abs;
im_ /= (max(|im_|) + 1e-3) # here the guard is added
spec = concat(re, im_) # end to end, not a magnitude
# 3. Two patchers. Time and spectrum do not share an embedding:
# `time_encoding.patcher` and `fft_encoding.patcher` are distinct.
time = patch(scaled, 8) @ time_encoding.patcher.T # 64 x 24
spec = patch(spec, 8) @ fft_encoding.patcher.T # 64 x 24
grid = concat(time, spec, registers) # 138 x 24; 10 registers,
# appended (TTM-R3 prepends)
grid = base_norm(flatten(grid)) # one LayerNorm over 138 * 24
h = encoder_mixers(grid) # 8 layers
h = decoder_mixers(h) # 2 layers
# 4. The forecast head reads the registers only.
y = register_mixers(h[-10:]) # 3 layers
y = layernorm(flatten(y)) # 240
forecast = y @ forecast_mapping.W.T # -> 16 samples
recon = h[:64] @ time_head.W.T # per patch 24 -> 8; 512 samples
forecast = invert_revin(forecast)
Sources, granite-tsfm v0.3.9: TSPulseLearnableMaskRevIN; get_fft, called with epsilon=minimum_scale from the backbone; the two encodings, register tokens and base_norm; the appended registers; the forecast mapping and head slicing.
Time and spectrum have separate trained patchers of the same shape, so reusing one for both still loads and still forecasts.
It does not consume magnitudes. The real and imaginary halves are normalised separately by their own maximum absolute value and laid end to end. A port that patches |rfft(x)| has thrown the phase away and halved the sequence.
The dropped bin is the last one, not DC (fft_remove_component: last). Dropping DC instead shifts every bin by one.
Two numerical guards, one constant, two different operations. RevIN clamps the variance — sqrt(max(var, 1e-3)) — and the spectrum normalisation adds to the maximum — re / (max|re| + 1e-3). Both matter exactly where a series is flat or nearly constant.
TSPulseForReconstruction.forward is stochastic. With mask_ratio: 0.7 the backbone builds a time masker, and this class calls the backbone without passing enable_masking, which defaults to true — so the input is masked at random in eval mode too, and two calls disagree.
Geometry
| layers | 8 |
| hidden size | 24 |
| context window | 512 samples |
| forecast horizon | 16 samples |
| patch length | 8 samples |
| patch stride | 8 samples |
| patches | 128 |
| decoder width | 24 |
| feed-forward expansion | 2 |
| input channels | 1 |
| largest checkpoint | 1.1M |
How this was checked
Status and evidence grade in the assessment (see what the grades mean):
granite-timeseries-tspulse-r1: runs,class— the architecture class is implemented; nothing checkpoint-specific was measured
The implementation meant here and below is an unpublished independent inference implementation by the author.
What stands behind the block above, beyond the published configuration it is read from:
- a checkpoint loader, which is where published tensor names are read
- an independent reference implementation of this architecture in Python, driving the published modelling code — an executable statement of what the model should compute, written against the publication rather than against any one implementation of it
Where an independent implementation and the published configuration disagree, the configuration is what this page reports and the disagreement is what it says.
Checkpoints with this architecture
| model | parameters | context |
|---|---|---|
granite-timeseries-tspulse-r1 | 1.1M | — |