MOIRAI: Universal Time Series Forecasting Transformer¶
Overview¶
MOIRAI is a universal time-series forecasting transformer developed by Salesforce Research. It's trained on a massive collection of diverse time-series data and supports various frequencies, context lengths, and prediction horizons out-of-the-box.
Paper¶
Unified Training of Universal Time Series Forecasting Transformers
Key Features¶
- ✅ Universal architecture for diverse datasets
- ✅ Multiple frequency support (hourly, daily, weekly, monthly, etc.)
- ✅ Flexible context and horizon lengths
- ✅ Mixture-of-Experts (MoE) variants
- ✅ Strong zero-shot performance across domains
Model Variants¶
MOIRAI comes in several variants:
| Model | Size | Type | Repository | 
|---|---|---|---|
| MOIRAI Small | ~12M | Standard | Salesforce/moirai-1.0-R-small | 
| MOIRAI Base | ~91M | Standard | Salesforce/moirai-1.0-R-base | 
| MOIRAI Large | ~311M | Standard | Salesforce/moirai-1.0-R-large | 
| MOIRAI-MoE Small | ~39M | MoE | Salesforce/moirai-moe-1.0-R-small | 
| MOIRAI-MoE Base | ~311M | MoE | Salesforce/moirai-moe-1.0-R-base | 
Quick Start¶
from samay.model import MoiraiTSModel
from samay.dataset import MoiraiDataset
# Model configuration
repo = "Salesforce/moirai-1.0-R-small"
config = {
    "context_len": 128,
    "horizon_len": 64,
    "model_type": "moirai",
    "model_size": "small",
}
# Load model
moirai_model = MoiraiTSModel(repo=repo, config=config)
# Load dataset
train_dataset = MoiraiDataset(
    name="ett",
    mode="train",
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    context_len=config['context_len'],
    horizon_len=config['horizon_len']
)
test_dataset = MoiraiDataset(
    name="ett",
    mode="test",
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    context_len=config['context_len'],
    horizon_len=config['horizon_len']
)
# Zero-shot evaluation
eval_results, trues, preds, histories = moirai_model.evaluate(
    test_dataset,
    metrics=["MSE", "MAE", "MASE"]
)
print(f"Results: {eval_results}")
Configuration Parameters¶
Model Configuration¶
| Parameter | Type | Default | Description | 
|---|---|---|---|
| context_len | int | 128 | Length of historical context | 
| horizon_len | int | 64 | Forecast horizon | 
| model_type | str | "moirai" | Model type: "moirai"or"moirai-moe" | 
| model_size | str | "small" | Model size: "small","base","large" | 
| patch_size | int | 16 | Patch size for patching | 
| num_layers | int | 100 | Number of transformer layers | 
Example Configurations¶
Small Model (Fast Inference)¶
repo = "Salesforce/moirai-1.0-R-small"
config = {
    "context_len": 128,
    "horizon_len": 64,
    "model_type": "moirai",
    "model_size": "small",
}
Base Model (Balanced)¶
repo = "Salesforce/moirai-1.0-R-base"
config = {
    "context_len": 256,
    "horizon_len": 96,
    "model_type": "moirai",
    "model_size": "base",
}
Large Model (High Accuracy)¶
repo = "Salesforce/moirai-1.0-R-large"
config = {
    "context_len": 512,
    "horizon_len": 128,
    "model_type": "moirai",
    "model_size": "large",
}
Mixture-of-Experts (MoE)¶
repo = "Salesforce/moirai-moe-1.0-R-small"
config = {
    "context_len": 128,
    "horizon_len": 64,
    "model_type": "moirai-moe",
    "model_size": "small",
}
Dataset¶
MoiraiDataset Parameters¶
| Parameter | Type | Default | Description | 
|---|---|---|---|
| name | str | None | Dataset name | 
| datetime_col | str | "date" | Name of datetime column | 
| path | str | Required | Path to CSV file | 
| mode | str | "train" | "train","val", or"test" | 
| context_len | int | 128 | Length of input context | 
| horizon_len | int | 32 | Forecast horizon | 
| freq | str | None | Time frequency: "h","d","w","m","q","y" | 
| batch_size | int | 16 | Batch size | 
| normalize | bool | True | Whether to normalize data | 
| boundaries | tuple | (0, 0, 0) | Custom split boundaries | 
| start_date | str | None | Start date for subset | 
| end_date | str | None | End date for subset | 
Data Format¶
CSV file with datetime and value columns:
date,HUFL,HULL,MUFL,MULL,LUFL,LULL,OT
2016-07-01 00:00:00,5.827,2.009,1.599,0.462,5.677,2.009,6.082
2016-07-01 01:00:00,5.693,2.076,1.492,0.426,5.485,1.942,5.947
...
Frequency Support¶
MOIRAI natively supports multiple time frequencies:
Hourly Data¶
Daily Data¶
Weekly Data¶
Monthly Data¶
Quarterly Data¶
dataset = MoiraiDataset(
    path="data/quarterly.csv",
    datetime_col="date",
    freq="q",  # Quarterly
    # ...
)
Yearly Data¶
Zero-Shot Forecasting¶
MOIRAI is designed for zero-shot forecasting across different domains:
from samay.model import MoiraiTSModel
from samay.dataset import MoiraiDataset
# Load model
repo = "Salesforce/moirai-1.0-R-small"
config = {
    "context_len": 128,
    "horizon_len": 64,
    "model_type": "moirai",
    "model_size": "small",
}
moirai_model = MoiraiTSModel(repo=repo, config=config)
# Test on different domain (no training!)
test_dataset = MoiraiDataset(
    name="new_domain",
    mode="test",
    path="data/new_domain.csv",
    datetime_col="timestamp",
    freq="h",
    context_len=128,
    horizon_len=64
)
# Zero-shot evaluation
eval_results, trues, preds, histories = moirai_model.evaluate(
    test_dataset,
    metrics=["MSE", "MAE"]
)
Evaluation Metrics¶
MOIRAI supports multiple evaluation metrics:
# Evaluate with multiple metrics
eval_results, trues, preds, histories = moirai_model.evaluate(
    test_dataset,
    metrics=["MSE", "MAE", "MASE", "MAPE", "RMSE"]
)
print("Evaluation Results:")
for metric, value in eval_results.items():
    print(f"  {metric}: {value:.4f}")
Available Metrics¶
- MSE: Mean Squared Error
- MAE: Mean Absolute Error
- MASE: Mean Absolute Scaled Error
- MAPE: Mean Absolute Percentage Error
- RMSE: Root Mean Squared Error
- sMAPE: Symmetric Mean Absolute Percentage Error
Training and Fine-Tuning¶
While MOIRAI is designed for zero-shot forecasting, you can fine-tune it:
# Load model
repo = "Salesforce/moirai-1.0-R-small"
config = {
    "context_len": 128,
    "horizon_len": 64,
    "model_type": "moirai",
    "model_size": "small",
}
moirai_model = MoiraiTSModel(repo=repo, config=config)
# Load training data
train_dataset = MoiraiDataset(
    name="ett",
    mode="train",
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    context_len=128,
    horizon_len=64
)
# Fine-tune
finetuned_model = moirai_model.finetune(
    train_dataset,
    epochs=10,
    learning_rate=1e-5
)
# Evaluate
test_dataset = MoiraiDataset(
    name="ett",
    mode="test",
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    context_len=128,
    horizon_len=64
)
eval_results, trues, preds, histories = moirai_model.evaluate(test_dataset)
Normalization¶
MOIRAI includes built-in normalization:
# With normalization (default)
dataset = MoiraiDataset(
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    normalize=True,  # Normalize data
    context_len=128,
    horizon_len=64
)
# Denormalize predictions
eval_results, trues, preds, histories = moirai_model.evaluate(dataset)
denormalized_preds = dataset._denormalize_data(preds)
denormalized_trues = dataset._denormalize_data(trues)
Handling Multivariate Data¶
MOIRAI naturally handles multivariate time series:
# Your CSV with multiple columns
dataset = MoiraiDataset(
    path="data/multivariate.csv",
    datetime_col="date",
    freq="h",
    context_len=128,
    horizon_len=64
)
# Model will forecast each channel independently
eval_results, trues, preds, histories = moirai_model.evaluate(dataset)
# Results shape: (num_windows, num_channels, horizon_len)
Data Subsetting¶
Select specific date ranges:
dataset = MoiraiDataset(
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    start_date="2016-07-01",  # Start from this date
    end_date="2017-12-31",    # End at this date
    context_len=128,
    horizon_len=64
)
Visualization¶
Single Channel Forecast¶
import matplotlib.pyplot as plt
import numpy as np
eval_results, trues, preds, histories = moirai_model.evaluate(test_dataset)
trues = np.array(trues)
preds = np.array(preds)
histories = np.array(histories)
# Plot first channel, first window
channel_idx = 0
window_idx = 0
history = histories[window_idx, channel_idx, :]
true = trues[window_idx, channel_idx, :]
pred = preds[window_idx, channel_idx, :]
plt.figure(figsize=(14, 5))
plt.plot(range(len(history)), history, label="History", linewidth=2)
plt.plot(
    range(len(history), len(history) + len(true)),
    true,
    label="Ground Truth",
    linestyle="--",
    linewidth=2
)
plt.plot(
    range(len(history), len(history) + len(pred)),
    pred,
    label="MOIRAI Prediction",
    linewidth=2
)
plt.axvline(x=len(history), color='gray', linestyle=':', alpha=0.5)
plt.legend()
plt.title("MOIRAI Time Series Forecasting")
plt.xlabel("Time Step")
plt.ylabel("Value")
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
Multiple Channels¶
fig, axes = plt.subplots(2, 2, figsize=(16, 10))
axes = axes.flatten()
for i in range(min(4, trues.shape[1])):
    ax = axes[i]
    history = histories[0, i, :]
    true = trues[0, i, :]
    pred = preds[0, i, :]
    ax.plot(range(len(history)), history, label="History", alpha=0.7)
    ax.plot(
        range(len(history), len(history) + len(true)),
        true,
        label="Ground Truth",
        linestyle="--"
    )
    ax.plot(
        range(len(history), len(history) + len(pred)),
        pred,
        label="Prediction"
    )
    ax.set_title(f"Channel {i}")
    ax.legend()
    ax.grid(alpha=0.3)
plt.suptitle("MOIRAI Multi-Channel Forecasting")
plt.tight_layout()
plt.show()
Advanced Usage¶
Custom Boundaries¶
# Specify exact train/val/test split points
dataset = MoiraiDataset(
    path="data/ETTh1.csv",
    datetime_col="date",
    freq="h",
    boundaries=(0, 10000, 15000),  # Train: 0-10k, Val: 10k-15k, Test: 15k-end
    context_len=128,
    horizon_len=64
)
Different Context Lengths¶
# Short context
config = {
    "context_len": 64,
    "horizon_len": 32,
    # ...
}
# Long context
config = {
    "context_len": 512,
    "horizon_len": 256,
    # ...
}
Mixture-of-Experts Models¶
# Use MoE variant for better performance
repo = "Salesforce/moirai-moe-1.0-R-small"
config = {
    "context_len": 128,
    "horizon_len": 64,
    "model_type": "moirai-moe",  # MoE type
    "model_size": "small",
}
moirai_moe_model = MoiraiTSModel(repo=repo, config=config)
Tips and Best Practices¶
1. Model Selection¶
- Use Small for fast inference and experimentation
- Use Base for balanced performance
- Use Large for highest accuracy
- Use MoE variants for best performance at similar compute
2. Context Length¶
- Match context length to your data's pattern length
- Longer context captures more patterns but is slower
- Start with 128-256 and adjust based on results
3. Frequency Specification¶
- Always specify the correct frequency (freqparameter)
- Correct frequency helps MOIRAI understand temporal patterns
- MOIRAI can auto-detect frequency but explicit is better
4. Normalization¶
- Keep normalization enabled (default) for best results
- Remember to denormalize predictions for interpretation
Common Issues¶
CUDA Out of Memory¶
# Use smaller model
repo = "Salesforce/moirai-1.0-R-small"
# Reduce batch size
dataset = MoiraiDataset(
    batch_size=8,  # Instead of 16
    # ...
)
# Reduce context/horizon length
config = {
    "context_len": 64,  # Instead of 128
    "horizon_len": 32,  # Instead of 64
}
Incorrect Frequency¶
Make sure frequency matches your data:
# Check your data's datetime column
import pandas as pd
df = pd.read_csv("data.csv")
df['date'] = pd.to_datetime(df['date'])
inferred_freq = pd.infer_freq(df['date'])
print(f"Inferred frequency: {inferred_freq}")
# Use correct frequency
dataset = MoiraiDataset(
    freq=inferred_freq,  # Use inferred frequency
    # ...
)
API Reference¶
For detailed API documentation, see:
Examples¶
See the Examples page for complete working examples.