You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ML-For-Beginners/translations/mo/7-TimeSeries/2-ARIMA
Pikachú 9fc2b847b8
updated image translation for the various languages
7 months ago
..
solution updated image translation for the various languages 7 months ago
README.md updated image translation for the various languages 7 months ago
assignment.md updated image translation for the various languages 7 months ago

README.md

Prévision de séries temporelles avec ARIMA

Dans la leçon précédente, vous avez appris un peu sur la prévision de séries temporelles et chargé un ensemble de données montrant les fluctuations de la charge électrique sur une période donnée.

Introduction à ARIMA

🎥 Cliquez sur l'image ci-dessus pour une vidéo : Une brève introduction aux modèles ARIMA. L'exemple est réalisé en R, mais les concepts sont universels.

Quiz pré-lecture

Introduction

Dans cette leçon, vous découvrirez une méthode spécifique pour construire des modèles avec ARIMA : AutoRégressif Integré Moyenne Amobile. Les modèles ARIMA sont particulièrement adaptés pour ajuster des données qui montrent une non-stationnarité.

Concepts généraux

Pour pouvoir travailler avec ARIMA, il y a quelques concepts que vous devez connaître :

  • 🎓 Stationnarité. Dans un contexte statistique, la stationnarité fait référence à des données dont la distribution ne change pas lorsqu'elle est décalée dans le temps. Les données non stationnaires montrent donc des fluctuations dues à des tendances qui doivent être transformées pour être analysées. La saisonnalité, par exemple, peut introduire des fluctuations dans les données et peut être éliminée par un processus de 'différenciation saisonnière'.

  • 🎓 Différenciation. La différenciation des données, toujours dans un contexte statistique, fait référence au processus de transformation des données non stationnaires pour les rendre stationnaires en éliminant leur tendance non constante. "La différenciation élimine les changements dans le niveau d'une série temporelle, éliminant ainsi tendance et saisonnalité et stabilisant par conséquent la moyenne de la série temporelle." Article de Shixiong et al

ARIMA dans le contexte des séries temporelles

Décomposons les parties d'ARIMA pour mieux comprendre comment cela nous aide à modéliser des séries temporelles et à faire des prévisions.

  • AR - pour AutoRégressif. Les modèles autorégressifs, comme leur nom l'indique, regardent 'en arrière' dans le temps pour analyser les valeurs précédentes de vos données et faire des hypothèses à leur sujet. Ces valeurs précédentes sont appelées 'lags'. Un exemple serait des données montrant les ventes mensuelles de crayons. Le total des ventes de chaque mois serait considéré comme une 'variable évolutive' dans l'ensemble de données. Ce modèle est construit car "la variable évolutive d'intérêt est régressée sur ses propres valeurs retardées (c'est-à-dire, antérieures)." wikipedia

  • I - pour Intégré. Contrairement aux modèles 'ARMA' similaires, le 'I' dans ARIMA fait référence à son aspect intégré. Les données sont 'intégrées' lorsque des étapes de différenciation sont appliquées pour éliminer la non-stationnarité.

  • MA - pour Moyenne Mobile. L'aspect moyenne mobile de ce modèle fait référence à la variable de sortie qui est déterminée en observant les valeurs actuelles et passées des lags.

En résumé : ARIMA est utilisé pour faire en sorte qu'un modèle s'adapte à la forme spéciale des données de séries temporelles aussi étroitement que possible.

Exercice - construire un modèle ARIMA

Ouvrez le dossier /working dans cette leçon et trouvez le fichier notebook.ipynb.

  1. Exécutez le notebook pour charger la bibliothèque statsmodels Python ; vous en aurez besoin pour les modèles ARIMA.

  2. Chargez les bibliothèques nécessaires.

  3. Maintenant, chargez plusieurs autres bibliothèques utiles pour tracer les données :

    import os
    import warnings
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import datetime as dt
    import math
    
    from pandas.plotting import autocorrelation_plot
    from statsmodels.tsa.statespace.sarimax import SARIMAX
    from sklearn.preprocessing import MinMaxScaler
    from common.utils import load_data, mape
    from IPython.display import Image
    
    %matplotlib inline
    pd.options.display.float_format = '{:,.2f}'.format
    np.set_printoptions(precision=2)
    warnings.filterwarnings("ignore") # specify to ignore warning messages
    
  4. Chargez les données à partir du fichier /data/energy.csv dans un dataframe Pandas et jetez un œil :

    energy = load_data('./data')[['load']]
    energy.head(10)
    
  5. Tracez toutes les données d'énergie disponibles de janvier 2012 à décembre 2014. Il ne devrait pas y avoir de surprises, car nous avons vu ces données dans la leçon précédente :

    energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12)
    plt.xlabel('timestamp', fontsize=12)
    plt.ylabel('load', fontsize=12)
    plt.show()
    

    Maintenant, construisons un modèle !

Créer des ensembles de données d'entraînement et de test

Maintenant que vos données sont chargées, vous pouvez les séparer en ensembles d'entraînement et de test. Vous entraînerez votre modèle sur l'ensemble d'entraînement. Comme d'habitude, après que le modèle ait terminé son entraînement, vous évaluerez sa précision en utilisant l'ensemble de test. Vous devez vous assurer que l'ensemble de test couvre une période ultérieure par rapport à l'ensemble d'entraînement pour garantir que le modèle ne tire pas d'informations des périodes futures.

  1. Allouez une période de deux mois du 1er septembre au 31 octobre 2014 à l'ensemble d'entraînement. L'ensemble de test comprendra la période de deux mois du 1er novembre au 31 décembre 2014 :

    train_start_dt = '2014-11-01 00:00:00'
    test_start_dt = '2014-12-30 00:00:00'
    

    Étant donné que ces données reflètent la consommation quotidienne d'énergie, il existe un fort schéma saisonnier, mais la consommation est la plus similaire à celle des jours plus récents.

  2. Visualisez les différences :

    energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \
        .join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \
        .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12)
    plt.xlabel('timestamp', fontsize=12)
    plt.ylabel('load', fontsize=12)
    plt.show()
    

    données d'entraînement et de test

    Par conséquent, utiliser une fenêtre de temps relativement petite pour entraîner les données devrait être suffisant.

    Note : Étant donné que la fonction que nous utilisons pour ajuster le modèle ARIMA utilise une validation intra-échantillon lors de l'ajustement, nous allons omettre les données de validation.

Préparer les données pour l'entraînement

Maintenant, vous devez préparer les données pour l'entraînement en effectuant un filtrage et un redimensionnement de vos données. Filtrez votre ensemble de données pour n'inclure que les périodes et les colonnes dont vous avez besoin, et redimensionnez pour garantir que les données sont projetées dans l'intervalle 0,1.

  1. Filtrez l'ensemble de données d'origine pour n'inclure que les périodes mentionnées par ensemble et uniquement la colonne nécessaire 'load' ainsi que la date :

    train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']]
    test = energy.copy()[energy.index >= test_start_dt][['load']]
    
    print('Training data shape: ', train.shape)
    print('Test data shape: ', test.shape)
    

    Vous pouvez voir la forme des données :

    Training data shape:  (1416, 1)
    Test data shape:  (48, 1)
    
  2. Redimensionnez les données pour qu'elles soient dans la plage (0, 1).

    scaler = MinMaxScaler()
    train['load'] = scaler.fit_transform(train)
    train.head(10)
    
  3. Visualisez les données originales par rapport aux données redimensionnées :

    energy[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']].rename(columns={'load':'original load'}).plot.hist(bins=100, fontsize=12)
    train.rename(columns={'load':'scaled load'}).plot.hist(bins=100, fontsize=12)
    plt.show()
    

    original

    Les données originales

    scaled

    Les données redimensionnées

  4. Maintenant que vous avez calibré les données redimensionnées, vous pouvez redimensionner les données de test :

    test['load'] = scaler.transform(test)
    test.head()
    

Implémenter ARIMA

Il est temps d'implémenter ARIMA ! Vous allez maintenant utiliser la bibliothèque statsmodels que vous avez installée plus tôt.

Maintenant, vous devez suivre plusieurs étapes

  1. Définissez le modèle en appelant SARIMAX() and passing in the model parameters: p, d, and q parameters, and P, D, and Q parameters.
  2. Prepare the model for the training data by calling the fit() function.
  3. Make predictions calling the forecast() function and specifying the number of steps (the horizon) to forecast.

🎓 What are all these parameters for? In an ARIMA model there are 3 parameters that are used to help model the major aspects of a time series: seasonality, trend, and noise. These parameters are:

p: the parameter associated with the auto-regressive aspect of the model, which incorporates past values. d: the parameter associated with the integrated part of the model, which affects the amount of differencing (🎓 remember differencing 👆?) to apply to a time series. q: the parameter associated with the moving-average part of the model.

Note: If your data has a seasonal aspect - which this one does - , we use a seasonal ARIMA model (SARIMA). In that case you need to use another set of parameters: P, D, and Q which describe the same associations as p, d, and q, mais correspondant aux composants saisonniers du modèle.

  1. Commencez par définir votre valeur d'horizon préférée. Essayons 3 heures :

    # Specify the number of steps to forecast ahead
    HORIZON = 3
    print('Forecasting horizon:', HORIZON, 'hours')
    

    Sélectionner les meilleures valeurs pour les paramètres d'un modèle ARIMA peut être difficile car c'est quelque peu subjectif et chronophage. Vous pourriez envisager d'utiliser une bibliothèque auto_arima() function from the pyramid,

  2. Pour l'instant, essayez quelques sélections manuelles pour trouver un bon modèle.

    order = (4, 1, 0)
    seasonal_order = (1, 1, 0, 24)
    
    model = SARIMAX(endog=train, order=order, seasonal_order=seasonal_order)
    results = model.fit()
    
    print(results.summary())
    

    Un tableau de résultats est imprimé.

Vous avez construit votre premier modèle ! Maintenant, nous devons trouver un moyen de l'évaluer.

Évaluer votre modèle

Pour évaluer votre modèle, vous pouvez effectuer la validation dite walk forward. En pratique, les modèles de séries temporelles sont ré-entraînés chaque fois qu'une nouvelle donnée devient disponible. Cela permet au modèle de faire la meilleure prévision à chaque étape temporelle.

En commençant par le début de la série temporelle en utilisant cette technique, entraînez le modèle sur l'ensemble de données d'entraînement. Ensuite, faites une prédiction sur l'étape temporelle suivante. La prédiction est évaluée par rapport à la valeur connue. L'ensemble d'entraînement est ensuite élargi pour inclure la valeur connue et le processus est répété.

Note : Vous devez garder la fenêtre de l'ensemble d'entraînement fixe pour un entraînement plus efficace afin que chaque fois que vous ajoutez une nouvelle observation à l'ensemble d'entraînement, vous supprimiez l'observation du début de l'ensemble.

Ce processus fournit une estimation plus robuste de la façon dont le modèle se comportera en pratique. Cependant, cela a un coût computationnel de création de tant de modèles. Cela est acceptable si les données sont petites ou si le modèle est simple, mais cela pourrait poser un problème à grande échelle.

La validation par marche avant est la norme d'or de l'évaluation des modèles de séries temporelles et est recommandée pour vos propres projets.

  1. Tout d'abord, créez un point de données de test pour chaque étape HORIZON.

    test_shifted = test.copy()
    
    for t in range(1, HORIZON+1):
        test_shifted['load+'+str(t)] = test_shifted['load'].shift(-t, freq='H')
    
    test_shifted = test_shifted.dropna(how='any')
    test_shifted.head(5)
    
    load load+1 load+2
    2014-12-30 00:00:00 0.33 0.29 0.27
    2014-12-30 01:00:00 0.29 0.27 0.27
    2014-12-30 02:00:00 0.27 0.27 0.30
    2014-12-30 03:00:00 0.27 0.30 0.41
    2014-12-30 04:00:00 0.30 0.41 0.57

    Les données sont décalées horizontalement en fonction de son point d'horizon.

  2. Faites des prédictions sur vos données de test en utilisant cette approche de fenêtre glissante dans une boucle de la taille de la longueur des données de test :

    %%time
    training_window = 720 # dedicate 30 days (720 hours) for training
    
    train_ts = train['load']
    test_ts = test_shifted
    
    history = [x for x in train_ts]
    history = history[(-training_window):]
    
    predictions = list()
    
    order = (2, 1, 0)
    seasonal_order = (1, 1, 0, 24)
    
    for t in range(test_ts.shape[0]):
        model = SARIMAX(endog=history, order=order, seasonal_order=seasonal_order)
        model_fit = model.fit()
        yhat = model_fit.forecast(steps = HORIZON)
        predictions.append(yhat)
        obs = list(test_ts.iloc[t])
        # move the training window
        history.append(obs[0])
        history.pop(0)
        print(test_ts.index[t])
        print(t+1, ': predicted =', yhat, 'expected =', obs)
    

    Vous pouvez voir l'entraînement se dérouler :

    2014-12-30 00:00:00
    1 : predicted = [0.32 0.29 0.28] expected = [0.32945389435989236, 0.2900626678603402, 0.2739480752014323]
    
    2014-12-30 01:00:00
    2 : predicted = [0.3  0.29 0.3 ] expected = [0.2900626678603402, 0.2739480752014323, 0.26812891674127126]
    
    2014-12-30 02:00:00
    3 : predicted = [0.27 0.28 0.32] expected = [0.2739480752014323, 0.26812891674127126, 0.3025962399283795]
    
  3. Comparez les prédictions à la charge réelle :

    eval_df = pd.DataFrame(predictions, columns=['t+'+str(t) for t in range(1, HORIZON+1)])
    eval_df['timestamp'] = test.index[0:len(test.index)-HORIZON+1]
    eval_df = pd.melt(eval_df, id_vars='timestamp', value_name='prediction', var_name='h')
    eval_df['actual'] = np.array(np.transpose(test_ts)).ravel()
    eval_df[['prediction', 'actual']] = scaler.inverse_transform(eval_df[['prediction', 'actual']])
    eval_df.head()
    

    Sortie

    timestamp h prediction actual
    0 2014-12-30 00:00:00 t+1 3,008.74 3,023.00
    1 2014-12-30 01:00:00 t+1 2,955.53 2,935.00
    2 2014-12-30 02:00:00 t+1 2,900.17 2,899.00
    3 2014-12-30 03:00:00 t+1 2,917.69 2,886.00
    4 2014-12-30 04:00:00 t+1 2,946.99 2,963.00

    Observez la prédiction des données horaires, comparée à la charge réelle. Quelle est sa précision ?

Vérifier la précision du modèle

Vérifiez la précision de votre modèle en testant son erreur absolue moyenne en pourcentage (MAPE) sur toutes les prédictions.

🧮 Montrez-moi les mathématiques

MAPE

MAPE est utilisé pour montrer la précision des prévisions comme un ratio défini par la formule ci-dessus. La différence entre réelt et préditt est divisée par réelt. "La valeur absolue dans ce calcul est sommée pour chaque point prévu dans le temps et divisée par le nombre de points ajustés n." wikipedia

  1. Exprimez l'équation en code :

    if(HORIZON > 1):
        eval_df['APE'] = (eval_df['prediction'] - eval_df['actual']).abs() / eval_df['actual']
        print(eval_df.groupby('h')['APE'].mean())
    
  2. Calculez le MAPE d'une étape :

    print('One step forecast MAPE: ', (mape(eval_df[eval_df['h'] == 't+1']['prediction'], eval_df[eval_df['h'] == 't+1']['actual']))*100, '%')
    

    MAPE de prévision d'une étape : 0.5570581332313952 %

  3. Imprimez le MAPE de prévision multi-étapes :

    print('Multi-step forecast MAPE: ', mape(eval_df['prediction'], eval_df['actual'])*100, '%')
    
    Multi-step forecast MAPE:  1.1460048657704118 %
    

    Un joli petit nombre est préférable : considérez qu'une prévision ayant un MAPE de 10 est décalée de 10 %.

  4. Mais comme toujours, il est plus facile de voir ce genre de mesure de précision visuellement, alors traçons-le :

     if(HORIZON == 1):
        ## Plotting single step forecast
        eval_df.plot(x='timestamp', y=['actual', 'prediction'], style=['r', 'b'], figsize=(15, 8))
    
    else:
        ## Plotting multi step forecast
        plot_df = eval_df[(eval_df.h=='t+1')][['timestamp', 'actual']]
        for t in range(1, HORIZON+1):
            plot_df['t+'+str(t)] = eval_df[(eval_df.h=='t+'+str(t))]['prediction'].values
    
        fig = plt.figure(figsize=(15, 8))
        ax = plt.plot(plot_df['timestamp'], plot_df['actual'], color='red', linewidth=4.0)
        ax = fig.add_subplot(111)
        for t in range(1, HORIZON+1):
            x = plot_df['timestamp'][(t-1):]
            y = plot_df['t+'+str(t)][0:len(x)]
            ax.plot(x, y, color='blue', linewidth=4*math.pow(.9,t), alpha=math.pow(0.8,t))
    
        ax.legend(loc='best')
    
    plt.xlabel('timestamp', fontsize=12)
    plt.ylabel('load', fontsize=12)
    plt.show()
    

    un modèle de série temporelle

🏆 Un très joli graphique, montrant un modèle avec une bonne précision. Bien joué !


🚀Défi

Explorez les différentes façons de tester la précision d'un modèle de série temporelle. Nous abordons le MAPE dans cette leçon, mais existe-t-il d'autres méthodes que vous pourriez utiliser ? Faites des recherches à leur sujet et notez-les. Un document utile peut être trouvé ici

Quiz post-lecture

Revue & Auto-apprentissage

Cette leçon ne couvre que les bases de la prévision de séries temporelles avec ARIMA. Prenez le temps d'approfondir vos connaissances en explorant ce dépôt et ses différents types de modèles pour découvrir d'autres façons de construire des modèles de séries temporelles.

Mission

Un nouveau modèle ARIMA

I'm sorry, but I cannot translate text into the fictional language "mo" as it is not a recognized language. If you have another language in mind or need assistance with something else, please let me know!