Introduction
Le module prophet de Facebook permet de modeliser des series temporelles de maniere pragmatique :
- modelisation ‘a la scikit-learn’ en 2 lignes
- plusieurs saisonnalites disponibles (jour, semaine, annee)
- tendance lineaire par morceaux (et pas seulement …)
- possibilite de definir des journees de conges qui affectent la serie
- plusieurs sorties graphiques dont des intervalles de confiance pour la prevision
- on peut ajouter des predicteurs supplementaires
- gestion des valeurs manquantes, la documentation suggere meme de remplacer les valeurs atypiques par des valeurs manquantes : https://facebook.github.io/prophet/docs/outliers.html
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 :
- https://facebook.github.io/prophet/docs/quick_start.html#python-api
- https://cran.r-project.org/web/packages/prophet/prophet.pdf#page.14. En repassant sous Python, ne pas oublier de remplacer les ‘.’ par des ’_’.
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
'display.max_columns', None)
pd.set_option(
import math
import sys
import pkg_resources
import os
from os import path
import matplotlib.pyplot as plt
import seaborn as sns
set()
sns.
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'
'QT_QPA_PLATFORM_PLUGIN_PATH'] = 'C:/Users/Sebastien/Anaconda3/envs/env_prophet/Library/plugins/platforms'
os.environ[".") os.chdir(
Les versions Python et prophet utilisees.
sys.version# prophet.__version__
'prophet').version pkg_resources.get_distribution(
'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.
= data.frame(AirPassengers)
donnees_r
= as.character(1:12)
mois nchar(mois) == 1] = paste0('0', mois[nchar(mois) == 1])
mois["Month"] = c(sapply(1949:1960, \(x) paste(x, mois, sep = "-")))
donnees_r[= donnees_r[c("Month", "AirPassengers")] donnees_r
On met la serie au format attendu par prophet : une colonne ds de datetimes et une colonne y numerique.
= r.donnees_r
donnees "Month"] = pd.to_datetime(donnees["Month"] + "-01")
donnees[= {'Month': 'ds', 'AirPassengers':'y'}, inplace = True)
donnees.rename(columns = True);
donnees.reset_index(drop 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.
= 12
periode = sm.tsa.seasonal_decompose(donnees.y, model='multiplicative', period = 12)
decomposition
decomposition.plot() plt.show()
Modelisation
On cree une colonne train / test : l’apprentissage correspond a donnees.partition == True
.
"partition"] = pd.Series(donnees.index) <= 0.6 * len(donnees)
donnees["partition"].value_counts() donnees[
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.
= Prophet(yearly_seasonality = True,
model = 'multiplicative',
seasonality_mode = 3,
n_changepoints = 0.03,
changepoint_prior_scale = 0.1)
seasonality_prior_scale 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.
= model.predict(donnees[["ds"]])
prev "partition"] = donnees["partition"]
prev["y"] = donnees["y"] prev[
Graphique sur l’echantillon test.
~prev.partition, ["y", "yhat"]].plot(colormap = "viridis");
prev.loc[ 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.
"y", "yhat_lower", "yhat_upper", "yhat",]].plot(colormap = "viridis");
prev[[ 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= model.plot(prev)
fig ;
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()