Metadata-Version: 2.5
Name: hskyto-timesfm-mlx
Version: 0.1.2
Summary: A pure-MLX port of Google Research's TimesFM-3 time-series foundation model. Runs natively on Apple Silicon, no PyTorch.
Project-URL: Homepage, https://github.com/Hemeskyo/TimesFM-3-MLX
Project-URL: Repository, https://github.com/Hemeskyo/TimesFM-3-MLX
Author: Serhat (Hemeskyo)
License: MIT
License-File: LICENSE
Keywords: apple-silicon,forecasting,mlx,time-series,timesfm
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Requires-Dist: huggingface-hub
Requires-Dist: mlx
Requires-Dist: numpy
Description-Content-Type: text/markdown

# TimesFM-3 MLX

A pure-[MLX](https://github.com/ml-explore/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](assets/showcase.png)

## 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

```bash
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:

```bash
git clone https://github.com/Hemeskyo/TimesFM-3-MLX && cd TimesFM-3-MLX && pip install -e .
```

## Usage

```python
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:

```python
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`](https://huggingface.co/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):

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

## 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`](https://huggingface.co/google/timesfm-3.0-pytorch) · arXiv:2310.10688.
