A pure-MLX port of Google Research's TimesFM-3, a 330M-parameter foundation model for time-series forecasting. Runs natively on Apple Silicon with no PyTorch dependency, and matches the official reference implementation to ~1e-6.
1
stars
6
commits
Python
primary language
Sep 3, 2026
updated
A pure-MLX port of Google Research's TimesFM-3, a 330M-parameter foundation model for time-series forecasting. Runs natively on Apple Silicon with no PyTorch dependency, and matches the official reference implementation to ~1e-6.

mlx and the .safetensors weights. No PyTorch install.pip install hskyto-timesfm-mlx
(mlx and huggingface-hub are pulled in automatically. The model weights are
downloaded and cached on first use.)
Or from source:
git clone https://github.com/Hemeskyo/TimesFM-3-MLX && cd TimesFM-3-MLX && pip install -e .
from timesfm_mlx import load_weights, forecast
weights = load_weights() # downloads from Hugging Face (cached) on first call
out = forecast(series, horizon=64, weights=weights) # (horizon, 9): 9 quantiles per step
median = out[:, 4] # column 4 = median forecast
For multivariate targets or covariates, use decode directly:
from timesfm_mlx import decode
# target: (b, num_target, context) ; optional past_only_/past_future_covariates
out = decode(target, horizon, weights,
past_only_covariates=po, past_future_covariates=pf) # (b, v, horizon, 9)
Weights are fetched from google/timesfm-3.0-pytorch automatically. To use a local file instead: load_weights("path/to/model.safetensors").
Time series are split into patches (32 steps = one token). TimesFM-3 is multivariate: tokens form a 2-D grid (series × time) and each layer attends on both axes.
raw series
→ preprocessing: running-stats RevIN + linear detrending + patching + stitching
→ pre_transformer_resblock (patch 192 → token 1280)
→ 20 × MixingTransformer (seq attention over TIME + var attention over SERIES + FFN)
→ output_head (1280 → 64 horizon steps × 9 quantiles)
→ reverse RevIN / re-trend
→ forecast + quantiles
Each MixingTransformer layer runs seq_attn across time (causal, RoPE) and var_attn across series (no RoPE, non-causal), each wrapped as post_norm(sublayer(pre_norm(h))) + h.
Every block is checked against the PyTorch reference (relative error):
| Block | rel. error |
|---|---|
| rms_norm · linear · per_dim_scale · rope | ~1e-6 |
| attention (seq) · var_attn · feed_forward | ~1e-6 |
| MixingTransformer layer · transformer_stack (20) | ~1e-6 |
| resblock · output_head | ~1e-6 |
| end-to-end decode (any context · past-only · past-future · both) | ~1e-6 |
Run the parity suite: PYTHONPATH=. python parities/parity.py.
timesfm_mlx/
tfm_mlx.py — transformer blocks: rms_norm, linear, per_dim_scale, rope,
attention (seq/var), feed_forward, mixing_layer, transformer_stack,
resblock, output_head
tfm_decode.py — preprocessing + decode + load_weights + forecast
__init__.py — public API
parities/ — parity tests against the PyTorch reference
experiments/ — usage demos
Code: MIT. The TimesFM-3 weights are distributed by Google under the timesfm-non-commercial-license-v1.0 (research / non-commercial only) and are not included here — download them from Hugging Face.
Reference: google/timesfm-3.0-pytorch · arXiv:2310.10688.
6 commits
Python
100.0%
A pure-MLX port of Google Research's TimesFM-3, a 330M-parameter foundation model for time-series forecasting. Runs natively on Apple Silicon with no PyTorch dependency, and matches the official reference implementation to ~1e-6.
1
stars
6
commits
Python
primary language
Sep 3, 2026
updated
A pure-MLX port of Google Research's TimesFM-3, a 330M-parameter foundation model for time-series forecasting. Runs natively on Apple Silicon with no PyTorch dependency, and matches the official reference implementation to ~1e-6.

mlx and the .safetensors weights. No PyTorch install.pip install hskyto-timesfm-mlx
(mlx and huggingface-hub are pulled in automatically. The model weights are
downloaded and cached on first use.)
Or from source:
git clone https://github.com/Hemeskyo/TimesFM-3-MLX && cd TimesFM-3-MLX && pip install -e .
from timesfm_mlx import load_weights, forecast
weights = load_weights() # downloads from Hugging Face (cached) on first call
out = forecast(series, horizon=64, weights=weights) # (horizon, 9): 9 quantiles per step
median = out[:, 4] # column 4 = median forecast
For multivariate targets or covariates, use decode directly:
from timesfm_mlx import decode
# target: (b, num_target, context) ; optional past_only_/past_future_covariates
out = decode(target, horizon, weights,
past_only_covariates=po, past_future_covariates=pf) # (b, v, horizon, 9)
Weights are fetched from google/timesfm-3.0-pytorch automatically. To use a local file instead: load_weights("path/to/model.safetensors").
Time series are split into patches (32 steps = one token). TimesFM-3 is multivariate: tokens form a 2-D grid (series × time) and each layer attends on both axes.
raw series
→ preprocessing: running-stats RevIN + linear detrending + patching + stitching
→ pre_transformer_resblock (patch 192 → token 1280)
→ 20 × MixingTransformer (seq attention over TIME + var attention over SERIES + FFN)
→ output_head (1280 → 64 horizon steps × 9 quantiles)
→ reverse RevIN / re-trend
→ forecast + quantiles
Each MixingTransformer layer runs seq_attn across time (causal, RoPE) and var_attn across series (no RoPE, non-causal), each wrapped as post_norm(sublayer(pre_norm(h))) + h.
Every block is checked against the PyTorch reference (relative error):
| Block | rel. error |
|---|---|
| rms_norm · linear · per_dim_scale · rope | ~1e-6 |
| attention (seq) · var_attn · feed_forward | ~1e-6 |
| MixingTransformer layer · transformer_stack (20) | ~1e-6 |
| resblock · output_head | ~1e-6 |
| end-to-end decode (any context · past-only · past-future · both) | ~1e-6 |
Run the parity suite: PYTHONPATH=. python parities/parity.py.
timesfm_mlx/
tfm_mlx.py — transformer blocks: rms_norm, linear, per_dim_scale, rope,
attention (seq/var), feed_forward, mixing_layer, transformer_stack,
resblock, output_head
tfm_decode.py — preprocessing + decode + load_weights + forecast
__init__.py — public API
parities/ — parity tests against the PyTorch reference
experiments/ — usage demos
Code: MIT. The TimesFM-3 weights are distributed by Google under the timesfm-non-commercial-license-v1.0 (research / non-commercial only) and are not included here — download them from Hugging Face.
Reference: google/timesfm-3.0-pytorch · arXiv:2310.10688.
6 commits
Python
100.0%