Membuat Model Time Series ARIMA Menggunakan Python


ARIMA
ARIMA atau Auto Regressive Integrated Moving Average adalah model yang banyak dipakai dalam peramalan data time series univariat. Sesuai namanya, model ARIMA terdiri 3 komponen yaitu Auto Regressive (AR), Integrated (I) dan Moving Average (MA) dan dinotasikan sebagai ARIMA(p, d, q).
Komponen p menunjukkan jumlah orde AR pada model. Model AR dapat dikatakan sebagai model regresi dengan peubah penjelasnya adalah data periode sebelumnya. Contoh, nilai p=2 menunjukkan untuk memprediksi data pada waktu ke-t, model menggunakan peubah penjelas yaitu data pada waktu ke-(t-1) dan (t-2).
Komponen d menunjukkan jumlah proses diferensiasi (d). Proses ini perlu dilakukan untuk menangani kondisi non-stasioner (misalnya trend) hingga mencapai stasioner. Nilai d=0 menunjukkan kondisi daata yang sudah stasioner tanpa perlu melakukan proses diferensiasi atau disebut juga model ARMA(p, q).
Komponen terakhir q menunjukkan orde atau lag dari error pada model MA. Nilai q menunjukkan jumlah periode yang digunakan untuk memprediksi error saat ini berdasarkan error periode sebelumnya.
Pemilihan kombinasi yang tepat untuk p, d dan q merupakan bagian penting untuk memperoleh model ARIMA yang optimal. Nilai p dan q umumnya dapat ditentukan dengan melihat plot Autocorrelation function (ACF) dan Partial Autocorrelation Function (PACF). Sementara itu untuk d terdapat uji yang dapat digunakan yaitu uji Augmented Dickey–Fuller (ADF).
Pendekatan lain yang banyak digunakan saat ini khususnya dalam konteks machine learning adalah grid search. Grid search atau dalam penerapan pada beberapa software menggunakan terminologi auto ARIMA adalah proses pencarian model secara iteratif dari berbagai kombinasi nilai p, d dan q. Nilai p, d dan q terbaik ditentukan berdasarkan metrik tertentu seperti AIC atau BIC.
Pada tutorial ini kita akan membuat model ARIMA menggunakan bahasa pemrograman python dengan library statsmodel dan memfokuskan pada penggunaan grid search dalam menentukan orde p, d dan q yang optimal.
Memuat Data Time Series
Contoh yang akan digunakan adalah data ekspor Indonesia periode bulanan selama tahun 2016-2019 (48 bulan). download
Data terdiri dari dua kolom yaitu periode dan nilai_jt_usd. Kita perlu merubah kolom periode sebagai indeks bagi dataframe. Langkah ini dilakukan dengan mengisi nilai parameter parse_dates. Selain itu, kita juga perlu menentukan frekuensi data yang digunakan yaitu bulanan.
Untuk eksplorasi data, kita dapat memvisualisasikan secara langsung menggunakan metode plot pada objek dataframe ekspor seperti kode berikut:
Python
import pandas as pd
# Memuat dataset ekspor-idn.csv
ekspor = pd.read_csv("ekspor-idn.csv", index_col="periode", parse_dates=True)
# mengatur frekuensi data bulanan
ekspor.index.freq = 'MS'
# print data
print(ekspor)
# membuat plot data
ekspor.plot(figsize=(12, 6))Output
# Output
nilai_jt_usd
periode
2016-01-01 39479.3
2016-02-01 38596.9
2016-03-01 42908.5
...
2019-10-01 61413.0
2019-11-01 56022.2
2019-12-01 55720.1

Membuat Model ARIMA
Pembuatan model ARIMA dilakukan dengan fungsi ARIMA dari library statsmodel. Pada bagian ini, kita akan membuat model ARIMA dengan nilai p,d,q yang sudah ditentukan yaitu p=1, d=1 dan q=1. Selanjutnya, dari model tersebut kita dapat melakukan forecasting atau prediksi nilai ekspor Indonesia untuk periode-periode berikutnya. Misalkan seperti contoh berikut ini, kita melakukan forecasting untuk 3 bulan yaitu Januari-Maret 2020.
Python
# Memuat fungsi ARIMA from statsmodels.tsa.arima.model import ARIMA # Membagun model ARIMA dengan p=1, d=1 dan q=1 model = ARIMA(data, order=(1, 1, 1)) model_fit = model.fit() # Melakukan forecasting # 3 bulan (Jan-Mar 2020) print(model_fit.forecast(3)) # alternatif prediksi # model_fit.predict(start=len(data), end=len(data)+2, typ="levels") # menampilkan summary model print(model_fit.summary())
Output
# forecast
2020-01-01 55472.142703
2020-02-01 55586.231825
2020-03-01 55533.737594
Freq: MS, Name: predicted_mean, dtype: float64
# summary
SARIMAX Results
==============================================================================
Dep. Variable: nilai_jt_usd No. Observations: 48
Model: ARIMA(1, 1, 1) Log Likelihood -461.005
Date: Sat, 21 Jan 2023 AIC 928.009
Time: 14:38:14 BIC 933.560
Sample: 01-01-2016 HQIC 930.098
- 12-01-2019
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 -0.4601 0.245 -1.878 0.060 -0.940 0.020
ma.L1 0.1835 0.272 0.675 0.500 -0.350 0.717
sigma2 1.218e+07 7.16e-09 1.7e+15 0.000 1.22e+07 1.22e+07
==============================================================================
Ljung-Box (L1) (Q): 9.50 Jarque-Bera (JB): 0.38
Prob(Q): 0.00 Prob(JB): 0.83
Heteroskedasticity (H): 1.27 Skew: 0.14
Prob(H) (two-sided): 0.63 Kurtosis: 2.65
==============================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
[2] Covariance matrix is singular or near-singular, with condition number 3.29e+31.
Standard errors may be unstable.
Mencari p, d dan q dengan Grid Search
Seperti yang telah disampaikan, model ARIMA memerlukan penentuan nilai p,d dan q. Salah satu teknik yang dapat digunakan adalah grid search. Langkah pertama yang perlu dilakukan adalah menyiapkan nilai-nilai p, d dan q yang akan dicobakan. Untuk memudahkan pekerjaan ini, kita dapat menggunakan fungsi product pada library itertools. Contoh yang akan kita gunakan yaitu nilai p (0-4), d (0-2) dan q (0-4). Secara total, pengaturan ini akan membandingkan 5x3x5 atau 75 model dengan kombinasi nilai p, d dan q yang berbeda.
Python
from itertools import product # Membuat list untuk p, d, dan q # ingat : indeks pada python dimulai dari 0 p = range(0, 5) # 0-4 d = range(0, 3) # 0-2 q = range(0, 5) # 0-4 # Menggunakan fungsi product dari itertools # untuk membuat kombinasi p, d, dan q pdq = list(product(p, d, q)) print(pdq)
Output
Output: [(0, 0, 0), (0, 0, 1), (0, 0, 2), ... (4, 2, 2), (4, 2, 3), (4, 2, 4)]
Berikutnya, kita lakukan iterasi untuk setiap kombinasi nilai pada variabel pdq. Pada setiap iterasi kita membuat model ARIMA dengan nilai p, d dan q tersebut. Dari setiap model yang dibuat, kita juga menyimpan metrik aic yang nantinya digunakan dalam penentuan model terbaik
Python
from statsmodels.tsa.arima.model import ARIMA
# Membuat list untuk menyimpan Skor AIC
aic_scores = []
# Melakukan grid search manual untuk menemukan p, d, q yang optimal
for param in pdq:
# Melakukan fitting ARIMA model
model = ARIMA(data, order=param)
model_fit = model.fit()
# Menambahkan aic score ke list
aic_scores.append({'par': param, 'aic': model_fit.aic})
# Memilih aic score terkecil
best_aic = min(aic_scores, key=lambda x: x['aic'])
print(best_aic)Output
Output:
{'par': (2, 1, 2), 'aic': 911.7672265060809}Dari proses grid search diperoleh nilai p, d dan q yang optimal adalah p=2, d=1 dan q=2 dengan skor AIC terkecil yaitu 911,767.
Langkah berikutnya, buat model ARIMA menggunakan nilai p, d dan q tersebut. Model kemudian dapat digunakan untuk forecasting sama seperti sebelumnya
Python
# Membuat model dengan p, d, dan q hasil grid search model = ARIMA(data, order=best_aic['par']) # order=(2, 1, 2) model_fit = model.fit() # forecasting 3 periode waktu ke depan model_fit.forecast(3) # alternatif prediksi # model_fit.predict(start=len(data), end=len(data)+2, typ="levels")
Output
2020-01-01 51357.694104 2020-02-01 54836.830177 2020-03-01 52991.158003 Freq: MS, Name: predicted_mean, dtype: float64
Validasi dan Evaluasi Model
Pada bagian sebelumnya, kita membangun model ARIMA menggunakan SELURUH DATA yang ada sehingga model tidak dapat dievaluasi dengan data baru. Cara tersebut terkadang dapat menghasilkan model yang overfitting. Praktik yang disarankan adalah membagi data menjadi setidaknya 2 bagian yaitu data training dan testing. Model akan dilatih dan dibentuk hanya berdasarkan data training saja, kemudian dilakukan evaluasi performa model menggunakan data testing (out-of-sample forecasting).
Tidak seperti validasi pada data cross section, pada data time series pembagian data tidak dapat dilakukan secara acak. Data harus dibagi 2, tepat pada suatu titik waktu tertentu. Setiap data yang berada pada periode sebelum titik tersebut digunakan sebagai data training, sementara data-data setelahnya menjadi menjadi data testing.
Dalam contoh ini, kita akan menggunakan data 5 bulan terakhir (Agustus-Desember 2019) sebagai data testing sehingga data sebelum periode tersebut menjadi data training.
Untuk menentukan nilai p,d dan q kita akan menggunakan cara yang sama seperti sebelumnya, namun data untuk fitting model adalah data training saja, bukan seluruh data.
Python
from statsmodels.tsa.arima.model import ARIMA
# Membagi data training dan testing
data_train = data[:-5]
data_test = data[-5:]
# Membuat list untuk menyimpan Skor AIC
aic_scores = []
# Melakukan grid search manual untuk menemukan p, d, q yang optimal
for param in pdq:
# Melakukan fitting model ARIMA
model = ARIMA(data_train, order=param)
model_fit = model.fit()
# Menambahkan aic score ke list
aic_scores.append({'par': param, 'aic': model_fit.aic})
# Mencari skor aic terkecil
best_aic = min(aic_scores, key=lambda x: x['aic'])
print(best_aic)
# Membuat model ARIMA dengan p, d, dan q hasil grid search
model = ARIMA(data_train, order=best_aic['par'])
model_fit = model.fit()
# Melakukan prediksi 5 periode ke depan (data testing)
# (Agustus - Desember 2019)
preds = model_fit.forecast(5)
print(preds)
# alternatif prediksi periode data testing
# model_fit.predict(start=data_test.index[0], end=data_test.index[-1], typ="levels")Output
Output:
{'par': (3, 1, 3), 'aic': 819.6467518173176}
2019-08-01 53694.007736
2019-09-01 54841.950539
2019-10-01 56074.166643
2019-11-01 53314.075703
2019-12-01 57545.297465
Freq: MS, Name: predicted_mean, dtype: float64Hasil grid search menggunakan data training memberikan nilai yang sedikit berbeda dari sebelumnya. Nilai AIC terkecil diperoleh pada p=3, d=1 dan q=3.
Selanjutnya, untuk mengevaluasi model, kita melakukan prediksi pada periode data testing. Hasil prediksi model kemudian dibandingkan dengan nilai sebenarnya. Di sini kita akan menggunakan metrik RMSE. Untuk menghitung nilai RMSE dapat menggunakan fungsi rmse pada library statsmodels.
Dari hasil penghitungan, diperoleh nilai RMSE data testing dari model ARIMA(3, 1, 3) adalah sebesar 2861,661. Jika melihat kisaran nilai pada data testing yang berada pada rentang 50.000 – 60.000. Nilai rata-rata error sebesar 2861,661 dapat kita katakan relatif kecil sehingga model yang kita peroleh sepertinya sudah cukup bagus.
Python
from statsmodels.tools.eval_measures import rmse
rmse = rmse(data_test["nilai_jt_usd"], preds)
print(f"RMSE : {rmse}")
data.plot(figsize=(12, 6), alpha=0.5, marker="s")
preds.plot(linewidth=2, marker="o", legend=True)Output
RMSE : 2861.6614013795875


Dalam evalausi model time series, terdapat teknik lainnya yang dapat digunakan untuk validasi dan evaluasi yaitu walk forward validation. Teknik ini mirip seperti K-Fold CV atau LOOVC namun tentunya dengan mempertimbangkan adanya keterkaitan antar waktu pada data time series. Topik ini akan dibahas lebih lanjut pada kesempatan lainnya.
Tulisan Lainnya





