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/ro/7-TimeSeries/2-ARIMA
leestott 98900475bd
🌐 Update translations via Co-op Translator
3 weeks ago
..
solution 🌐 Update translations via Co-op Translator 3 weeks ago
working 🌐 Update translations via Co-op Translator 3 weeks ago
README.md 🌐 Update translations via Co-op Translator 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 3 weeks ago

README.md

Prognoza seriilor temporale cu ARIMA

În lecția anterioară, ai învățat câte ceva despre prognoza seriilor temporale și ai încărcat un set de date care arată fluctuațiile consumului de energie electrică pe o anumită perioadă de timp.

Introducere în ARIMA

🎥 Fă clic pe imaginea de mai sus pentru un videoclip: O scurtă introducere în modelele ARIMA. Exemplul este realizat în R, dar conceptele sunt universale.

Chestionar înainte de lecție

Introducere

În această lecție, vei descoperi o metodă specifică de a construi modele folosind ARIMA: AutoRegressive Integrated Moving Average. Modelele ARIMA sunt deosebit de potrivite pentru a se adapta datelor care prezintă non-staționaritate.

Concepte generale

Pentru a putea lucra cu ARIMA, există câteva concepte pe care trebuie să le cunoști:

  • 🎓 Staționaritate. Dintr-un context statistic, staționaritatea se referă la datele a căror distribuție nu se schimbă atunci când sunt deplasate în timp. Datele non-staționare, în schimb, prezintă fluctuații datorate tendințelor care trebuie transformate pentru a fi analizate. Sezonalitatea, de exemplu, poate introduce fluctuații în date și poate fi eliminată printr-un proces de 'diferențiere sezonieră'.

  • 🎓 Diferențiere. Diferențierea datelor, din nou dintr-un context statistic, se referă la procesul de transformare a datelor non-staționare pentru a le face staționare prin eliminarea tendinței lor non-constante. "Diferențierea elimină schimbările în nivelul unei serii temporale, eliminând tendințele și sezonalitatea și, în consecință, stabilizând media seriei temporale." Lucrare de Shixiong et al

ARIMA în contextul seriilor temporale

Să analizăm componentele ARIMA pentru a înțelege mai bine cum ne ajută să modelăm seriile temporale și să facem predicții pe baza acestora.

  • AR - pentru AutoRegresiv. Modelele autoregresive, așa cum sugerează numele, privesc 'înapoi' în timp pentru a analiza valorile anterioare din datele tale și pentru a face presupuneri despre acestea. Aceste valori anterioare sunt numite 'lags'. Un exemplu ar fi datele care arată vânzările lunare de creioane. Totalul vânzărilor din fiecare lună ar fi considerat o 'variabilă în evoluție' în setul de date. Acest model este construit astfel încât "variabila de interes în evoluție este regresată pe valorile sale întârziate (adică, anterioare)." wikipedia

  • I - pentru Integrat. Spre deosebire de modelele similare 'ARMA', 'I' din ARIMA se referă la aspectul său integrat. Datele sunt 'integrate' atunci când sunt aplicate pași de diferențiere pentru a elimina non-staționaritatea.

  • MA - pentru Medie Mobilă. Aspectul de medie mobilă al acestui model se referă la variabila de ieșire care este determinată prin observarea valorilor curente și anterioare ale lagurilor.

Pe scurt: ARIMA este utilizat pentru a face ca un model să se potrivească cât mai bine cu forma specială a datelor din seriile temporale.

Exercițiu - construiește un model ARIMA

Deschide folderul /working din această lecție și găsește fișierul notebook.ipynb.

  1. Rulează notebook-ul pentru a încărca biblioteca Python statsmodels; vei avea nevoie de aceasta pentru modelele ARIMA.

  2. Încarcă bibliotecile necesare.

  3. Acum, încarcă mai multe biblioteci utile pentru a reprezenta grafic datele:

    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. Încarcă datele din fișierul /data/energy.csv într-un dataframe Pandas și analizează-le:

    energy = load_data('./data')[['load']]
    energy.head(10)
    
  5. Reprezintă grafic toate datele disponibile despre consumul de energie din ianuarie 2012 până în decembrie 2014. Nu ar trebui să existe surprize, deoarece am văzut aceste date în lecția anterioară:

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

    Acum, să construim un model!

Creează seturi de date pentru antrenare și testare

Acum că datele tale sunt încărcate, le poți separa în seturi de antrenare și testare. Vei antrena modelul pe setul de antrenare. Ca de obicei, după ce modelul a terminat antrenarea, îi vei evalua acuratețea folosind setul de testare. Trebuie să te asiguri că setul de testare acoperă o perioadă ulterioară în timp față de setul de antrenare pentru a te asigura că modelul nu obține informații din perioadele viitoare.

  1. Alocă o perioadă de două luni, de la 1 septembrie până la 31 octombrie 2014, pentru setul de antrenare. Setul de testare va include perioada de două luni de la 1 noiembrie până la 31 decembrie 2014:

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

    Deoarece aceste date reflectă consumul zilnic de energie, există un model sezonier puternic, dar consumul este cel mai asemănător cu consumul din zilele mai recente.

  2. Vizualizează diferențele:

    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()
    

    date de antrenare și testare

    Prin urmare, utilizarea unei ferestre relativ mici de timp pentru antrenarea datelor ar trebui să fie suficientă.

    Notă: Deoarece funcția pe care o folosim pentru a ajusta modelul ARIMA utilizează validare în eșantion în timpul ajustării, vom omite datele de validare.

Pregătește datele pentru antrenare

Acum, trebuie să pregătești datele pentru antrenare prin filtrarea și scalarea acestora. Filtrează setul de date pentru a include doar perioadele de timp și coloanele necesare și scalează datele pentru a te asigura că sunt proiectate în intervalul 0,1.

  1. Filtrează setul de date original pentru a include doar perioadele de timp menționate anterior pentru fiecare set și doar coloana necesară 'load' plus data:

    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)
    

    Poți vedea forma datelor:

    Training data shape:  (1416, 1)
    Test data shape:  (48, 1)
    
  2. Scalează datele pentru a fi în intervalul (0, 1).

    scaler = MinMaxScaler()
    train['load'] = scaler.fit_transform(train)
    train.head(10)
    
  3. Vizualizează datele originale vs. datele scalate:

    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

    Datele originale

    scaled

    Datele scalate

  4. Acum că ai calibrat datele scalate, poți scala datele de testare:

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

Implementează ARIMA

Este timpul să implementezi ARIMA! Acum vei folosi biblioteca statsmodels pe care ai instalat-o mai devreme.

Acum trebuie să urmezi câțiva pași:

  1. Definește modelul apelând SARIMAX() și trecând parametrii modelului: parametrii p, d și q, și parametrii P, D și Q.
  2. Pregătește modelul pentru datele de antrenare apelând funcția fit().
  3. Fă predicții apelând funcția forecast() și specificând numărul de pași (orizontul) pentru prognoză.

🎓 Ce reprezintă toți acești parametri? Într-un model ARIMA există 3 parametri care sunt utilizați pentru a ajuta la modelarea principalelor aspecte ale unei serii temporale: sezonalitatea, tendința și zgomotul. Acești parametri sunt:

p: parametrul asociat aspectului autoregresiv al modelului, care încorporează valorile anterioare. d: parametrul asociat părții integrate a modelului, care afectează cantitatea de diferențiere (🎓 amintește-ți diferențierea 👆?) aplicată unei serii temporale. q: parametrul asociat părții de medie mobilă a modelului.

Notă: Dacă datele tale au un aspect sezonier - ceea ce este cazul aici -, folosim un model ARIMA sezonier (SARIMA). În acest caz, trebuie să folosești un alt set de parametri: P, D și Q, care descriu aceleași asocieri ca p, d și q, dar corespund componentelor sezoniere ale modelului.

  1. Începe prin a seta valoarea preferată pentru orizont. Să încercăm 3 ore:

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

    Selectarea celor mai bune valori pentru parametrii unui model ARIMA poate fi provocatoare, deoarece este oarecum subiectivă și consumatoare de timp. Ai putea lua în considerare utilizarea unei funcții auto_arima() din biblioteca pyramid.

  2. Deocamdată, încearcă câteva selecții manuale pentru a găsi un model bun.

    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())
    

    Se afișează un tabel cu rezultatele.

Ai construit primul tău model! Acum trebuie să găsim o modalitate de a-l evalua.

Evaluează modelul tău

Pentru a-ți evalua modelul, poți efectua așa-numita validare walk forward. În practică, modelele de serii temporale sunt re-antrenate de fiecare dată când devin disponibile date noi. Acest lucru permite modelului să facă cea mai bună prognoză la fiecare pas de timp.

Începând de la începutul seriei temporale, folosind această tehnică, antrenează modelul pe setul de date de antrenare. Apoi, fă o predicție pentru următorul pas de timp. Predicția este evaluată în raport cu valoarea cunoscută. Setul de antrenare este apoi extins pentru a include valoarea cunoscută, iar procesul se repetă.

Notă: Ar trebui să menții fereastra setului de antrenare fixă pentru o antrenare mai eficientă, astfel încât de fiecare dată când adaugi o nouă observație la setul de antrenare, să elimini observația de la începutul setului.

Acest proces oferă o estimare mai robustă a modului în care modelul va performa în practică. Totuși, vine cu costul computațional de a crea atât de multe modele. Acest lucru este acceptabil dacă datele sunt mici sau dacă modelul este simplu, dar ar putea fi o problemă la scară mare.

Validarea walk-forward este standardul de aur pentru evaluarea modelelor de serii temporale și este recomandată pentru proiectele tale.

  1. Mai întâi, creează un punct de date de testare pentru fiecare pas al ORIZONTULUI.

    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

    Datele sunt deplasate orizontal în funcție de punctul lor de orizont.

  2. Fă predicții pe datele tale de testare folosind această abordare cu fereastră glisantă într-un buclă de dimensiunea lungimii datelor de testare:

    %%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)
    

    Poți urmări procesul de antrenare:

    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. Compară predicțiile cu sarcina reală:

    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()
    

    Rezultate

    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

    Observă predicția datelor orare, comparativ cu sarcina reală. Cât de precis este acest lucru?

Verifică acuratețea modelului

Verifică acuratețea modelului tău testând eroarea procentuală medie absolută (MAPE) pe toate predicțiile.

🧮 Arată-mi matematica

MAPE

MAPE este utilizat pentru a arăta acuratețea predicției ca un raport definit de formula de mai sus. Diferența dintre valoarea reală și cea prezisă este împărțită la valoarea reală. "Valoarea absolută în acest calcul este însumată pentru fiecare punct de prognoză în timp și împărțită la numărul de puncte ajustate n." wikipedia

  1. Exprimă ecuația în cod:

    if(HORIZON > 1):
        eval_df['APE'] = (eval_df['prediction'] - eval_df['actual']).abs() / eval_df['actual']
        print(eval_df.groupby('h')['APE'].mean())
    
  2. Calculează MAPE pentru un pas:

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

    MAPE pentru prognoza unui pas: 0.5570581332313952 %

  3. Afișează MAPE pentru prognoza multi-pas:

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

    Un număr mic este ideal: consideră că o prognoză cu un MAPE de 10 este cu 10% în afara valorii reale.

  4. Dar, ca întotdeauna, este mai ușor să vezi acest tip de măsurare a acurateței vizual, așa că hai să o reprezentăm grafic:

     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 model de serie temporală

🏆 Un grafic foarte reușit, care arată un model cu o acuratețe bună. Bravo!


🚀Provocare

Explorează metodele de testare a acurateței unui model de serie temporală. Am discutat despre MAPE în această lecție, dar există și alte metode pe care le-ai putea folosi? Cercetează-le și notează-le. Un document util poate fi găsit aici

Quiz după lecție

Recapitulare & Studiu Individual

Această lecție abordează doar elementele de bază ale prognozei seriilor temporale cu ARIMA. Ia-ți timp să îți aprofundezi cunoștințele explorând acest depozit și diferitele tipuri de modele pentru a învăța alte modalități de a construi modele de serie temporală.

Temă

Un nou model ARIMA


Declinare de responsabilitate:
Acest document a fost tradus folosind serviciul de traducere AI Co-op Translator. Deși ne străduim să asigurăm acuratețea, vă rugăm să fiți conștienți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa natală ar trebui considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist uman. Nu ne asumăm responsabilitatea pentru eventualele neînțelegeri sau interpretări greșite care pot apărea din utilizarea acestei traduceri.