|
3 weeks ago | |
---|---|---|
.. | ||
solution | 3 weeks ago | |
working | 3 weeks ago | |
README.md | 3 weeks ago | |
assignment.md | 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.
🎥 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.
-
Rulează notebook-ul pentru a încărca biblioteca Python
statsmodels
; vei avea nevoie de aceasta pentru modelele ARIMA. -
Încarcă bibliotecile necesare.
-
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
-
Încarcă datele din fișierul
/data/energy.csv
într-un dataframe Pandas și analizează-le:energy = load_data('./data')[['load']] energy.head(10)
-
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.
-
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.
-
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()
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.
-
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)
-
Scalează datele pentru a fi în intervalul (0, 1).
scaler = MinMaxScaler() train['load'] = scaler.fit_transform(train) train.head(10)
-
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()
Datele originale
Datele scalate
-
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:
- Definește modelul apelând
SARIMAX()
și trecând parametrii modelului: parametrii p, d și q, și parametrii P, D și Q. - Pregătește modelul pentru datele de antrenare apelând funcția
fit()
. - 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
șiQ
, care descriu aceleași asocieri cap
,d
șiq
, dar corespund componentelor sezoniere ale modelului.
-
Î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 bibliotecapyramid
. -
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.
-
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.
-
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]
-
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 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
-
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())
-
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 %
-
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.
-
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 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ă
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.