OTIS base — ONNX

OTIS is an open time series encoder: 7.1 M parameters, matching the accuracy of encoders 54× its size across 162 tasks at 10× less memory, 43× less energy and 37× lower latency. This is the released base checkpoint exported to ONNX so it can run client-side in a browser — the demo page runs it on the visitor's own data without uploading anything.

file size contents
otis_encoder.onnx ~22 MB encoder, float32
otis_decoder.onnx ~5 MB decoder, float32
otis_encoder_int8.onnx ~6 MB encoder, dynamic int8
otis_decoder_int8.onnx ~1.4 MB decoder, dynamic int8
otis_meta.json — patch size, domain offsets, variate slots
pos_embed_y.bin 15 KB learned variate embeddings, raw float32 (39 x 96)
pos_embed_x.bin 17 KB fixed sincos position table, raw float32 (1 x 43 x 96)
decoder_pos_embed_x.bin 14 KB the decoder's, raw float32 (1 x 43 x 80)
units_x128_<V>x<T>[_int8].onnx 3-12 MB UniTS backbone per demo shape
units_meta.json — UniTS graph list, token size, prompt count
moment_large_int8.onnx 330 MB MOMENT-large, dynamic V and T, feat + pred + emb
moment_fc_<dataset>_int8.onnx 3-6 MB MOMENT's linear-probing forecasting head per benchmark, applied to emb
moment_meta.json — MOMENT graph entry
moment_released_tokens.bin, moment_<sine|chirp|square>_tokens.bin 37 KB each MOMENT's mask token + reconstruction head as graph inputs: the released pair, and the pair fitted on sines, chirps or squares from 20 to 120 Hz for the Impute row
chronos2_fc336_96_int8.onnx 131 MB Chronos-2, 336 -> 96 median forecast, dynamic V
chronos2_embed_int8.onnx 128 MB Chronos-2 encoder states for the Explore map
zero_shot_meta.json — the zero-shot graph(s) hosted here: split, sizes, int8 error
forecast/<dataset>[_revin]/ ~7 MB each OTIS fine-tuned per forecasting benchmark: int8 graphs, meta, tables
sine_embed.bin, <chirp|square>_embed.bin 384 B each one OTIS variate embedding per Impute source, fitted on clean sines, chirps or squares from 20 to 120 Hz

Signatures

otis_encoder(x, attn_mask, pos_embed_y, pos_embed_x, ids_keep)                  -> latent
otis_decoder(latent, attn_mask, pos_embed_y, decoder_pos_embed_x, ids_restore)  -> pred

pos_embed_y is (B, V, T', 96) vectors, not integer ids: the nn.Embedding lookup is lifted out of the graph so the caller supplies the variate embeddings. A domain seen in pre-training uses the learned rows from pos_embed_y.bin (indexed arange(V) + 1 + domain_offset); an unseen domain gets randomly initialised ones, trunc_normal(std=0.02), as the paper specifies and as models_otis.initialize_weights does it.

pos_embed_x is (1, 1+T', 96) and is lifted out for the same reason. It is a fixed sincos table, requires_grad=False, so baking the checkpoint's 42 positions in would cap a run at 1008 time steps — which the codebase does not do: util/pos_embed.interpolate_pos_embed_x resamples it (linear, align_corners=False) for anything longer, and slices it for anything shorter. Pass the table you want; pos_embed_x.bin is the checkpoint's.

Masking is deliberately outside the graph: the reference random_masking draws from an RNG and selects with a boolean mask, so its output shape is data dependent and cannot be expressed in ONNX. The caller picks the visible patches and passes them as ids_keep, which also lets a mask-ratio slider re-run without re-exporting. Passing ids_keep = arange(N) with attn_mask = 1 reproduces the all-patches-visible path exactly.

Licenses

The OTIS graphs are released under this repository's license (CC BY-NC 4.0). The comparison models keep their own: UniTS (MIT), MOMENT-large (MIT) and Chronos-2 (Apache-2.0) are converted to ONNX without any change to the weights, and are here only so the demo page can run them in the browser; use them under their own terms. TimesFM-3's license (TimesFM Non-Commercial License v1.0) does not allow the weights or derivatives to be distributed, so its graph is not here: the page runs its rows only from a local copy of the graph.

Note on attention

These weights were trained with an inner nn.MultiheadAttention, i.e. with a second projection between qkv and proj. util/transformer.py keeps that layout and folds the two projections into one at inference, which is exact and is why the exported graph is smaller than the checkpoint's nominal parameter count.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support