Inflation Forecast 1707125827

Vous aimerez peut-être aussi

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 22

The Box-Jenkins method

# importation des packages


import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

import warnings
warnings.filterwarnings('ignore')

from statsmodels.tsa.stattools import adfuller


from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.stattools import acf, pacf
from statsmodels.tsa.arima_model import ARIMA

df = pd.read_csv('US_inflation_rates.csv')

df.tail()

date value
913 2023-02-01 301.648
914 2023-03-01 301.808
915 2023-04-01 302.918
916 2023-05-01 303.294
917 2023-06-01 303.841

df.rename(columns={'value':'inflation'},inplace=True)

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 918 entries, 0 to 917
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 918 non-null object
1 inflation 918 non-null float64
dtypes: float64(1), object(1)
memory usage: 14.5+ KB

from datetime import datetime


df['date']= pd.to_datetime(df['date'],infer_datetime_format=True)

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 918 entries, 0 to 917
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 918 non-null datetime64[ns]
1 inflation 918 non-null float64
dtypes: datetime64[ns](1), float64(1)
memory usage: 14.5 KB

df.set_index('date',inplace=True)

df

inflation
date
1947-01-01 21.480
1947-02-01 21.620
1947-03-01 22.000
1947-04-01 22.000
1947-05-01 21.950
... ...
2023-02-01 301.648
2023-03-01 301.808
2023-04-01 302.918
2023-05-01 303.294
2023-06-01 303.841

[918 rows x 1 columns]

# vèrification des valeurs manquantes


df.isnull().sum()

inflation 0
dtype: int64

Identification du modèle
Analyse des donnèes
# affichage du graphique

plt.figure(figsize=(10,6))
plt.plot(df.index,df['inflation'], color='blue')
plt.title('Evolution de inflation')
plt.xlabel('date')
plt.ylabel('IPC')
plt.grid(True)
plt.show

<function matplotlib.pyplot.show(close=None, block=None)>


from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# création des subplots
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))

# ACF
plot_acf(df['inflation'], lags=30, zero=True, ax=ax1)
ax1.set_title('ACF - sèrie inflation')
ax1.set_xlabel('Lag')
ax1.set_ylabel('Corrélation')
ax1.grid(True)
ax1.set_xticks(np.arange(0, 31, 1))

# PACF
plot_pacf(df['inflation'], lags=30, zero=True, ax=ax2)
ax2.set_title('PACF - sèrie inflation')
ax2.set_xlabel('Lag')
ax2.set_ylabel('Corrélation partielle')
ax2.grid(True)
ax2.set_xticks(np.arange(0, 31, 1))

# ajustement des subplots


plt.tight_layout()
plt.show()
# Analyse de la stationnarité de la variable
from statsmodels.tsa.stattools import adfuller
from tabulate import tabulate

# Effectuer le test de Dickey-Fuller augmenté


result = adfuller(df)

# Formater les résultats dans un tableau


table = [
['Valeur de test', result[0]],
['P-valeur', result[1]],
['Conclusion', 'La série est stationnaire' if result[1] < 0.05
else 'La série est non stationnaire']
]

# Afficher les résultats sous forme de tableau


print(tabulate(table, headers=['Métrique', 'Valeur'],
tablefmt='github'))
| Métrique | Valeur |
|----------------|-------------------------------|
| Valeur de test | 2.6788674500166874 |
| P-valeur | 0.9990856107806778 |
| Conclusion | La série est non stationnaire |

# Effectuer la décomposition saisonnière


decomposition = seasonal_decompose(df['inflation'], model='additive')

# Extraction des composantes de la décomposition


trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid

# Affichage des composantes de la décomposition


plt.figure(figsize=(12, 8))

plt.subplot(411)
plt.plot(df['inflation'], label='Série originale')
plt.legend(loc='best')

plt.subplot(412)
plt.plot(trend, label='Tendance')
plt.legend(loc='best')

plt.subplot(413)
plt.plot(seasonal, label='Saisonnalité')
plt.legend(loc='best')

plt.subplot(414)
plt.plot(residual, label='Résidus')
plt.legend(loc='best')

plt.tight_layout()
plt.show()
# Différenciation pour rendre la série stationnaire
differenced = df['inflation'].diff().dropna()

# Affichage de la série différienciée


plt.figure(figsize=(10, 6))
plt.plot(differenced)
plt.title('Série temporelle différienciée (inflation)')
plt.xlabel('Date')
plt.ylabel('Différence')
plt.grid(True)
plt.show()
# Créer les subplots
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))

# Tracer l'ACF
plot_acf(differenced, lags=30, zero=True, ax=ax1)
ax1.set_title('ACF - sèrie inflation')
ax1.set_xlabel('Lag')
ax1.set_ylabel('Corrélation')
ax1.grid(True)

# Ajuster les graduations sur l'axe x pour l'ACF


ax1.set_xticks(np.arange(0, 31, 1))

# Tracer le PACF
plot_pacf(differenced, lags=30, zero=True, ax=ax2)
ax2.set_title('PACF - sèrie inflation')
ax2.set_xlabel('Lag')
ax2.set_ylabel('Corrélation partielle')
ax2.grid(True)

# Ajuster les graduations sur l'axe x pour le PACF


ax2.set_xticks(np.arange(0, 31, 1))

# Ajuster les subplots


plt.tight_layout()
# Afficher le graphique
plt.show()

# Analyse de la stationnarité de la variable


from statsmodels.tsa.stattools import adfuller
from tabulate import tabulate

# Effectuer le test de Dickey-Fuller augmenté


result = adfuller(differenced)

# Formater les résultats dans un tableau


table = [
['Valeur de test', result[0]],
['P-valeur', result[1]],
['Conclusion', 'La série est stationnaire' if result[1] < 0.05
else 'La série est non stationnaire']
]
# Afficher les résultats sous forme de tableau
print(tabulate(table, headers=['Métrique', 'Valeur'],
tablefmt='github'))

| Métrique | Valeur |
|----------------|---------------------------|
| Valeur de test | -3.5827298316483045 |
| P-valeur | 0.006099910514823511 |
| Conclusion | La série est stationnaire |

# identification de l'ordre p d et q
p= 1
d= 1
q=1,3

# Séparer les données en ensemble d'entraînement et ensemble de test


train_data = df['inflation'][:-101]
test_data = df['inflation'][-101:]

from statsmodels.tsa.arima.model import ARIMA

# Créer un modèle ARIMA(1,2,1)


model = ARIMA(train_data, order=(1,2,1))

# Ajuster le modèle
model_fit = model.fit()

# Afficher le résumé du modèle


print(model_fit.summary())

SARIMAX Results

======================================================================
========
Dep. Variable: inflation No. Observations:
817
Model: ARIMA(1, 2, 1) Log Likelihood
-220.011
Date: Mon, 08 Jan 2024 AIC
446.022
Time: 17:01:18 BIC
460.132
Sample: 01-01-1947 HQIC
451.438
- 01-01-2015

Covariance Type: opg

======================================================================
========
coef std err z P>|z| [0.025
0.975]
----------------------------------------------------------------------
--------
ar.L1 0.4706 0.014 32.678 0.000 0.442
0.499
ma.L1 -0.9768 0.008 -126.837 0.000 -0.992
-0.962
sigma2 0.1002 0.002 48.348 0.000 0.096
0.104
======================================================================
=============
Ljung-Box (L1) (Q): 4.62 Jarque-Bera (JB):
15605.24
Prob(Q): 0.03 Prob(JB):
0.00
Heteroskedasticity (H): 35.74 Skew:
-1.73
Prob(H) (two-sided): 0.00 Kurtosis:
24.16
======================================================================
=============

Warnings:
[1] Covariance matrix calculated using the outer product of gradients
(complex-step).

from statsmodels.stats.diagnostic import acorr_ljungbox


from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.pyplot as plt
import seaborn as sns

# Calculer les résidus


residuals = model_fit.resid

# Tracer l'ACF des résidus


plt.figure(figsize=(10, 5))
plot_acf(residuals, lags=30, zero=False)
plt.title("Autocorrelogram of Residuals")
plt.show()

# Tracer la PACF des résidus


plt.figure(figsize=(10, 5))
plot_pacf(residuals, lags=30, zero=False)
plt.title("Partial Autocorrelogram of Residuals")
plt.show()

<Figure size 1000x500 with 0 Axes>


<Figure size 1000x500 with 0 Axes>
prédiction
from sklearn.metrics import mean_absolute_error, mean_squared_error,
r2_score
# Prédictions sur l'ensemble d'entraînement
train_predictions = model_fit.predict(start=train_data.index[0],
end=train_data.index[-1])

# Prédictions sur l'ensemble de test


test_predictions = model_fit.predict(start=test_data.index[0],
end=test_data.index[-1])

# Prédictions sur l'ensemble d'entraînement


train_predictions = model_fit.predict(start=train_data.index[0],
end=train_data.index[-1])

# Prédictions sur l'ensemble de test


test_predictions = model_fit.predict(start=test_data.index[0],
end=test_data.index[-1])

# Tracer les prédictions et les données réelles avec les courbes


collées
plt.figure(figsize=(10, 6))
plt.plot(train_data.index, train_data.values, label='Ensemble
d\'entraînement', color='blue')
plt.plot(test_data.index, test_data.values, label='Ensemble de test
(réel)', color='blue', linestyle='--')
plt.plot(train_predictions.index, train_predictions,
label='Prédictions (Entraînement)', color='red')
plt.plot(test_predictions.index, test_predictions, label='Prédictions
(Test)', color='green')

# Définir les limites des axes x et y pour une continuité visuelle


plt.xlim(train_data.index[0], test_data.index[-1])
plt.ylim(min(train_data.min(), test_data.min()), max(train_data.max(),
test_data.max()))

plt.xlabel('Date')
plt.ylabel('inflation')
plt.title('Prédictions du modèle ARIMA')
plt.legend()
plt.show()

# Mesures de performance sur l'ensemble d'entraînement


train_mae = mean_absolute_error(train_data, train_predictions)
train_mse = mean_squared_error(train_data, train_predictions)
train_rmse = mean_squared_error(train_data, train_predictions,
squared=False)
train_r2 = r2_score(train_data, train_predictions)

# Mesures de performance sur l'ensemble de test


test_mae = mean_absolute_error(test_data, test_predictions)
test_mse = mean_squared_error(test_data, test_predictions)
test_rmse = mean_squared_error(test_data, test_predictions,
squared=False)
test_r2 = r2_score(test_data, test_predictions)

# Créer un DataFrame pour afficher les mesures de performance


performance_df = pd.DataFrame({
'Métrique': ['MAE', 'MSE', 'RMSE', 'R²'],
'Ensemble d\'entraînement': [train_mae, train_mse, train_rmse,
train_r2],
'Ensemble de test': [test_mae, test_mse, test_rmse, test_r2]
})

print(performance_df)

Métrique Ensemble d'entraînement Ensemble de test


0 MAE 0.215012 14.977569
1 MSE 0.802306 423.982721
2 RMSE 0.895715 20.590841
3 R² 0.999841 -0.065662

Modèle automatique
import pmdarima as pm

# Séparer les données en ensemble d'entraînement et ensemble de test


train_data = df['inflation'][:-200]
test_data = df['inflation'][-200:]

# Utiliser auto_arima pour trouver le meilleur modèle ARIMA


model = pm.auto_arima(train_data)

print(model.summary())

SARIMAX Results

======================================================================
========
Dep. Variable: y No. Observations:
718
Model: SARIMAX(2, 2, 1) Log Likelihood
39.909
Date: Mon, 08 Jan 2024 AIC
-71.817
Time: 17:01:24 BIC
-53.523
Sample: 01-01-1947 HQIC
-64.753
- 10-01-2006

Covariance Type: opg

======================================================================
========
coef std err z P>|z| [0.025
0.975]
----------------------------------------------------------------------
--------
ar.L1 0.3124 0.023 13.498 0.000 0.267
0.358
ar.L2 -0.2954 0.022 -13.698 0.000 -0.338
-0.253
ma.L1 -0.8716 0.020 -43.165 0.000 -0.911
-0.832
sigma2 0.0523 0.001 53.905 0.000 0.050
0.054
======================================================================
=============
Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB):
7942.50
Prob(Q): 0.98 Prob(JB):
0.00
Heteroskedasticity (H): 14.88 Skew:
0.24
Prob(H) (two-sided): 0.00 Kurtosis:
19.31
======================================================================
=============

Warnings:
[1] Covariance matrix calculated using the outer product of gradients
(complex-step).

# Ajuster le modèle aux données


model.fit(train_data)
# Obtenir les résidus du modèle
residuals = model.resid()

# Tracer la fonction d'autocorrélation (ACF) des résidus


plot_acf(residuals, lags=20)
plt.xlabel('Lag')
plt.ylabel('Autocorrelation')
plt.title('ACF des résidus')
plt.show()
# Tracer la fonction d'autocorrélation partielle (PACF) des résidus
plot_pacf(residuals, lags=20)
plt.xlabel('Lag')
plt.ylabel('Partial Autocorrelation')
plt.title('PACF des résidus')
plt.show()
# Faire des prédictions sur l'ensemble d'entraînement
train_pred, train_confint =
model.predict_in_sample(return_conf_int=True)

# Faire des prédictions sur l'ensemble de test


n_periods = len(test_data)
predicted, confint = model.predict(n_periods=n_periods,
return_conf_int=True)

# Concaténer les prédictions pour l'ensemble d'entraînement et de test


all_predictions = pd.concat([pd.Series(train_pred,
index=train_data.index),
pd.Series(predicted,
index=test_data.index)],
axis=0)

# Tracer les valeurs réelles et les prédictions pour l'ensemble


d'entraînement et de test
plt.figure(figsize=(12, 6))
plt.plot(train_data, label='Observed Training', color='blue')
plt.plot(test_data, label='Observed Test', color='green')
plt.plot(all_predictions, label='Predicted', color='red')
plt.xlabel('Date')
plt.ylabel('inflation')
plt.title('Observed vs Predicted inflation')
plt.legend()
plt.grid(True)
plt.show()

# Calculer les mesures de performance sur l'ensemble d'entraînement


train_mae = mean_absolute_error(train_data, train_pred)
train_mse = mean_squared_error(train_data, train_pred)
train_rmse = mean_squared_error(train_data, train_pred, squared=False)
train_r2 = r2_score(train_data, train_pred)

# Calculer les mesures de performance sur l'ensemble de test


test_mae = mean_absolute_error(test_data, predicted)
test_mse = mean_squared_error(test_data, predicted)
test_rmse = mean_squared_error(test_data, predicted, squared=False)
test_r2 = r2_score(test_data, predicted)

# Créer un DataFrame pour afficher les mesures de performance


performance_df = pd.DataFrame({
'Métrique': ['MAE', 'MSE', 'RMSE', 'R²'],
'Ensemble d\'entraînement': [train_mae, train_mse, train_rmse,
train_r2],
'Ensemble de test': [test_mae, test_mse, test_rmse, test_r2]
})

print(performance_df)
Métrique Ensemble d'entraînement Ensemble de test
0 MAE 0.183745 5.485333
1 MSE 0.851302 99.367903
2 RMSE 0.922660 9.968345
3 R² 0.999749 0.833563

# comparaison manuelle des résultats du modèle


target_date = '2006-11-01'

prediction = model.predict(start=target_date, end=target_date,


return_conf_int=False)

comparison_data = pd.DataFrame(index=[pd.to_datetime(target_date)],
columns=['ActualInflation', 'PredictedInflation'])
comparison_data['ActualInflation'] = df.loc[target_date, 'inflation']
comparison_data['PredictedInflation'] = prediction

print(comparison_data)

ActualInflation PredictedInflation
2006-11-01 202.0 202.240288

print("Last date in training data:", df.index[-1])

# Print the model summary


print(model.summary())

Last date in training data: 2023-06-01 00:00:00


SARIMAX Results

======================================================================
========
Dep. Variable: y No. Observations:
718
Model: SARIMAX(2, 2, 1) Log Likelihood
39.909
Date: Mon, 08 Jan 2024 AIC
-71.817
Time: 17:01:25 BIC
-53.523
Sample: 01-01-1947 HQIC
-64.753
- 10-01-2006

Covariance Type: opg

======================================================================
========
coef std err z P>|z| [0.025
0.975]
----------------------------------------------------------------------
--------
ar.L1 0.3124 0.023 13.498 0.000 0.267
0.358
ar.L2 -0.2954 0.022 -13.698 0.000 -0.338
-0.253
ma.L1 -0.8716 0.020 -43.165 0.000 -0.911
-0.832
sigma2 0.0523 0.001 53.905 0.000 0.050
0.054
======================================================================
=============
Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB):
7942.50
Prob(Q): 0.98 Prob(JB):
0.00
Heteroskedasticity (H): 14.88 Skew:
0.24
Prob(H) (two-sided): 0.00 Kurtosis:
19.31
======================================================================
=============

Warnings:
[1] Covariance matrix calculated using the outer product of gradients
(complex-step).

result = model.fit(test_data)
print(result.summary())

SARIMAX Results

======================================================================
========
Dep. Variable: y No. Observations:
200
Model: SARIMAX(2, 2, 1) Log Likelihood
-192.689
Date: Mon, 08 Jan 2024 AIC
393.378
Time: 17:01:25 BIC
406.531
Sample: 11-01-2006 HQIC
398.702
- 06-01-2023

Covariance Type: opg

======================================================================
========
coef std err z P>|z| [0.025
0.975]
----------------------------------------------------------------------
--------
ar.L1 0.5459 0.055 9.983 0.000 0.439
0.653
ar.L2 -0.1143 0.063 -1.819 0.069 -0.237
0.009
ma.L1 -0.9353 0.024 -38.356 0.000 -0.983
-0.887
sigma2 0.4073 0.027 15.354 0.000 0.355
0.459
======================================================================
=============
Ljung-Box (L1) (Q): 0.01 Jarque-Bera (JB):
193.28
Prob(Q): 0.93 Prob(JB):
0.00
Heteroskedasticity (H): 1.05 Skew:
-1.10
Prob(H) (two-sided): 0.85 Kurtosis:
7.31
======================================================================
=============

Warnings:
[1] Covariance matrix calculated using the outer product of gradients
(complex-step).

# crèation des dates futures


future_dates = pd.date_range(start=df.index[-1], periods=10, freq='M')

forecast = result.predict(start=df.index[-1], end=len(df) + 99,


typ='levels')

forecast_df = pd.DataFrame({'date': future_dates, 'Forecast':


forecast})

print(forecast_df)

date Forecast
2023-07-01 2023-06-30 304.708797
2023-08-01 2023-07-31 305.732176
2023-09-01 2023-08-31 306.803824
2023-10-01 2023-09-30 307.884039
2023-11-01 2023-10-31 308.963415
2023-12-01 2023-11-30 310.041352
2024-01-01 2023-12-31 311.118601
2024-02-01 2024-01-31 312.195638
2024-03-01 2024-02-29 313.272638
2024-04-01 2024-03-31 314.349643
observed_line, = plt.plot(df.index, df['inflation'], label='Observed
Data', color='blue')

forecast_line, = plt.plot(forecast_df['date'],
forecast_df['Forecast'], label='Forecast', linestyle='dashed',
color='red')

plt.xlabel('Date')
plt.ylabel('inflation')
plt.title('Observed Data and Forecast')

plt.show()

Vous aimerez peut-être aussi