Aller au contenu principal

Module 1 — Ce qui distingue une série temporelle des autres données

Les cours d'apprentissage supervisé partaient d'un tableau où chaque ligne était considérée comme un tirage indépendant : les vingt clients qui figurent en haut n'ont rien de plus à dire sur les vingt du bas que sur ceux de la première ligne. Cette hypothèse — l'indépendance des observations — sous-tend la validation croisée aléatoire, la stratification et la plupart des garanties statistiques que l'on manipule. Or dans notre fil rouge, la vente d'un lundi de janvier n'est pas indépendante de celle du dimanche qui précède ni de celle du lundi suivant. Le temps introduit une structure de dépendance qui invalide plusieurs pratiques par défaut et exige un vocabulaire propre.

Ce qu'est une série temporelle

Une série temporelle est une suite d'observations d'une grandeur ordonnée dans le temps et échantillonnée à une fréquence fixe. Notre réseau de pharmacies enregistre les ventes une fois par jour, sur quatre ans : cela donne environ 1 460 valeurs alignées sur un calendrier régulier. La régularité compte : lorsqu'un jour manque parce que le magasin était fermé, ce n'est pas une observation absente qu'on peut simplement retirer, c'est un trou dans un tissu qu'il faudra reconstituer ou dont il faudra rendre compte.

On distingue habituellement deux vues sur la même quantité. La série univariée est la seule chronique observée — les ventes totales par jour. La série multivariée ajoute d'autres chroniques synchronisées, comme la température moyenne du jour, un indicateur de campagne promotionnelle ou l'incidence grippale. On appelle régresseurs externes ces variables auxiliaires ; le module 7 leur est consacré et le module 5 y reviendra sous le nom de « variables exogènes ».

Un vocabulaire minimal fixe le reste. La série a une tendance lorsqu'elle progresse ou décline sur le long terme, une saisonnalité lorsqu'un motif se répète à période fixe (le pic hebdomadaire du samedi, le creux annuel d'août), un cycle lorsqu'un motif se répète sans période fixe (les vagues épidémiques), et un bruit irréductible. Le module suivant proposera une décomposition explicite de ces composantes.

L'horizon et le pas

L'horizon de prévision est le point de départ de toute conception, et c'est celui qui contraint le plus le choix méthodologique. Prévoir la vente du lendemain, celle de la semaine à venir, ou la demande sur les vingt-huit prochains jours sont trois problèmes différents, même sur la même série. Notre projet impose 28 jours : la dernière valeur observée est parfois utile pour prévoir demain, mais elle explique presque rien de la vente dans quatre semaines, où seule la structure saisonnière compte encore.

Le pas est la granularité de la prévision. Un horizon de 28 jours au pas quotidien produit 28 valeurs prédictes ; au pas hebdomadaire, il en produirait quatre. Le pas est en général celui de l'échantillonnage, mais rien n'oblige à prévoir aussi finement qu'on observe.

Le découpage : d'abord dans le temps

C'est le point qui fait échouer le plus de projets. Avec des données tabulaires indépendantes, on tire aléatoirement 80 % pour l'entraînement et 20 % pour le test. Cette procédure est interdite pour une série temporelle, et pour une raison simple : elle place des observations postérieures dans le lot d'entraînement, si bien que le modèle apprend à connaître un futur qu'il devra prédire — c'est ce qu'on appelle la fuite du futur.

Le découpage correct est chronologique. Les trois premières années servent à l'entraînement, la quatrième au test, sans mélange. Une variante intermédiaire, la validation glissante par origine mobile, sera introduite au module 9 : elle simule plusieurs origines de prévision successives pour évaluer la stabilité d'un modèle dans le temps.

import numpy as np
import pandas as pd

# Chargement du fil rouge : ventes quotidiennes de 2022-01-01 a 2025-12-31.
ventes = pd.read_csv("ventes_pharmacies.csv", parse_dates=["date"], index_col="date")
ventes = ventes.asfreq("D") # index quotidien explicite, sans trou

# Decoupage chronologique : 3 ans pour entrainer, 1 an pour tester.
seuil = pd.Timestamp("2025-01-01")
train = ventes.loc[:seuil - pd.Timedelta(days=1)]
test = ventes.loc[seuil:]

print(f"entrainement : {train.index.min().date()} -> {train.index.max().date()} ({len(train)} jours)")
print(f"test : {test.index.min().date()} -> {test.index.max().date()} ({len(test)} jours)")

# Verification : aucune date du test n'est anterieure a la fin de l'entrainement.
assert test.index.min() > train.index.max()

Cette assertion peut paraître triviale, mais elle attrape une classe entière d'erreurs de tuyauterie : jointures qui remélangent les lignes, tri par identifiant plutôt que par date, ou split aléatoire copié depuis un notebook de classification.

La fuite du futur, sous ses formes moins visibles

Le mélange aléatoire est la fuite la plus grossière ; il en existe de plus discrètes. La normalisation calculée sur l'ensemble complet en est une : si vous soustrayez la moyenne des quatre années aux valeurs du train, cette moyenne a été influencée par le test, et vos scores d'évaluation s'en trouvent maquillés. Le module 3 en donnera un exemple lors du choix de l'ordre de différenciation.

Une deuxième fuite s'installe dans la construction de variables : un décalage (« lag ») de 7 jours calculé après avoir concaténé train et test fait entrer des valeurs de test dans les lignes du bord — un simple shift(-1) mal placé fait pire encore. Le module 7 fixera la règle : les décalages, moyennes glissantes et cumuls se calculent exclusivement à partir du passé, et la coupe train/test se fait avant l'ingénierie de variables.

Une troisième fuite provient des régresseurs. Utiliser la météo réelle du jour à prédire est valable si vous prévoyez la vente à 12 h à partir de la météo du matin, mais interdit si vous prévoyez à horizon de 28 jours sans disposer d'une prévision météo à 28 jours. La règle utile : à l'instant où vous voulez que le modèle fonctionne en production, quelles variables connaît-on vraiment ?

La règle unique à retenir

Toute grandeur qui entre dans une prédiction pour la date tt doit être connue au plus tard à l'instant où la prévision est faite. Si vous ne pouvez pas dire à quel moment précis chaque colonne devient disponible, la fuite est déjà présente ; les scores flatteurs seront invalidés par la production.

Ce qui change pour un modèle

La dépendance temporelle a des conséquences concrètes sur le modèle. Le mélange de lots pendant l'entraînement d'un réseau doit être fait sur des fenêtres, pas sur des observations individuelles (le module 8 y reviendra). Les statistiques d'entraînement — moyenne, écart-type — se recalculent périodiquement, car la série évolue. Enfin, un modèle validé une fois n'est jamais validé pour toujours : le module 10 introduira un plan de réentraînement.

Le geste initial qui économise des heures

Avant toute modélisation, tracez la série entière. Sur notre fil rouge, une seule figure suffit à repérer la coupure des confinements en 2022, le décrochage estival annuel, le pic hebdomadaire du samedi et l'effet d'une promotion massive. Ces observations orientent la décomposition (module 2), le choix de l'ordre saisonnier (modules 3 et 5) et la sélection des régresseurs (module 7). Un modèle ajusté sans avoir regardé la figure est presque toujours mal spécifié.

En résumé

  • Une série temporelle est ordonnée et échantillonnée à fréquence fixe ; les observations ne sont pas indépendantes.
  • L'horizon de prévision contraint le choix méthodologique bien plus que le volume de données ; ici, 28 jours au pas quotidien.
  • Le découpage est chronologique, jamais aléatoire ; toute grandeur utilisée doit être connue à l'instant de la prévision, sinon il y a fuite du futur.
  • Vocabulaire de base : tendance, saisonnalité, cycle, bruit, régresseurs externes — ces briques structurent tout le reste du cours.

Module suivant : la décomposition d'une série en tendance, saisonnalité et bruit, avec STL et les saisonnalités multiples de notre fil rouge.