AccueilBlogTest technique séries temporelles : analyse, prédiction, anomaly detection
Guide recrutement data

Test technique séries temporelles : analyse, prédiction, anomaly detection

Les données temporelles ont des propriétés spécifiques (autocorrélation, saisonnalité, trend) qui nécessitent des méthodes dédiées. En entretien, on évalue la compréhension de ces spécificités.

Data Builder·Juin 2025·7 min de lecture·Data Scientist · Data Analyst
Sommaire
  1. Décomposition de séries temporelles
  2. Stationnarité
  3. ARIMA et SARIMA
  4. Prophet : prédiction pratique
  5. Détection d anomalies
  6. Features temporelles pour ML
  7. Grille

1Décomposition : trend, saisonnalité, résidu

Question discriminante

Quels sont les 3 composantes d une série temporelle ? Comment les extraire ?

from statsmodels.tsa.seasonal import seasonal_decompose import pandas as pd df = pd.read_csv('sales.csv', parse_dates=['date'], index_col='date') # Décomposition additive : Y = Trend + Saisonnalité + Résidu # (quand la saisonnalité ne dépend pas du niveau) result = seasonal_decompose(df['revenue'], model='additive', period=52) # Décomposition multiplicative : Y = Trend * Saisonnalité * Résidu # (quand la saisonnalité est proportionnelle au niveau) result_mult = seasonal_decompose(df['revenue'], model='multiplicative', period=52) print('Trend:', result.trend[:5]) print('Seasonal:', result.seasonal[:5]) print('Residual:', result.resid[:5])
  • Additif — la saisonnalité est constante (même amplitude quelle que soit la valeur)
  • Multiplicatif — la saisonnalité est proportionnelle au niveau (amplitude grandit avec le niveau)

2Stationnarité : pourquoi c est important

Question discriminante

Qu est-ce que la stationnarité ? Comment testez-vous si une série est stationnaire ?

from statsmodels.tsa.stattools import adfuller # Test de Dickey-Fuller augmenté # H0 : la série a une racine unitaire (non stationnaire) result = adfuller(df['revenue']) adf_stat, p_value = result[0], result[1] print(f'ADF Statistic: {adf_stat:.4f}') print(f'p-value: {p_value:.4f}') if p_value < 0.05: print('Stationnaire (rejette H0)') else: print('NON stationnaire - différenciation nécessaire') df_diff = df['revenue'].diff().dropna() # différenciation d ordre 1 result_diff = adfuller(df_diff) print(f'Après différenciation: p={result_diff[1]:.4f}')
  • Stationnarité — mean, variance et autocorrélation constantes dans le temps
  • ARIMA nécessite — une série stationnaire. La différenciation (d dans ARIMA) rend la série stationnaire

3ARIMA : comprendre les paramètres

Question discriminante

Que signifient les paramètres p, d, q dans ARIMA(p,d,q) ?

from statsmodels.tsa.arima.model import ARIMA from pmdarima import auto_arima # p = ordre AR (autorégressif) : dépendance sur les valeurs passées # d = ordre d intégration : nombre de différenciations # q = ordre MA (moyenne mobile) : dépendance sur les erreurs passées # Auto-sélection des paramètres model_auto = auto_arima( df['revenue'], seasonal=True, m=52, # périodicité (52 semaines) stepwise=True, information_criterion='aic' ) print(model_auto.summary()) # ARIMA manuel model = ARIMA(df['revenue'], order=(2, 1, 1)) fitted = model.fit() predictions = fitted.forecast(steps=12) # 12 prochains pas

4Prophet : prédiction pratique

Question discriminante

Pourquoi Prophet est-il souvent préféré à ARIMA pour les séries temporelles business ?

from prophet import Prophet import pandas as pd # Format Prophet : colonnes 'ds' (date) et 'y' (valeur) df_prophet = df.reset_index().rename(columns={'date': 'ds', 'revenue': 'y'}) model = Prophet( seasonality_mode='multiplicative', # si saisonnalité proportionnelle yearly_seasonality=True, weekly_seasonality=True, daily_seasonality=False, changepoint_prior_scale=0.05 # flexibilité du trend ) # Ajouter des jours fériés model.add_country_holidays(country_name='FR') # Ajouter une saisonnalité custom model.add_seasonality(name='quarterly', period=91.25, fourier_order=5) model.fit(df_prophet) future = model.make_future_dataframe(periods=52, freq='W') forecast = model.predict(future)
  • Prophet vs ARIMA — Prophet gère automatiquement les jours fériés, les changements de trend, les saisonnalités multiples. Plus robuste sur les données business
  • Limitation — moins performant sur les séries avec forte autocorrélation ou structures complexes

5Détection d anomalies temporelles

Question discriminante

Comment détectez-vous des anomalies dans une série temporelle ?

import numpy as np from sklearn.ensemble import IsolationForest # Méthode 1 : Z-score sur la série différenciée df['diff'] = df['revenue'].diff() df['z_score'] = (df['diff'] - df['diff'].mean()) / df['diff'].std() anomalies_z = df[df['z_score'].abs() > 3] # Méthode 2 : Prophet residuals forecast = model.predict(df_prophet) df_prophet['yhat'] = forecast['yhat'] df_prophet['residual'] = df_prophet['y'] - df_prophet['yhat'] threshold = df_prophet['residual'].std() * 3 anomalies_prophet = df_prophet[df_prophet['residual'].abs() > threshold] # Méthode 3 : Isolation Forest multivarié features = df[['revenue', 'volume', 'avg_basket']].values iso = IsolationForest(contamination=0.02, random_state=42) df['anomaly'] = iso.fit_predict(features) # -1 = anomalie

6Features temporelles pour les modèles ML

Question discriminante

Comment encodez-vous le temps pour des modèles ML non-séries-temporelles ?

  • Lag features — valeur à t-1, t-7, t-30 (hier, semaine passée, mois passé)
  • Rolling statistics — moyenne glissante, écart-type glissant, min/max sur N jours
  • Encodage cyclique — sin/cos pour le mois, le jour de la semaine (évite la discontinuité 12→1)
  • Features calendaires — is_weekend, is_holiday, day_of_week, quarter, is_month_end
  • Différences — croissance vs période précédente (revenue_t / revenue_t-1 - 1)
import pandas as pd from statsmodels.tsa.statespace.sarimax import SARIMAX from prophet import Prophet from sklearn.metrics import mean_absolute_percentage_error # ARIMA/SARIMA pour les séries saisonnières model_sarima = SARIMAX(train, order=(1,1,1), seasonal_order=(1,1,1,7)) # saisonnalité hebdomadaire results = model_sarima.fit() forecast = results.forecast(steps=30) # Prophet : simple, robuste aux données manquantes df_prophet = train.reset_index().rename(columns={"date": "ds", "sales": "y"}) m = Prophet(seasonality_mode="multiplicative", weekly_seasonality=True, yearly_seasonality=True) m.add_country_holidays(country_name="FR") m.fit(df_prophet) future = m.make_future_dataframe(periods=30) forecast = m.predict(future) # Évaluation mape = mean_absolute_percentage_error(test, forecast[-len(test):]) print(f"MAPE: {mape:.2%}") # Détection d'anomalies sur séries temporelles from pyod.models.iforest import IForest detector = IForest(contamination=0.01) detector.fit(X_train_features) anomalies = detector.predict(X_test_features) # 1 = anomalie
  • Stationnarité — ARIMA nécessite une série stationnaire. Test ADF (Augmented Dickey-Fuller) pour vérifier. Différenciation (d=1 ou d=2) pour la rendre stationnaire
  • Prophet — Facebook Prophet : décomposition trend + seasonality + holidays. Robuste aux données manquantes et aux outliers. Idéal pour les équipes non-statisticiennes
  • Cross-validation temporelle — ne jamais mélanger le passé et le futur dans le split train/test. Utiliser TimeSeriesSplit de sklearn ou la CV walk-forward
  • Features lag — les features lag (ventes J-7, J-14, J-28) sont souvent les plus prédictives. Ajouter des rolling mean et std sur différentes fenêtres
  • MAPE vs MAE — MAPE en % (facile à expliquer business). MAE en unités absolues (plus robuste aux séries proches de 0). Utiliser les deux selon le contexte
  • Stationnarite - ARIMA necessite une serie stationnaire. Test ADF (Augmented Dickey-Fuller) pour verifier. Diferenciation (d=1 ou d=2) pour la rendre stationnaire
  • Prophet - Facebook Prophet : decomposition trend + seasonality + holidays. Robuste aux donnees manquantes et outliers. Ideal pour les equipes non-statisticiennes
  • Cross-validation temporelle - ne jamais melanger le passe et le futur dans le split train/test. Utiliser TimeSeriesSplit de sklearn ou la CV walk-forward
  • Features lag - les features lag (ventes J-7, J-14, J-28) sont souvent les plus predictives. Ajouter des rolling mean et std sur differentes fenetres
  • MAPE vs MAE - MAPE en % (facile a expliquer business). MAE en unites absolues (plus robuste aux series proches de 0). Utiliser les deux selon le contexte

7Grille par niveau

NiveauMaitriseSignal GONO-GO
ConfirméDécomposition, stationnarité, Prophet basiqueTeste la stationnarité avant ARIMA, a utilisé ProphetApplique KFold aléatoire à une série temporelle
SeniorARIMA tuning, détection d anomalies, features temporelles pour MLChoisit entre ARIMA et Prophet selon le contexte, détecte les anomaliesNe sait pas ce qu est la stationnarité

Vous recrutez un Data Scientist ?

Premier entretien gratuit. Rapport GO/NO-GO sous 48h.