timesfm-forecasting

Par mkurman · zorai

npx skills add https://github.com/mkurman/zorai --skill timesfm-forecasting

name: timesfm-forecasting description: Prévision de séries temporelles sans entraînement avec le modèle fondationnel TimesFM de Google. Utilisez pour n'importe quelle série temporelle univariée (ventes, capteurs, énergie, signes vitaux, météo) sans entraîner un modèle personnalisé. Supporte les entrées CSV/DataFrame/tableau avec prévisions ponctuelles et intervalles de prédiction. Inclut un script de vérification système pour vérifier la RAM/GPU avant la première utilisation. allowed-tools: Read Write Edit Bash license: Apache-2.0 license tags: [time-series-forecasting, foundation-models, temporal-prediction, business-forecasting, timesfm-forecasting] metadata: skill-author: Clayton Young / Superior Byte Works, LLC (@borealBytes) skill-version: "1.0.0" ---------- | --------- | ---------- | ---- | ------- | | TimesFM 2.5 (recommandé) | 200M | ≥ 4 GB | ≥ 2 GB | ~800 MB | jusqu'à 16 384 | | TimesFM 2.0 (archivé) | 500M | ≥ 16 GB | ≥ 8 GB | ~2 GB | jusqu'à 2 048 | | TimesFM 1.0 (archivé) | 200M | ≥ 8 GB | ≥ 4 GB | ~800 MB | jusqu'à 2 048 |

Recommandation : Utilisez toujours TimesFM 2.5 sauf si vous avez une raison particulière d'utiliser un checkpoint plus ancien. Il est plus petit, plus rapide et supporte un contexte 8× plus long.

🔧 Installation

Étape 1 : Vérifier le système (toujours en premier)

python scripts/check_system.py

Étape 2 : Installer TimesFM

# Avec uv (recommandé par ce repository)
uv pip install timesfm[torch]

# Ou avec pip
pip install timesfm[torch]

# Pour le backend JAX/Flax (plus rapide sur TPU/GPU)
uv pip install timesfm[flax]

Étape 3 : Installer PyTorch pour votre matériel

# CUDA 12.1 (GPU NVIDIA)
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cu121

# CPU uniquement
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cpu

# Apple Silicon (MPS)
pip install torch>=2.0.0  # Le support MPS est intégré

Étape 4 : Vérifier l'installation

import timesfm
import numpy as np
print(f"TimesFM version: {timesfm.__version__}")
print("Installation OK")

🎯 Démarrage rapide

Exemple minimal (5 lignes)

import torch, numpy as np, timesfm

torch.set_float32_matmul_precision("high")

model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
    "google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
    max_context=1024, max_horizon=256, normalize_inputs=True,
    use_continuous_quantile_head=True, force_flip_invariance=True,
    infer_is_positive=True, fix_quantile_crossing=True,
))

point, quantiles = model.forecast(horizon=24, inputs=[
    np.sin(np.linspace(0, 20, 200)),  # n'importe quel tableau 1-D
])
# point.shape == (1, 24)        — prévision médiane
# quantiles.shape == (1, 24, 10) — bandes de percentiles 10e–90e

Prévision à partir d'un CSV

import pandas as pd, numpy as np

df = pd.read_csv("monthly_sales.csv", parse_dates=["date"], index_col="date")

# Convertissez chaque colonne en liste de tableaux
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]

point, quantiles = model.forecast(horizon=12, inputs=inputs)

# Construisez un DataFrame de résultats
for i, col in enumerate(df.columns):
    last_date = df[col].dropna().index[-1]
    future_dates = pd.date_range(last_date, periods=13, freq="MS")[1:]
    forecast_df = pd.DataFrame({
        "date": future_dates,
        "forecast": point[i],
        "lower_80": quantiles[i, :, 2],  # 20e percentile
        "upper_80": quantiles[i, :, 8],  # 80e percentile
    })
    print(f"\n--- {col} ---")
    print(forecast_df.to_string(index=False))

Prévision avec covariables (XReg)

TimesFM 2.5+ supporte les variables exogènes via forecast_with_covariates(). Nécessite timesfm[xreg].

# Nécessite : uv pip install timesfm[xreg]
point, quantiles = model.forecast_with_covariates(
    inputs=inputs,
    dynamic_numerical_covariates={"price": price_arrays},
    dynamic_categorical_covariates={"holiday": holiday_arrays},
    static_categorical_covariates={"region": region_labels},
    xreg_mode="xreg + timesfm",  # ou "timesfm + xreg"
)
Type de covariable Description Exemple
dynamic_numerical Numérique variant dans le temps prix, température, dépense en promotion
dynamic_categorical Catégorique variant dans le temps drapeau de vacances, jour de la semaine
static_numerical Numérique par série taille du magasin, ancienneté du compte
static_categorical Catégorique par série type de magasin, région, catégorie de produit

Modes XReg :

  • "xreg + timesfm" (par défaut) : TimesFM prévoit en premier, puis XReg ajuste les résidus
  • "timesfm + xreg" : XReg s'ajuste en premier, puis TimesFM prévoit les résidus

Voir examples/covariates-forecasting/ pour un exemple complet avec des données de vente synthétiques.

Détection d'anomalies (via intervalles de quantiles)

TimesFM n'a pas de détection d'anomalies intégrée, mais les prévisions de quantiles fournissent naturellement des intervalles de prédiction qui peuvent détecter les anomalies :

point, q = model.forecast(horizon=H, inputs=[values])

# Intervalle de prédiction 90%
lower_90 = q[0, :, 1]  # 10e percentile
upper_90 = q[0, :, 9]  # 90e percentile

# Détectez les anomalies : valeurs en dehors de l'IC 90%
actual = test_values  # vos données de validation
anomalies = (actual < lower_90) | (actual > upper_90)

# Niveaux de gravité
is_warning = (actual < q[0, :, 2]) | (actual > q[0, :, 8])  # en dehors de l'IC 80%
is_critical = anomalies  # en dehors de l'IC 90%
Gravité Condition Interprétation
Normal Dans l'IC 80% Comportement attendu
Avertissement En dehors de l'IC 80% Inhabituel mais possible
Critique En dehors de l'IC 90% Statistiquement rare (< 10 % de probabilité)

Voir examples/anomaly-detection/ pour un exemple complet avec visualisation.

# Nécessite : uv pip install timesfm[xreg]
point, quantiles = model.forecast_with_covariates(
    inputs=inputs,
    dynamic_numerical_covariates={"temperature": temp_arrays},
    dynamic_categorical_covariates={"day_of_week": dow_arrays},
    static_categorical_covariates={"region": region_labels},
    xreg_mode="xreg + timesfm",  # ou "timesfm + xreg"
)

📊 Comprendre la sortie

Structure de prévision des quantiles

TimesFM retourne (point_forecast, quantile_forecast) :

  • point_forecast : forme (batch, horizon) — la médiane (quantile 0,5)
  • quantile_forecast : forme (batch, horizon, 10) — dix tranches :
Index Quantile Utilisation
0 Moyenne Prédiction moyenne
1 0,1 Limite inférieure de PI 80%
2 0,2 Limite inférieure de PI 60%
3 0,3
4 0,4
5 0,5 Médiane (= point_forecast)
6 0,6
7 0,7
8 0,8 Limite supérieure de PI 60%
9 0,9 Limite supérieure de PI 80%

Extraction des intervalles de prédiction

point, q = model.forecast(horizon=H, inputs=data)

# Intervalle de prédiction 80% (le plus courant)
lower_80 = q[:, :, 1]  # 10e percentile
upper_80 = q[:, :, 9]  # 90e percentile

# Intervalle de prédiction 60% (plus serré)
lower_60 = q[:, :, 2]  # 20e percentile
upper_60 = q[:, :, 8]  # 80e percentile

# Médiane (identique à la prévision ponctuelle)
median = q[:, :, 5]
flowchart LR
    accTitle: Quantile Forecast Anatomy
    accDescr: Diagram showing how the 10-element quantile vector maps to prediction intervals.

    input["📈 Input Series<br/>1-D array"] --> model["🤖 TimesFM<br/>compile + forecast"]
    model --> point["📍 Point Forecast<br/>(batch, horizon)"]
    model --> quant["📊 Quantile Forecast<br/>(batch, horizon, 10)"]
    quant --> pi80["80% PI<br/>q[:,:,1] – q[:,:,9]"]
    quant --> pi60["60% PI<br/>q[:,:,2] – q[:,:,8]"]
    quant --> median["Median<br/>q[:,:,5]"]

    classDef data fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
    classDef model fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#581c87
    classDef output fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d

    class input data
    class model model
    class point,quant,pi80,pi60,median output

🔧 Référence ForecastConfig

Tout le comportement de prévision est contrôlé par timesfm.ForecastConfig :

timesfm.ForecastConfig(
    max_context=1024,                    # Fenêtre de contexte max (tronque les séries plus longues)
    max_horizon=256,                     # Horizon de prévision max
    normalize_inputs=True,               # Normalise les entrées (RECOMMANDÉ pour la stabilité)
    per_core_batch_size=32,              # Taille de batch par appareil (à régler selon la mémoire)
    use_continuous_quantile_head=True,   # Meilleure précision des quantiles pour les longs horizons
    force_flip_invariance=True,          # Assure f(-x) = -f(x) (cohérence mathématique)
    infer_is_positive=True,              # Limite les prévisions ≥ 0 quand toutes les entrées > 0
    fix_quantile_crossing=True,          # Assure q10 ≤ q20 ≤ ... ≤ q90
    return_backcast=False,               # Retourne le backcast (pour les workflows de covariables)
)
Paramètre Défaut Quand changer
max_context 0 Régler pour correspondre à votre fenêtre historique la plus longue (ex. 512, 1024, 4096)
max_horizon 0 Régler pour votre longueur de prévision maximale
normalize_inputs False Toujours régler à True — évite l'instabilité dépendante de l'échelle
per_core_batch_size 1 Augmentez pour le débit ; diminuez en cas d'OOM
use_continuous_quantile_head False Régler à True pour les intervalles de prédiction calibrés
force_flip_invariance True Garder True sauf si le profilage montre un impact négatif
infer_is_positive True Régler à False pour les séries pouvant être négatives (température, rendements)
fix_quantile_crossing False Régler à True pour garantir des quantiles monotones

📋 Workflows courants

Workflow 1 : Prévision d'une seule série

flowchart TD
    accTitle: Single Series Forecast Workflow
    accDescr: Step-by-step workflow for forecasting a single time series with system checking.

    check["1. Exécutez check_system.py"] --> load["2. Chargez le modèle<br/>from_pretrained()"]
    load --> compile["3. Compilez avec ForecastConfig"]
    compile --> prep["4. Préparez les données<br/>pd.read_csv → np.array"]
    prep --> forecast["5. model.forecast()<br/>horizon=N"]
    forecast --> extract["6. Extrayez point + PI"]
    extract --> plot["7. Tracez ou exportez les résultats"]

    classDef step fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
    class check,load,compile,prep,forecast,extract,plot step
import torch, numpy as np, pandas as pd, timesfm

# 1. Vérification système (une seule fois)
# python scripts/check_system.py

# 2-3. Charger et compiler
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
    "google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
    max_context=512, max_horizon=52, normalize_inputs=True,
    use_continuous_quantile_head=True, fix_quantile_crossing=True,
))

# 4. Préparer les données
df = pd.read_csv("weekly_demand.csv", parse_dates=["week"])
values = df["demand"].values.astype(np.float32)

# 5. Prévoir
point, quantiles = model.forecast(horizon=52, inputs=[values])

# 6. Extraire les intervalles de prédiction
forecast_df = pd.DataFrame({
    "forecast": point[0],
    "lower_80": quantiles[0, :, 1],
    "upper_80": quantiles[0, :, 9],
})

# 7. Tracer
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(values[-104:], label="Historical")
x_fc = range(len(values[-104:]), len(values[-104:]) + 52)
ax.plot(x_fc, forecast_df["forecast"], label="Forecast", color="tab:orange")
ax.fill_between(x_fc, forecast_df["lower_80"], forecast_df["upper_80"],
                alpha=0.2, color="tab:orange", label="80% PI")
ax.legend()
ax.set_title("52-Week Demand Forecast")
plt.tight_layout()
plt.savefig("forecast.png", dpi=150)
print("Saved forecast.png")

Workflow 2 : Prévision par lot (nombreuses séries)

import pandas as pd, numpy as np

# Charger un CSV au format large (une colonne par série)
df = pd.read_csv("all_stores.csv", parse_dates=["date"], index_col="date")
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]

# Prévoir toutes les séries à la fois (lot interne)
point, quantiles = model.forecast(horizon=30, inputs=inputs)

# Collecter les résultats
results = {}
for i, col in enumerate(df.columns):
    results[col] = {
        "forecast": point[i].tolist(),
        "lower_80": quantiles[i, :, 1].tolist(),
        "upper_80": quantiles[i, :, 9].tolist(),
    }

# Exporter
import json
with open("batch_forecasts.json", "w") as f:
    json.dump(results, f, indent=2)
print(f"Prévues {len(results)} séries → batch_forecasts.json")

Workflow 3 : Évaluer la précision de la prévision

import numpy as np

# Réserver les H derniers points pour l'évaluation
H = 24
train = values[:-H]
actual = values[-H:]

point, quantiles = model.forecast(horizon=H, inputs=[train])
pred = point[0]

# Métriques
mae = np.mean(np.abs(actual - pred))
rmse = np.sqrt(np.mean((actual - pred) ** 2))
mape = np.mean(np.abs((actual - pred) / actual)) * 100

# Couverture de l'intervalle de prédiction
lower = quantiles[0, :, 1]
upper = quantiles[0, :, 9]
coverage = np.mean((actual >= lower) & (actual <= upper)) * 100

print(f"MAE:  {mae:.2f}")
print(f"RMSE: {rmse:.2f}")
print(f"MAPE: {mape:.1f}%")
print(f"80% PI Coverage: {coverage:.1f}% (target: 80%)")

⚙️ Optimisation des performances

Accélération GPU

import torch

# Vérifier la disponibilité du GPU
if torch.cuda.is_available():
    print(f"GPU: {torch.cuda.get_device_name(0)}")
    print(f"VRAM: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")
elif hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
    print("Apple Silicon MPS disponible")
else:
    print("CPU uniquement — l'inférence sera plus lente mais fonctionnera")

# Toujours régler ceci pour les GPU Ampere+ (A100, RTX 3090, etc.)
torch.set_float32_matmul_precision("high")

Réglage de la taille de batch

# Commencez conservatif, augmentez jusqu'à OOM
# GPU avec 8 GB VRAM :  per_core_batch_size=64
# GPU avec 16 GB VRAM : per_core_batch_size=128
# GPU avec 24 GB VRAM : per_core_batch_size=256
# CPU avec 8 GB RAM :   per_core_batch_size=8
# CPU avec 16 GB RAM :  per_core_batch_size=32
# CPU avec 32 GB RAM :  per_core_batch_size=64

model.compile(timesfm.ForecastConfig(
    max_context=1024,
    max_horizon=256,
    per_core_batch_size=32,  # <-- réglez ceci
    normalize_inputs=True,
    use_continuous_quantile_head=True,
    fix_quantile_crossing=True,
))

Environnements à mémoire limitée

import gc, torch

# Forcer la collecte des poubelles avant le chargement
gc.collect()
if torch.cuda.is_available():
    torch.cuda.empty_cache()

# Charger le modèle
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
    "google/timesfm-2.5-200m-pytorch"
)

# Utiliser une petite taille de batch sur les machines à faible mémoire
model.compile(timesfm.ForecastConfig(
    max_context=512,        # Réduisez le contexte si nécessaire
    max_horizon=128,        # Réduisez l'horizon si nécessaire
    per_core_batch_size=4,  # Petits lots
    normalize_inputs=True,
    use_continuous_quantile_head=True,
    fix_quantile_crossing=True,
))

# Traiter les séries par chunks pour éviter l'OOM
CHUNK = 50
all_results = []
for i in range(0, len(inputs), CHUNK):
    chunk = inputs[i:i+CHUNK]
    p, q = model.forecast(horizon=H, inputs=chunk)
    all_results.append((p, q))
    gc.collect()  # Nettoyer entre les chunks

🔗 Intégration avec d'autres skills

Avec statsmodels

Utilisez statsmodels pour les modèles classiques (ARIMA, SARIMAX) comme ligne de base de comparaison :

# Prévision TimesFM
tfm_point, tfm_q = model.forecast(horizon=H, inputs=[values])

# Prévision statsmodels ARIMA
from statsmodels.tsa.arima.model import ARIMA
arima = ARIMA(values, order=(1,1,1)).fit()
arima_forecast = arima.forecast(steps=H)

# Comparer
print(f"TimesFM MAE: {np.mean(np.abs(actual - tfm_point[0])):.2f}")
print(f"ARIMA MAE:   {np.mean(np.abs(actual - arima_forecast)):.2f}")

Avec matplotlib / scientific-visualization

Tracez les prévisions avec des intervalles de prédiction comme figures de qualité pour publication.

Avec exploratory-data-analysis

Exécutez l'EDA sur la série temporelle avant la prévision pour comprendre les tendances, la saisonnalité et la stationnarité.

📚 Scripts disponibles

scripts/check_system.py

Vérificateur de vol obligatoire. Exécutez avant le premier chargement de modèle.

python scripts/check_system.py

Exemple de sortie :

=== TimesFM System Requirements Check ===

[RAM]       Total: 32.0 GB | Available: 24.3 GB  ✅ PASS
[GPU]       NVIDIA RTX 4090 | VRAM: 24.0 GB      ✅ PASS
[Disk]      Free: 142.5 GB                        ✅ PASS
[Python]    3.12.1                                 ✅ PASS
[timesfm]   Installed (2.5.0)                      ✅ PASS
[torch]     Installed (2.4.1+cu121)                ✅ PASS

VERDICT: ✅ System is ready for TimesFM 2.5 (GPU mode)
Recommended: per_core_batch_size=128

scripts/forecast_csv.py

Prévision CSV de bout en bout avec vérification système automatique.

python scripts/forecast_csv.py input.csv \
    --horizon 24 \
    --date-col date \
    --value-cols sales,revenue \
    --output forecasts.csv

📖 Documentation de référence

Guides détaillés dans references/ :

Fichier Contenu
references/system_requirements.md Tiers matériels, sélection GPU/CPU, formules d'estimation de mémoire
references/api_reference.md Docs ForecastConfig complets, options from_pretrained, formes de sortie
references/data_preparation.md Formats d'entrée, gestion des NaN, chargement CSV, configuration des covariables

Pièges courants

  1. Ne pas exécuter la vérification système → le chargement du modèle échoue sur les machines à faible RAM. Exécutez toujours check_system.py en premier.
  2. Oublier model.compile()RuntimeError: Model is not compiled. Doit appeler compile() avant forecast().
  3. Ne pas régler normalize_inputs=True → prévisions instables pour les séries avec de grandes valeurs.
  4. Utiliser v1/v2 sur des machines avec < 32 GB RAM → utilisez TimesFM 2.5 (200M params) à la place.
  5. Ne pas régler fix_quantile_crossing=True → les quantiles peuvent ne pas être monotones (q10 > q50).
  6. Énorme per_core_batch_size sur petit GPU → CUDA OOM. Commencez petit, augmentez.
  7. Passer des tableaux 2-D → TimesFM attend une liste de tableaux 1-D, pas une matrice 2-D.
  8. Oublier torch.set_float32_matmul_precision("high") → inférence plus lente sur GPU Ampere+.
  9. Ne pas gérer NaN en sortie → cas limites avec séries très courtes. Vérifiez toujours np.isnan(point).any().
  10. Utiliser infer_is_positive=True pour les séries pouvant être négatives → limite les prévisions à zéro. Régler à False pour la température, les rendements, etc.

Versions du modèle

timeline
    accTitle: TimesFM Version History
    accDescr: Timeline of TimesFM model releases showing parameter counts and key improvements.

    section 2024
        TimesFM 1.0 : 200M params, 2K context, JAX only
        TimesFM 2.0 : 500M params, 2K context, PyTorch + JAX
    section 2025
        TimesFM 2.5 : 200M params, 16K context, quantile head, no frequency indicator
Version Params Contexte Tête quantile Drapeau fréquence Statut
2.5 200M 16 384 ✅ Continue (30M) ❌ Supprimé Dernier
2.0 500M 2 048 ✅ Buckets fixes ✅ Requis Archivé
1.0 200M 2 048 ✅ Buckets fixes ✅ Requis Archivé

Checkpoints Hugging Face :

  • google/timesfm-2.5-200m-pytorch (recommandé)
  • google/timesfm-2.5-200m-flax
  • google/timesfm-2.0-500m-pytorch (archivé)
  • google/timesfm-1.0-200m-pytorch (archivé)

Ressources

Exemples

Trois exemples entièrement fonctionnels vivent dans examples/. Utilisez-les comme source de vérité pour l'utilisation correcte de l'API et la forme de sortie attendue.

Exemple Répertoire Ce qu'il démontre Quand l'utiliser
Prévision température mondiale examples/global-temperature/ Appel basique model.forecast(), pipeline CSV -> PNG -> GIF, contexte NOAA 36 mois Point de départ ; copiez-collez la base pour n'importe quelle série univariée
Détection d'anomalies examples/anomaly-detection/ Détection deux phases : détrendance linéaire + Z-score sur contexte, PI quantile sur prévision ; viz 2 panneaux N'importe quelle tâche nécessitant la détection de valeurs aberrantes sur données historiques + prévues
Covariables (XReg) examples/covariates-forecasting/ API forecast_with_covariates() (TimesFM 2.5), décomposition covariables, viz 2x2 axe partagé Vente au détail, énergie ou n'importe quelle série avec moteurs exogènes connus

Exécuter les exemples

# Température mondiale (TimesFM 2.5 pas nécessaire)
cd examples/global-temperature && python run_forecast.py && python visualize_forecast.py

# Détection d'anomalies (utilise TimesFM 1.0)
cd examples/anomaly-detection && python detect_anomalies.py

# Covariables (démo API -- nécessite TimesFM 2.5 + timesfm[xreg] pour inférence réelle)
cd examples/covariates-forecasting && python demo_covariates.py

Sorties attendues

Exemple Fichiers de sortie clés Critères d'acceptation
global-temperature output/forecast_output.json, output/forecast_visualization.png point_forecast a 12 valeurs ; PNG montre contexte + prévision + bandes PI
anomaly-detection output/anomaly_detection.json, output/anomaly_detection.png Sep 2023 marqué CRITICAL (z >= 3,0) ; >= 2 prévisions CRITICAL des anomalies injectées
covariates-forecasting output/sales_with_covariates.csv, output/covariates_data.png CSV a 108 lignes (3 magasins x 36 semaines) ; les magasins ont des tableaux de prix distincts

Liste de contrôle de qualité

Exécutez cette liste de contrôle après chaque tâche TimesFM avant de déclarer succès :

  • [ ] Forme de sortie correcte -- point_fc shape est (n_series, horizon), quant_fc est (n_series, horizon, 10)
  • [ ] Indices de quantiles -- index 0 = moyenne, 1 = q10, 2 = q20 ... 9 = q90. PAS 0 = q0, 1 = q10.
  • [ ] Drapeau fréquence -- TimesFM 1.0/2.0 : passer freq=[0] pour données mensuelles. TimesFM 2.5 : pas de drapeau freq.
  • [ ] Longueur de série -- contexte doit être >= 32 points de données (minimum modèle). Avertir si plus court.
  • [ ] Pas de NaN -- np.isnan(point_fc).any() doit être False. Vérifier d'abord les écarts de série d'entrée.
  • [ ] Axes de visualisation -- si plusieurs panneaux partagent des données, utiliser sharex=True. Tous les axes temporels doivent couvrir la même plage.
  • [ ] Sorties binaires dans Git LFS -- les fichiers PNG et GIF doivent être suivis via .gitattributes (repo root déjà configuré).
  • [ ] Pas de grands ensembles de données committés -- n'importe quel ensemble de données réel > 1 MB doit être téléchargé vers tempfile.mkdtemp() et annoté dans le code.
  • [ ] matplotlib.use('Agg') -- doit apparaître avant toute importation pyplot lors d'une exécution sans tête.
  • [ ] infer_is_positive -- régler à False pour les anomalies de température, les rendements financiers ou n'importe quelle série pouvant être négative.

Erreurs courantes

Ces bugs sont apparus dans les exemples de ce skill. Apprenez-en :

  1. Index de quantile décalé d'un -- L'erreur la plus courante. quant_fc[..., 0] est la moyenne, pas q0. q10 = index 1, q90 = index 9. Toujours définir des constantes nommées : IDX_Q10, IDX_Q20, IDX_Q80, IDX_Q90 = 1, 2, 8, 9.

  2. Ombrage de variable dans les compréhensions -- Si vous construisez des dicts de covariables par série dans une boucle, n'utilisez PAS la variable de boucle comme variable de compréhension. Accumulez dans des dict[str, ndarray] distincts en dehors de la boucle, puis assignez.

    # MAUVAIS -- `store_id` externe est ombragé :
    covariates = {store_id: arr[store_id] for store_id in stores}  # dans boucle externe sur store_id
    # CORRECT -- utiliser un nom différent ou accumuler à l'avance :
    prices_by_store: dict[str, np.ndarray] = {}
    for store_id, config in stores.items():
        prices_by_store[store_id] = compute_price(config)
  3. Mauvais nom de colonne CSV -- Le CSV de température mondiale utilise anomaly_c, pas anomaly. Toujours print(df.columns) avant d'accéder.

  4. Avertissement tight_layout() avec sharex=True -- Inoffensif ; supprimer avec plt.tight_layout(rect=[0, 0, 1, 0.97]) ou ignorer.

  5. TimesFM 2.5 requis pour forecast_with_covariates() -- TimesFM 1.0 n'a PAS cette méthode. Installer pip install timesfm[xreg] et utiliser checkpoint google/timesfm-2.5-200m-pytorch.

  6. Les covariables futures doivent couvrir l'horizon complet -- Les covariables dynamiques (prix, promotions, vacances) doivent avoir des valeurs pour le contexte ET l'horizon de prévision. Vous ne pouvez pas passer des tableaux contexte-uniquement.

  7. Les seuils d'anomalie doivent être définis une seule fois -- Définir CRITICAL_Z = 3.0, WARNING_Z = 2.0 comme constantes au niveau du module. Ne jamais coder en dur 3 ou 2 en ligne.

  8. La détection d'anomalie de contexte utilise les résidus, pas les valeurs brutes -- Toujours détendre d'abord (np.polyfit linéaire, ou décomposition saisonnière), puis Z-score les résidus. Les Z-scores de valeurs brutes sont trompeurs sur données en tendance.

Validation et vérification

Utilisez les sorties d'exemple comme bases de référence de régression. Si vous modifiez la logique de prévision, vérifiez :

# Vérification régression détection d'anomalies :
python -c "
import json
d = json.load(open('examples/anomaly-detection/output/anomaly_detection.json'))
ctx = d['context_summary']
assert ctx['critical'] >= 1, 'Sep 2023 must be CRITICAL'
assert any(r['date'] == '2023-09' and r['severity'] == 'CRITICAL'
           for r in d['context_detections']), 'Sep 2023 not found'
print('Anomaly detection regression: PASS')"

# Vérification régression covariables :
python -c "
import pandas as pd
df = pd.read_csv('examples/covariates-forecasting/output/sales_with_covariates.csv')
assert len(df) == 108, f'Expected 108 rows, got {len(df)}'
prices = df.groupby('store_id')['price'].mean()
assert prices['store_A'] > prices['store_B'] > prices['store_C'], 'Store price ordering wrong'
print('Covariates regression: PASS')"

Skills similaires