Hemeskyo/TimesFM-3-MLX

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

pypi.org/project/hskyto-timesfm-mlx/
ai
apple
apple-silicon
google-research
mlx
tfm3
timesfm
Browse cluster: Speech & Audio on Apple Silicon

README

TimesFM-3 MLX

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.

Results

Features

  • Complete — multivariate targets, past-only and past-future covariates, arbitrary context length.
  • Standalone — depends only on mlx and the .safetensors weights. No PyTorch install.
  • Faithful — ~1e-6 relative error vs the official PyTorch reference on every tested configuration.

Installation

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 .

Usage

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").

Architecture

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.

Validation

Every block is checked against the PyTorch reference (relative error):

Blockrel. 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.

Project structure

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

License

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.

Contributors

Hemeskyo

6 commits

Hemeskyo/TimesFM-3-MLX

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

pypi.org/project/hskyto-timesfm-mlx/
ai
apple
apple-silicon
google-research
mlx
tfm3
timesfm
Browse cluster: Speech & Audio on Apple Silicon

README

TimesFM-3 MLX

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.

Results

Features

  • Complete — multivariate targets, past-only and past-future covariates, arbitrary context length.
  • Standalone — depends only on mlx and the .safetensors weights. No PyTorch install.
  • Faithful — ~1e-6 relative error vs the official PyTorch reference on every tested configuration.

Installation

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 .

Usage

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").

Architecture

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.

Validation

Every block is checked against the PyTorch reference (relative error):

Blockrel. 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.

Project structure

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

License

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.

Contributors

Hemeskyo

6 commits

Languages

Python

100.0%