Introduction

Le module prophet de Facebook permet de modeliser des series temporelles de maniere pragmatique :

L’installation du module necessite la dependance PyStan, cf les documents officiels :

Pour une introduction a prophet et une description precise des fonctions, de leurs arguments et de leurs valeurs par defaut :

library("reticulate")

# on a installe prophet dans l'environnement vituel conda "env_prophet"
use_condaenv(condaenv = "env_prophet", required = TRUE)

Modules

import numpy as np
import pandas as pd
pd.set_option('display.max_columns', None)

import math
import sys
import pkg_resources
import os
from os import path

import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

from sklearn.metrics import mean_squared_error
import statsmodels.api as sm

from prophet import Prophet
from prophet.plot import plot_plotly, add_changepoints_to_plot

# pour regler un bug graphique assez courant avec Anaconda, 
# adapter le chemin vers le dossier 'plugins/platforms'
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = 'C:/Users/Sebastien/Anaconda3/envs/env_prophet/Library/plugins/platforms'
os.chdir(".")

Les versions Python et prophet utilisees.

sys.version
# prophet.__version__
pkg_resources.get_distribution('prophet').version
'3.9.7 (default, Sep 16 2021, 16:59:28) [MSC v.1916 64 bit (AMD64)]'
'1.0.1'

Description des donnees ‘Airline Passengers’

Il s’agit du nombre mensuel de passagers du secteur aerien de 1949 a 1960.

donnees_r = data.frame(AirPassengers)

mois = as.character(1:12)
mois[nchar(mois) == 1] = paste0('0', mois[nchar(mois) == 1])
donnees_r["Month"] = c(sapply(1949:1960, \(x) paste(x, mois, sep = "-")))
donnees_r = donnees_r[c("Month", "AirPassengers")]

On met la serie au format attendu par prophet : une colonne ds de datetimes et une colonne y numerique.

donnees = r.donnees_r
donnees["Month"] = pd.to_datetime(donnees["Month"] + "-01")
donnees.rename(columns = {'Month': 'ds', 'AirPassengers':'y'}, inplace = True)
donnees.reset_index(drop = True);
donnees
            ds      y
0   1949-01-01  112.0
1   1949-02-01  118.0
2   1949-03-01  132.0
3   1949-04-01  129.0
4   1949-05-01  121.0
..         ...    ...
139 1960-08-01  606.0
140 1960-09-01  508.0
141 1960-10-01  461.0
142 1960-11-01  390.0
143 1960-12-01  432.0

[144 rows x 2 columns]

La serie est clairement multiplicative avec une saisonnalite de periode 12. La tendance est lineaire avec plusieurs changements de pente.

periode = 12
decomposition = sm.tsa.seasonal_decompose(donnees.y, model='multiplicative', period = 12)
decomposition.plot()
plt.show()

Modelisation

On cree une colonne train / test : l’apprentissage correspond a donnees.partition == True.

donnees["partition"] = pd.Series(donnees.index) <= 0.6 * len(donnees)
donnees["partition"].value_counts()
True     87
False    57
Name: partition, dtype: int64

Parametrage et entrainement du modele

On indique que la serie est multiplicative avec une saisonnalite annuelle, on suggere 3 points de changements de tendance et on rend les tendances et saisonnalite moins flexibles qu’avec les valeurs par defaut.

model = Prophet(yearly_seasonality = True, 
                seasonality_mode = 'multiplicative', 
                n_changepoints = 3, 
                changepoint_prior_scale = 0.03,  
                seasonality_prior_scale = 0.1)
model.fit(donnees[donnees.partition])
<prophet.forecaster.Prophet object at 0x0000000035D528B0>

INFO:prophet:Disabling weekly seasonality. Run prophet with weekly_seasonality=True to override this.
INFO:prophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.

Qualite de la prevision

On applique le modele a tout le jeu de donnees.

prev = model.predict(donnees[["ds"]])
prev["partition"] = donnees["partition"]
prev["y"] = donnees["y"]

Graphique sur l’echantillon test.

prev.loc[~prev.partition, ["y", "yhat"]].plot(colormap = "viridis");
plt.show()

Valeur du RMSE :

int(mean_squared_error(prev.yhat[~prev.partition], prev.y[~prev.partition])**1/2)
227

Intervalles de confiance des previsions sur toutes les donnees.

prev[["y",  "yhat_lower", "yhat_upper", "yhat",]].plot(colormap = "viridis");
plt.show()

Sorties graphiques de prophet

Qualite du modele sur l’echantillon d’apprentissage.

model.plot(prev[prev.partition])
plt.show()

Tendance et saisonnalite sur toutes les donnees.

model.plot_components(prev)
plt.show()

Les changements de regime de la tendance, le modele n’a finalemet retenu que 2 des 3 points detectes.

model.changepoints
fig = model.plot(prev)
add_changepoints_to_plot(fig.gca(), model, prev);
plt.show()
23   1950-12-01
45   1952-10-01
68   1954-09-01
Name: ds, dtype: datetime64[ns]

Version interactive sur toutes les donnees avec plotly.

plot_plotly(model, prev)
plt.show()

retour au debut du document