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.