1. Pendahuluan

1.1 Latar Belakang

Bawang merah merupakan salah satu jenis sayuran yang sangat dicari dan diusahakan oleh petani di Indonesia. Bawang merah adalah tanaman holtikultura yang sangat sensitif terhadap perubahan harga, yang dapat mempengaruhi baik petani maupun konsumen. Harga bawang merah di pasaran sangat berfluktuatif karena pembentukan harga sepenuhnya diserahkan pada mekanisme pasar (Widiyasari, 2001). Harga produk yang berfluktuasi secara tajam sebenarnya tidak menguntungkan petani, karena menyebabkan ketidakpastian pendapatan dan akan meningkatkan resiko. Oleh karena itu, perlu dilakukan peramalan untuk memperkecil resiko.

Metode ARIMA merupakan metode peramalan yang paling umum digunakan. Metode ini mampu menangkap pola data musiman maupun tren dalam data runtun waktu. Namun, data harga yang berfluktuatif terkadang menjadi tantangan baru dalam metode ARIMA, karena data dengan fluktuatif tinggi sering mengandung outlier. Menurut (Sihombing P.R, 2022), data outlier dapat didefinisikan sebagai amatan yang menyimpang jauh dari amatan yang lainnya. Data runtun waktu yang mengandung outlier sering kali membuat hasil peramalan yang tida akurat, sehingga metode ARIMA masih kurang baik digunakan untuk peramalan data yang memiliki outlier. ARIMA outlier merupakan modifikasi dari metode ARIMA. Dengan menggunakan model ARIMA dengan penambahan outlier, dengan metode ini diharapkan nantinya model peramalan yang dibentuk akan dapat menangkap data outlier sehingga peramalan yang dihasilkan dapat lebih akurat.

Disisi lain, dengan perkembangan zaman yang semakin berkembang, pemodelan data berbasis kecerdasan buatan seperti Neural Network (NN) juga mulai banyak digunakan untuk meramalkan data yang kompleks dan memiliki pola nonlinier. Dengan memanfaatkan pemodelan dengan metode NN, data runtun waktu yang memiliki fluktuasi yang tinggi dapat diramalkan dengan memanfaatkan proses pelatihan jaringan saraf tiruan untuk mengenali pola dalam data dan meramalkan nilainya di masa depan (Sawitri M.N.D, 2018). Namun pada prosesnya, sering kali metode NN memerlukan data yang besar untuk menjadi data yang training, serta tidak menutup kemungkinan mengalami overfitting.

Dengan mempertimbangkan kelebihan dan kekurangan dari kedua metode diatas, peneliti tertarik untuk melakukan analisis perbendingan peramalan harga bawang merah dengan menggunakan metode ARIMA outlier dengan metode Neural Network. Dengan penelitian ini diharapkan dapat memberikan gambaran perbandingan metode perAmalan yang lebih akurat untuk meramalkan data harga komoditas yang mudah mengalami fluktuasi.

2. Import Library

library(MASS)
## Warning: package 'MASS' was built under R version 4.4.3
library(car)
## Loading required package: carData
library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(tseries)
library(quadprog)
library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(fracdiff)
library(fUnitRoots)
library(lmtest)
library(Rssa)
## Warning: package 'Rssa' was built under R version 4.4.3
## Loading required package: svd
## Warning: package 'svd' was built under R version 4.4.3
## 
## Attaching package: 'Rssa'
## The following object is masked from 'package:stats':
## 
##     decompose
library(tseries)
library(forecast)
library(MLmetrics)
## Warning: package 'MLmetrics' was built under R version 4.4.3
## 
## Attaching package: 'MLmetrics'
## The following object is masked from 'package:base':
## 
##     Recall
library(Metrics)
## Warning: package 'Metrics' was built under R version 4.4.3
## 
## Attaching package: 'Metrics'
## The following object is masked from 'package:forecast':
## 
##     accuracy
library(urca) 
## Warning: package 'urca' was built under R version 4.4.3
## 
## Attaching package: 'urca'
## The following objects are masked from 'package:fUnitRoots':
## 
##     punitroot, qunitroot, unitrootTable
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
## 
##     recode
## The following object is masked from 'package:MASS':
## 
##     select
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(TSA)
## Warning: package 'TSA' was built under R version 4.4.3
## Registered S3 methods overwritten by 'TSA':
##   method       from    
##   fitted.Arima forecast
##   plot.Arima   forecast
## 
## Attaching package: 'TSA'
## The following objects are masked from 'package:stats':
## 
##     acf, arima
## The following object is masked from 'package:utils':
## 
##     tar
library(neuralnet)
## Warning: package 'neuralnet' was built under R version 4.4.3
## 
## Attaching package: 'neuralnet'
## The following object is masked from 'package:dplyr':
## 
##     compute

3. Input Data dan Splitting Data

Data yang digunakan dalam penelitian ini adalah data mingguan Harga Bawang Merah di Kota Samarinda periode 2 Januari 2023 hingga 5 Mei 2025. Adapun sumber data diperoleh dari laman website : bi.go.id/hargapangan/TabelHarga/PasarTradisionalDaerah

data = read.table(file.choose(),header = T)

harga_bawang = ts(data$Zt)
Zt_rill<-ts(data[1:111,1])
Zt<-Zt_rill/1000
Zt_rill<-ts(data[1:111,1])
Zt<-Zt_rill/1000

4. Time Series Plot

plot(Zt_rill, main = "Time Series Plot Harga Bawang Merah", xlab="Periode ke-", ylab="Harga Bawang Merah")

Berdasarkan time series plot diatas dapat diketahui bahwa nilai tukar rupiah mengalami fluktuasi di tiap periode nya dan cenderung mengalami trend naik.

5. ARIMA Outlier

Sebelum melakukan tahap analisis menggunakan model Autoregressive Integrated Moving Average (ARIMA) dan Neural Network (NN) dilakukan tahap pembagian data atau splitting data dengan rasio 90% untuk data training dan 10% untuk data testing atau dapat ditulis sebagai 90:10

jumlah_train = round(NROW(harga_bawang)*0.9,0)
jumlah_test = NROW(harga_bawang)-jumlah_train

data_train = harga_bawang[1:jumlah_train]
data_test  = harga_bawang[(jumlah_train+1):(jumlah_test+jumlah_train)]

5.1 Tahap stasioneritas data

Dalam melakukan pemodelan ARIMA, maka tahapan awal yang harus dilakukan adalah melakukan stasioneritas pada data, hal ini dikarenakan dalam melakukan pemodelan ARIMA harus memenuhi syarat stasioneritas data. Terdapat dua tahapan dalam stasioneritas yaitu stasioneritas terhadap varinasi dan stasioneritas terhadap rata-rata.

5.1.1 Stasioneritas Dalam Variansi

boxcox(Zt~1) #cek stasioner dalam variansi

p<-powerTransform(Zt)
p
## Estimated transformation parameter 
##        Zt 
## 0.2322095
y<-Zt^p$lambda

ts.plot(y,ylab="Zt Hasil Transformasi",xlab="Periode")

acf(y,main="",ylab="FOK")

pacf(y,main="",ylab="FOKP")

Karena hasil uji Box-Cox memberikan nilai lambda sebesar 0,232 maka disimpulkan data tidak stasioner terhadap variansi karena lambda belum mendekati 1, sehingga perlu dilakukan transformasi dengan memangkatkan data dengan nilai lambda yang diperoleh. Kemudian dilakukan pengecekan plot ACF dan PACF dan dapat dilihat plot ACF belum mengalami cut off sehingga dapat mengindikasikan data tidak stasioner terhadap rata-rata dan dilakukan uji ADF.

5.1.2 Stasioneritas Dalam Rata-rata

Setelah melakukan tahap transformasi maka dilakukan tahap stasioneritas rata-rata.

adfTest(y)
## 
## Title:
##  Augmented Dickey-Fuller Test
## 
## Test Results:
##   PARAMETER:
##     Lag Order: 1
##   STATISTIC:
##     Dickey-Fuller: -0.2106
##   P VALUE:
##     0.5462 
## 
## Description:
##  Tue May 13 01:50:13 2025 by user: HP
#Diff 1 kali
datadiff=diff(y,differences=1)
datadiff
## Time Series:
## Start = 2 
## End = 111 
## Frequency = 1 
##   [1]  0.0117743983  0.0156261823  0.0066889142  0.0046454263  0.0131098969
##   [6] -0.0104687777 -0.0227655608 -0.0200086518 -0.0035075748 -0.0063578922
##  [11] -0.0049850084 -0.0028645284 -0.0145009693 -0.0014667848  0.0065763894
##  [16]  0.0029030877  0.0469281155  0.0213663136  0.0110979621 -0.0091270598
##  [21] -0.0206313247 -0.0074660196  0.0040820511  0.0047330825  0.0047019723
##  [26]  0.0026730535 -0.0114300309 -0.0227248347 -0.0344173091 -0.0246866575
##  [31] -0.0193083061 -0.0166512240 -0.0178939212 -0.0217799317 -0.0207564045
##  [36] -0.0124158548 -0.0135686027 -0.0073535451 -0.0018514447  0.0046187647
##  [41] -0.0027673200 -0.0046385451  0.0018593958  0.0361171519  0.0283760616
##  [46]  0.0182689092  0.0089518965  0.0096325924  0.0204146685  0.0243199649
##  [51] -0.0181590480  0.0802875211  0.0274923361 -0.0046198522 -0.0174245388
##  [56] -0.0213473259 -0.0141220102 -0.0078896056 -0.0014440565  0.0028851435
##  [61] -0.0065083688 -0.0036420964  0.0000000000 -0.0036611953  0.0273565267
##  [66]  0.0536992302  0.0078161113  0.1648483697 -0.0067869972 -0.0354127291
##  [71] -0.0222912683 -0.0102497308 -0.0115550853 -0.0224598960 -0.0108809152
##  [76] -0.0135207118 -0.0245996581 -0.0307986763 -0.0279915470 -0.0430712424
##  [81] -0.0411852822 -0.0371548598 -0.0210872988 -0.0103639631 -0.0043666171
##  [86] -0.0123825069  0.0035616776  0.0079440342 -0.0052853710  0.0327834720
##  [91]  0.0050319491  0.0115965116  0.0016404485  0.0032689762  0.0177024665
##  [96]  0.0527247050  0.0407288325  0.0272433873  0.0106133971  0.0032848412
## [101]  0.0065251677  0.0071103529 -0.0006435208  0.0127633680 -0.0089107745
## [106] -0.0155348346 -0.0219219803 -0.0184495915 -0.0175214764 -0.0121683735
adfTest(datadiff)
## Warning in adfTest(datadiff): p-value smaller than printed p-value
## 
## Title:
##  Augmented Dickey-Fuller Test
## 
## Test Results:
##   PARAMETER:
##     Lag Order: 1
##   STATISTIC:
##     Dickey-Fuller: -4.7226
##   P VALUE:
##     0.01 
## 
## Description:
##  Tue May 13 01:50:13 2025 by user: HP

Setelah dilakukan uji ADF diperoleh p-value lebih besar dari alpha sehingga data tidak stasioner terhadap rata-rata dan perlu dilakukan differencing orde 1. Setelah dilakukan differencing orde 1 diperoleh p-value sebesar 0,01 sehingga data sudah stasioner terhadap rata-rata.

5.2 Pembentukan Model ARIMA Sementara

acf(datadiff,100,main="",ylab="FOK") #q=1
grid()

pacf(datadiff,100,main="",ylab="FOKP") #p=1 
grid()

Berdasarkan plot ACF dan PACF dapat dilihat bahwa plot ACF dan PACF mengalami cut off setelah lag 1 sehingga diperoleh model AR (1,1) dan MA (1,1) karena kedua plot cut off sehingga model AR dan MA tidak dapat digabung.

5.3 Tahap Estimasi dan Pengujian Signifikansi Parameter Model ARIMA

# Pengujian Signifikansi Parameter
fit1=arima(x=y,order=c(1,1,0))
fit1 
## 
## Call:
## arima(x = y, order = c(1, 1, 0))
## 
## Coefficients:
##          ar1
##       0.3847
## s.e.  0.0875
## 
## sigma^2 estimated as 0.0005639:  log likelihood = 255.27,  aic = -508.54
coeftest(fit1,df=110)
## 
## t test of coefficients:
## 
##     Estimate Std. Error t value  Pr(>|t|)    
## ar1 0.384697   0.087506  4.3963 2.552e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
fit2=arima(x=y,order=c(0,1,1))
fit2 
## 
## Call:
## arima(x = y, order = c(0, 1, 1))
## 
## Coefficients:
##          ma1
##       0.2825
## s.e.  0.0778
## 
## sigma^2 estimated as 0.000593:  log likelihood = 252.54,  aic = -503.09
coeftest(fit2,df=110)
## 
## t test of coefficients:
## 
##     Estimate Std. Error t value  Pr(>|t|)    
## ma1 0.282471   0.077767  3.6323 0.0004284 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Berdasarkan estimasi dan pengujian signifikansi parameter dapat disimpulkan bahwa kedua model signifikan sehingga kedua model dilanjutkan ke pemeriksaan diagnostik.

5.4 Pengujian diagnostik model ARIMA

Terdapat dua pengujian diagnostik model, yakni pengujian normalitas residual model ARIMA dan pengujian independensi residual model ARIMA (white noise)

5.4.1 Pengujian normalitas residual

Pengujian normalitas residual model ARIMA dilakukan menggunakan uji

res1=resid(fit1)
ks.test(res1,"pnorm",mean(res1),sqrt(var(res1)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  res1
## D = 0.1957, p-value = 0.0004061
## alternative hypothesis: two-sided
res2=resid(fit2)
ks.test(res2,"pnorm",mean(res2),sqrt(var(res2)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  res2
## D = 0.1838, p-value = 0.001106
## alternative hypothesis: two-sided

Berdasarkan uji Kolmogorov-Smirnov dapat dilihat bahwa kedua model tidak memenuhi asumsi normalitas residual namun hal tersebut bukanlah masalah besar karena tujuan utama kita adalah untuk meramalkan harga bawang merah sehingga lebih diutamakan memenuhi asumsi white noise.

5.4.2 Independensi Residual (white noise)

x<-res1
pv2<-rep(1,length(x))
for(i in 1:length(x))
  pv2[i]=Box.test(x,lag=i,type="Ljung")$p.value
plot(pv2,type="p",main="Ljung-Box ARIMA (1,1,0)",xlab="lag",ylab="p value",ylim=c(0,1))
abline(h=0.05,lty=1,col="red")

pv2<-rep(1,length(x))
for(i in 1:length(x))
  pv2[i]=Box.test(x,lag=i,type="Ljung")$p.value
plot(pv2,type="p",main="Ljung-Box ARIMA (0,1,1)",xlab="lag",ylab="p value",ylim=c(0,1))
abline(h=0.05,lty=1,col="red")

Berdasarkan uji Ljung-Box yang telah dilakukan dapat disimpulkan bahwa kedua model tidak white noise. Salah satu penyebab model tidak white noise adalah karena terdapat outlier pada residual, sehingga perlu dilanjutkan ke pemodelan ARIMA outlier. Untuk mempermudah proses pemodelan akan ditentukan terlebih dahulu model terbaik berdasarkan nilai RMSE, MAPE, dan SMAPE.

5.5 Tahap Pemilihan Model Terbaik ARIMA

akurasi_model <- function(actual, forecast) {
  rmse <- sqrt(mean((actual - forecast)^2, na.rm = TRUE))
  mape <- mean(abs((actual - forecast) / actual), na.rm = TRUE) * 100
  smape <- mean(2 * abs(forecast - actual) / (abs(actual) + abs(forecast)), na.rm = TRUE) * 100
  return(list(
    RMSE = rmse,
    MAPE = mape,
    sMAPE = smape
  ))
}
balik_pred1=fitted(fit1)^(1/p$lambda)*1000
balik_pred2=fitted(fit2)^(1/p$lambda)*1000
akurasi_model(Zt_rill, balik_pred1)
## $RMSE
## [1] 1890.029
## 
## $MAPE
## [1] 2.428473
## 
## $sMAPE
## [1] 2.465133
akurasi_model(Zt_rill, balik_pred2)
## $RMSE
## [1] 1900.256
## 
## $MAPE
## [1] 2.641946
## 
## $sMAPE
## [1] 2.681888

Berdasarkan akurasi yang diperoleh dapat dilihat bahwa model ARIMA (1,1,0) merupakan model terbaik karena memiliki nilai RMSE, MAPE, dan SMAPE yang lebih kecil. Sehingga model ARIMA (1,1,0) akan kita modelkan dengan deteksi outlier.

5.6 Pendeteksian Outlier

Prediksi_TFR1<-fitted.values(fit1)
Hasil_Prediksi1<-Prediksi_TFR1^(1/p$lambda)
Error_Prediksi1<-Zt-Hasil_Prediksi1
plot(scale(Error_Prediksi1),main="Residual ARIMA (1,1,0)",ylim=c(-7,7))
points(scale(Error_Prediksi1),pch=16,col="black")
abline(h=1.96,col="red")
abline(h=-1.96,col="red")

Berdasarkan plot residual tersebut dapat dilihat bahwa terdapat outlier pada residualke-53, 69, dan 70 karena residual tersebut bernilai lebih besar dari 1,96 atau lebih kecil dari -1,96.

5.7 Estimasi dan Pengujian Signifikansi Model ARIMA Outlier

#PEMODELAN OUTLIER (53,69,70)
#ARIMA (1,1,0) + Outlier 53
outlierdummy1<-rep(0,length(y))
outlierdummy1[53]<-1
model1<-arima(y,order=c(1,1,0),xreg=outlierdummy1)
summary(model1)
## 
## Call:
## arima(x = y, order = c(1, 1, 0), xreg = outlierdummy1)
## 
## Coefficients:
##          ar1    xreg
##       0.4071  0.0282
## s.e.  0.0866  0.0131
## 
## sigma^2 estimated as 0.0005415:  log likelihood = 257.49,  aic = -510.99
## 
## Training set error measures:
##                        ME       RMSE        MAE      MPE     MAPE      MASE
## Training set -0.000157905 0.02316553 0.01340765 83.36415 108.1134 0.8330712
##                     ACF1
## Training set -0.05748279
coeftest(model1)
## 
## z test of coefficients:
## 
##      Estimate Std. Error z value  Pr(>|z|)    
## ar1  0.407117   0.086566  4.7030 2.564e-06 ***
## xreg 0.028153   0.013122  2.1456   0.03191 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
res_model1=resid(model1)
#ARIMA (1,1,0) + Outlier 69
outlierdummy2<-rep(0,length(y))
outlierdummy2[69]<-1
model2<-arima(y,order=c(1,1,0),xreg=outlierdummy2)
summary(model2)
## 
## Call:
## arima(x = y, order = c(1, 1, 0), xreg = outlierdummy2)
## 
## Coefficients:
##          ar1    xreg
##       0.5482  0.0794
## s.e.  0.0791  0.0100
## 
## sigma^2 estimated as 0.0003689:  log likelihood = 278.52,  aic = -553.04
## 
## Training set error measures:
##                         ME      RMSE        MAE      MPE    MAPE      MASE
## Training set -0.0001517651 0.0191203 0.01182654 51.69868 133.581 0.7348301
##                     ACF1
## Training set -0.02515894
coeftest(model2)
## 
## z test of coefficients:
## 
##       Estimate Std. Error z value  Pr(>|z|)    
## ar1  0.5481675  0.0790548  6.9340 4.090e-12 ***
## xreg 0.0794109  0.0099948  7.9452 1.939e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
res_model2=resid(model2)
#ARIMA (1,1,0) + Outlier 70
outlierdummy3<-rep(0,length(y))
outlierdummy3[70]<-1
model3<-arima(y,order=c(1,1,0),xreg=outlierdummy3)
summary(model3)
## 
## Call:
## arima(x = y, order = c(1, 1, 0), xreg = outlierdummy3)
## 
## Coefficients:
##          ar1     xreg
##       0.4003  -0.0097
## s.e.  0.0888   0.0137
## 
## sigma^2 estimated as 0.0005613:  log likelihood = 255.52,  aic = -507.03
## 
## Training set error measures:
##                         ME       RMSE        MAE      MPE     MAPE      MASE
## Training set -0.0001582794 0.02358645 0.01333182 95.32514 99.27152 0.8283594
##                     ACF1
## Training set -0.05419745
coeftest(model3)
## 
## z test of coefficients:
## 
##        Estimate Std. Error z value  Pr(>|z|)    
## ar1   0.4002656  0.0888112  4.5069 6.577e-06 ***
## xreg -0.0096879  0.0137145 -0.7064    0.4799    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
res_model3=resid(model3)
#ARIMA (1,1,0) + Outlier 53 + Outlier 69
outlierdummy4<-matrix(0,length(y),ncol=2)
outlierdummy4[53,1]<-1
outlierdummy4[69,2]<-1
model4<-arima(y,order=c(1,1,0),xreg=outlierdummy4)
summary(model4)
## 
## Call:
## arima(x = y, order = c(1, 1, 0), xreg = outlierdummy4)
## 
## Coefficients:
##          ar1   xreg1   xreg2
##       0.5805  0.0284  0.0793
## s.e.  0.0769  0.0094  0.0094
## 
## sigma^2 estimated as 0.000341:  log likelihood = 282.81,  aic = -559.61
## 
## Training set error measures:
##                         ME      RMSE        MAE      MPE    MAPE     MASE
## Training set -0.0001508316 0.0183849 0.01168658 31.10562 147.333 0.726134
##                   ACF1
## Training set 0.0208347
coeftest(model4)
## 
## z test of coefficients:
## 
##        Estimate Std. Error z value  Pr(>|z|)    
## ar1   0.5804587  0.0768747  7.5507 4.329e-14 ***
## xreg1 0.0284472  0.0094312  3.0163  0.002559 ** 
## xreg2 0.0792735  0.0094355  8.4016 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
res_model4=resid(model4)
#ARIMA (1,1,0) + Outlier 53 + Outlier 69 + Outlier 70
outlierdummy5<-matrix(0,length(y),ncol=3)
outlierdummy5[53,1]<-1
outlierdummy5[69,2]<-1
outlierdummy5[70,3]<-1
model5<-arima(y,order=c(1,1,0),xreg=outlierdummy5)
summary(model5)
## 
## Call:
## arima(x = y, order = c(1, 1, 0), xreg = outlierdummy5)
## 
## Coefficients:
##          ar1   xreg1   xreg2   xreg3
##       0.6474  0.0285  0.1216  0.0649
## s.e.  0.0718  0.0078  0.0104  0.0104
## 
## sigma^2 estimated as 0.000253:  log likelihood = 299.16,  aic = -590.32
## 
## Training set error measures:
##                         ME       RMSE      MAE      MPE     MAPE      MASE
## Training set -0.0001495719 0.01583595 0.010823 13.17928 172.7759 0.6724766
##                    ACF1
## Training set 0.01491082
coeftest(model5)
## 
## z test of coefficients:
## 
##        Estimate Std. Error z value  Pr(>|z|)    
## ar1   0.6474377  0.0717770  9.0201 < 2.2e-16 ***
## xreg1 0.0285127  0.0078248  3.6439 0.0002685 ***
## xreg2 0.1216479  0.0103761 11.7238 < 2.2e-16 ***
## xreg3 0.0648842  0.0103839  6.2486 4.143e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
res_model5=resid(model5)

Berdasarkan hasil estimasi dan pengujian signifikansi parameter diperoleh model yang signifikan adalah model ARIMA (1,1,0) + Outlier ke-53, ARIMA (1,1,0) + Outlier ke-69, ARIMA (1,1,0) + Outlier ke-53 + Outlier ke-69, dan ARIMA (1,1,0) + Outlier ke-53 + Outlier ke-69 + Outlier ke-70. Sehingga keempat model tersebut dilanjutkan ke pemeriksaan diagnostik.

5.8 Pemeriksaan Diagnostik Model ARIMA Outlier

ks.test(res_model1,"pnorm",mean(res_model1),sqrt(var(res_model1)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  res_model1
## D = 0.18717, p-value = 0.0008384
## alternative hypothesis: two-sided
x<-res_model1
pv2<-rep(1,length(x))
for(i in 1:length(x))
  pv2[i]=Box.test(x,lag=i,type="Ljung")$p.value
plot(pv2,type="p",main="Ljung-Box ARIMA (1,1,0)",xlab="lag",ylab="p value",ylim=c(0,1))
abline(h=0.05,lty=1,col="red")

ks.test(res_model2,"pnorm",mean(res_model2),sqrt(var(res_model2)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  res_model2
## D = 0.16233, p-value = 0.00576
## alternative hypothesis: two-sided
x<-res_model2
pv2<-rep(1,length(x))
for(i in 1:length(x))
  pv2[i]=Box.test(x,lag=i,type="Ljung")$p.value
plot(pv2,type="p",main="Ljung-Box ARIMA (1,1,0)",xlab="lag",ylab="p value",ylim=c(0,1))
abline(h=0.05,lty=1,col="red")

ks.test(res_model4,"pnorm",mean(res_model4),sqrt(var(res_model4)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  res_model4
## D = 0.15486, p-value = 0.009745
## alternative hypothesis: two-sided
x<-res_model4
pv2<-rep(1,length(x))
for(i in 1:length(x))
  pv2[i]=Box.test(x,lag=i,type="Ljung")$p.value
plot(pv2,type="p",main="Ljung-Box ARIMA (1,1,0)",xlab="lag",ylab="p value",ylim=c(0,1))
abline(h=0.05,lty=1,col="red")

ks.test(res_model5,"pnorm",mean(res_model5),sqrt(var(res_model5)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  res_model5
## D = 0.13584, p-value = 0.03326
## alternative hypothesis: two-sided
x<-res_model5
pv2<-rep(1,length(x))
for(i in 1:length(x))
  pv2[i]=Box.test(x,lag=i,type="Ljung")$p.value
plot(pv2,type="p",main="Ljung-Box ARIMA (1,1,0)",xlab="lag",ylab="p value",ylim=c(0,1))
abline(h=0.05,lty=1,col="red")

Berdasarkan pemeriksaan diagnostik yang telah dilakukan, dengan menggunakan uji Kolmogorov-Smirnov dapat disimpulkan bahwa residual keempat model tidak berdistribusi normal. Namun, seperti yang telah disampaikan sebelumnya hal itu bukanlah masalah besar karena model masih dapat menghasilkan prediksi yang cukup baik selama model memenuhi asumsi white noise. Berdasarkan uji Ljung-Box yang telah dilakukan dapat disimpulkan bahwa model ARIMA (1,1,0) + Outlier ke-53 white noise. Sehingga model tersebut merupakan model ARIMA Outlier terbaik yang terbentuk.

5.9 Akurasi Model ARIMA Outlier

#Akurasi Model ARIMA Outlier
akurasi_model <- function(actual, forecast) {
  rmse <- sqrt(mean((actual - forecast)^2, na.rm = TRUE))
  mape <- mean(abs((actual - forecast) / actual), na.rm = TRUE) * 100
  smape <- mean(2 * abs(forecast - actual) / (abs(actual) + abs(forecast)), na.rm = TRUE) * 100
  return(list(
    RMSE = rmse,
    MAPE = mape,
    sMAPE = smape
  ))
}
model1_balik<-fitted(model1)^(1/p$lambda)*1000
akurasi_model(Zt_rill,model1_balik)
## $RMSE
## [1] 1874.213
## 
## $MAPE
## [1] 2.428839
## 
## $sMAPE
## [1] 2.460095
#Akurasi Model ARIMA Outlier Outsample
ramalan=predict(model1,n.ahead=24,newxreg = rep(0,24))
ramalan
## $pred
## Time Series:
## Start = 112 
## End = 135 
## Frequency = 1 
##  [1] 2.311536 2.309519 2.308698 2.308364 2.308227 2.308172 2.308149 2.308140
##  [9] 2.308137 2.308135 2.308134 2.308134 2.308134 2.308134 2.308134 2.308134
## [17] 2.308134 2.308134 2.308134 2.308134 2.308134 2.308134 2.308134 2.308134
## 
## $se
## Time Series:
## Start = 112 
## End = 135 
## Frequency = 1 
##  [1] 0.02326952 0.04016927 0.05434253 0.06640822 0.07691685 0.08627061
##  [7] 0.09474875 0.10254469 0.10979472 0.11659720 0.12302505 0.12913370
## [13] 0.13496629 0.14055711 0.14593392 0.15111956 0.15613306 0.16099051
## [19] 0.16570563 0.17029025 0.17475463 0.17910778 0.18335760 0.18751112
kembalikan.ramalan=ramalan$pred^(1/p$lambda)*1000
out_balik<-ts(kembalikan.ramalan[1:12],start=1)
akurasi_model <- function(actual, forecast) {
  rmse <- sqrt(mean((actual - forecast)^2, na.rm = TRUE))
  mape <- mean(abs((actual - forecast) / actual), na.rm = TRUE) * 100
  smape <- mean(2 * abs(forecast - actual) / (abs(actual) + abs(forecast)), na.rm = TRUE) * 100
  return(list(
    RMSE = rmse,
    MAPE = mape,
    sMAPE = smape
  ))
}
Zt_out<-ts(data[112:123,1])
akurasi_model(Zt_out,out_balik)
## $RMSE
## [1] 8617.068
## 
## $MAPE
## [1] 16.72452
## 
## $sMAPE
## [1] 18.6268

Berdasarkan akurasi model yang diperoleh dapat dilihat bahwa model ARIMA (1,1,0) + Outlier ke-53 dapat memprediksi data insample dengan sangat baik karena memiliki nilai MAPE sebesar 2,428 dan dapat memprediksi data outsample dengan baik karena memiliki nilai MAPE sebesar 16,724. Sehingga dapat disimpulkan bahwa model ARIMA (1,1,0) + Outlier ke-53 dapat meramalkan harga bawang merah dengan baik.

5.10 Grafik Perbandingan Hasil Ramalan ARIMA Outlier

ramal_balik<-ts(kembalikan.ramalan[13:24],start=1)
prediksii=c(model1_balik,out_balik,ramal_balik)
prediksii
##   [1] 38732.76 38973.15 40100.10 41375.43 41604.90 41893.14 43162.34 41627.62
##   [9] 39573.26 38221.31 38448.58 37917.96 37608.22 37468.81 36148.79 36409.35
##  [17] 37084.42 37181.66 41878.42 42715.12 43249.80 41917.54 40031.65 39877.73
##  [25] 40522.63 40893.16 41243.15 41381.64 40107.82 38143.27 35456.27 34094.96
##  [33] 33001.11 32029.84 30910.47 29532.77 28372.14 27868.78 27099.10 26838.44
##  [41] 26859.37 27252.29 26939.12 26648.73 26890.79 29696.20 31192.11 32056.45
##  [49] 32376.01 32996.72 34590.45 36317.67 35824.50 39495.69 43799.07 41558.15
##  [57] 39879.76 38232.22 37448.59 37077.85 37159.35 37481.66 36767.99 36598.59
##  [65] 36700.00 36348.60 39144.93 43994.62 43146.13 63891.37 56237.01 51899.76
##  [73] 50402.51 49937.09 48897.28 46642.79 46137.38 44957.94 42674.81 40171.75
##  [81] 38238.29 34880.70 32296.42 30149.36 29302.32 28958.40 28848.69 27968.77
##  [89] 28531.73 29084.76 28478.55 31300.68 30922.78 31788.45 31640.78 31881.70
##  [97] 33356.10 37831.43 40408.17 42036.30 42329.09 42352.11 42954.85 43525.46
## [105] 43229.66 44662.16 43267.47 41868.80 40042.58 38810.35 37599.93 36908.15
## [113] 36769.67 36713.41 36690.52 36681.21 36677.42 36675.87 36675.24 36674.99
## [121] 36674.88 36674.84 36674.83 36674.82 36674.82 36674.81 36674.81 36674.81
## [129] 36674.81 36674.81 36674.81 36674.81 36674.81 36674.81 36674.81
data_lengkap<-data$Zt
ts.plot(data_lengkap,col="blue",type="o",main="Harga Bawang Merah",xlab="Time (Mingguan)",ylab="Data",xlim=c(0,135),ylim=c(26640,63900),lwd=1)
lines(prediksii,col="red",type="o",lwd=1)
legend('topleft',legend=c("Aktual","Prediksi"),col=c("blue","red"),lty=1)
abline(v=123,col="red",lwd=1,lty=2)

Berdasarkan plot yang diperoleh dapat dilihat bahwa model dapat menangkap pola data dengan baik namun memiliki kesulitan dalam memprediksi data outsample karena menghasilkan nilai yang konstan hingga peramalan.

6. Neural Network

Neural Network (NN) merupakan model yang cukup banyak digunakan akhir-akhir ini untuk menganalisis dara runtun waktu. Hal ini dikarenakan Neural Network merupakan model yang dapat meramalkan data kompleks serta memiliki pola nonlinier. Berikut langkah-langkah dalam meramalkan data runtun waktu menggunakan Neural Network.

6.1 Standarisasi data

Proses standarisasi data diperlukan dalam pemodelan Neural Network dikarenakan proses standarisasi dapat membuat skala data lebih kecil, dapat memudahkan model Neural Network untuk menemukan pola data, serta proses standarisasi data dapat menjadi acuan dalam pemilihan fungsi aktivasi. Pada penelitian ini standarisasi data yang dihasilkan berkisar antara -1 sampai 1 yang mana karakteristik data ini sama dengan karakteristik fungsi aktivasi tanh .

max_asli = max(harga_bawang)
min_asli = min(harga_bawang)
data_standarisasi = 2*((as.numeric(harga_bawang) - min_asli)/(max_asli - min_asli))-1
head(data_standarisasi)
## [1] -0.20065789 -0.14473684 -0.06907895 -0.03618421 -0.01315789  0.05263158

Setelah mendapatkan data standarisasi yang berkisar antara -1 sampai 1. Proses selanjutnya adalah membuat grafik Partial Autocorrelation Function (PACF) dari data standarisasi.

6.2 Grafik PACF Data Standarisasi

Grafik PACF dalam proses pemodelan Neural Network digunakan untuk menentukan data input, hal ini dilakukan dengan cara melihat lag-lag yang signifikan pada grafik PACF.

pacf(data_standarisasi, main = "PACF Data Standarisasi", lag.max = 80)
grid()

Berdasarkan output diatas, maka dapat diketahui bahwa nilai PACF cut off setelah lag ke-3. Oleh karena itu, maka data yang dimasukan dalam layer input adalah seluruh data asli \((Z_t)\) dan data pada lag ke-3 \((Z_{t-3})\).

6.3 Tahap Pembentukan model NN

Setelah mendapatkan data input atau masukan yakni data \(Z_t\) dan \(Z_{t-3}\) kemudian dilakukan tahap pemodelan hingga training. Proses training Neural Network menggunakan algoritma Backpropagation dengan optimasi rpopr+ serta menggunakan fungsi aktivasi tanh . Adapun jumlah hidden layer yang digunakan dalam penelitian ini bermacam-macam. Berikut proses pembentukan model hingga ketahap training model Neural Network.

6.3.1 Input data

y = data.frame(
  nilai_asli = data_standarisasi
) %>% 
  mutate(
    nilai_lag = dplyr::lag(nilai_asli, n = 3, default = NA)
  )
y
##       nilai_asli    nilai_lag
## 1   -0.200657895           NA
## 2   -0.144736842           NA
## 3   -0.069078947           NA
## 4   -0.036184211 -0.200657895
## 5   -0.013157895 -0.144736842
## 6    0.052631579 -0.069078947
## 7    0.000000000 -0.036184211
## 8   -0.111842105 -0.013157895
## 9   -0.207236842  0.052631579
## 10  -0.223684211  0.000000000
## 11  -0.253289474 -0.111842105
## 12  -0.276315789 -0.207236842
## 13  -0.289473684 -0.223684211
## 14  -0.355263158 -0.253289474
## 15  -0.361842105 -0.276315789
## 16  -0.332236842 -0.289473684
## 17  -0.319078947 -0.355263158
## 18  -0.098684211 -0.361842105
## 19   0.006578947 -0.332236842
## 20   0.062500000 -0.319078947
## 21   0.016447368 -0.098684211
## 22  -0.085526316  0.006578947
## 23  -0.121710526  0.062500000
## 24  -0.101973684  0.016447368
## 25  -0.078947368 -0.085526316
## 26  -0.055921053 -0.121710526
## 27  -0.042763158 -0.101973684
## 28  -0.098684211 -0.078947368
## 29  -0.207236842 -0.055921053
## 30  -0.365131579 -0.042763158
## 31  -0.473684211 -0.098684211
## 32  -0.555921053 -0.207236842
## 33  -0.625000000 -0.365131579
## 34  -0.697368421 -0.473684211
## 35  -0.782894737 -0.555921053
## 36  -0.861842105 -0.625000000
## 37  -0.907894737 -0.697368421
## 38  -0.957236842 -0.782894737
## 39  -0.983552632 -0.861842105
## 40  -0.990131579 -0.907894737
## 41  -0.973684211 -0.957236842
## 42  -0.983552632 -0.983552632
## 43  -1.000000000 -0.990131579
## 44  -0.993421053 -0.973684211
## 45  -0.861842105 -0.983552632
## 46  -0.753289474 -1.000000000
## 47  -0.680921053 -0.993421053
## 48  -0.644736842 -0.861842105
## 49  -0.605263158 -0.753289474
## 50  -0.519736842 -0.680921053
## 51  -0.414473684 -0.644736842
## 52  -0.493421053 -0.605263158
## 53  -0.128289474 -0.519736842
## 54   0.006578947 -0.414473684
## 55  -0.016447368 -0.493421053
## 56  -0.101973684 -0.128289474
## 57  -0.203947368  0.006578947
## 58  -0.269736842 -0.016447368
## 59  -0.305921053 -0.101973684
## 60  -0.312500000 -0.203947368
## 61  -0.299342105 -0.269736842
## 62  -0.328947368 -0.305921053
## 63  -0.345394737 -0.312500000
## 64  -0.345394737 -0.299342105
## 65  -0.361842105 -0.328947368
## 66  -0.236842105 -0.345394737
## 67   0.023026316 -0.345394737
## 68   0.062500000 -0.361842105
## 69   1.000000000 -0.236842105
## 70   0.957236842  0.023026316
## 71   0.740131579  0.062500000
## 72   0.608552632  1.000000000
## 73   0.549342105  0.957236842
## 74   0.483552632  0.740131579
## 75   0.358552632  0.608552632
## 76   0.299342105  0.549342105
## 77   0.226973684  0.483552632
## 78   0.098684211  0.358552632
## 79  -0.055921053  0.299342105
## 80  -0.190789474  0.226973684
## 81  -0.388157895  0.098684211
## 82  -0.565789474 -0.055921053
## 83  -0.717105263 -0.190789474
## 84  -0.799342105 -0.388157895
## 85  -0.838815789 -0.565789474
## 86  -0.855263158 -0.717105263
## 87  -0.901315789 -0.799342105
## 88  -0.888157895 -0.838815789
## 89  -0.858552632 -0.855263158
## 90  -0.878289474 -0.901315789
## 91  -0.753289474 -0.888157895
## 92  -0.733552632 -0.858552632
## 93  -0.687500000 -0.878289474
## 94  -0.680921053 -0.753289474
## 95  -0.667763158 -0.733552632
## 96  -0.595394737 -0.687500000
## 97  -0.368421053 -0.680921053
## 98  -0.180921053 -0.667763158
## 99  -0.049342105 -0.595394737
## 100  0.003289474 -0.368421053
## 101  0.019736842 -0.180921053
## 102  0.052631579 -0.049342105
## 103  0.088815789  0.003289474
## 104  0.085526316  0.019736842
## 105  0.151315789  0.052631579
## 106  0.105263158  0.088815789
## 107  0.026315789  0.085526316
## 108 -0.082236842  0.151315789
## 109 -0.171052632  0.105263158
## 110 -0.253289474  0.026315789
## 111 -0.309210526 -0.082236842
## 112 -0.328947368 -0.171052632
## 113 -0.259868421 -0.253289474
## 114 -0.032894737 -0.309210526
## 115  0.115131579 -0.328947368
## 116  0.200657895 -0.259868421
## 117  0.315789474 -0.032894737
## 118  0.335526316  0.115131579
## 119  0.348684211  0.200657895
## 120  0.500000000  0.315789474
## 121  0.424342105  0.335526316
## 122  0.223684211  0.348684211
## 123  0.115131579  0.500000000
trainy = y[1:111,]
trainy = na.omit(trainy)
testy = y[112:123,]

head(trainy)
##    nilai_asli   nilai_lag
## 4 -0.03618421 -0.20065789
## 5 -0.01315789 -0.14473684
## 6  0.05263158 -0.06907895
## 7  0.00000000 -0.03618421
## 8 -0.11184211 -0.01315789
## 9 -0.20723684  0.05263158
head(testy)
##      nilai_asli   nilai_lag
## 112 -0.32894737 -0.17105263
## 113 -0.25986842 -0.25328947
## 114 -0.03289474 -0.30921053
## 115  0.11513158 -0.32894737
## 116  0.20065789 -0.25986842
## 117  0.31578947 -0.03289474
attach(trainy)
attach(testy)
## The following objects are masked from trainy:
## 
##     nilai_asli, nilai_lag

6.3.2 Neural network 1 hidden layer

set.seed(1234)
mlp_1_1 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=1, act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_1_1)
set.seed(1234)
mlp_1_2 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=2, act.fct="tanh", linear.output = T, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_1_2)
set.seed(1234)
mlp_1_3 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=3, act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_1_3)

6.3.3 Neural network 2 hidden layer

set.seed(1234)
mlp_2_1_1 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=c(1,1), act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_2_1_1)
set.seed(1234)
mlp_2_1_2 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=c(1,2), act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_2_1_2)
set.seed(1234)
mlp_2_1_3 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=c(1,3), act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_2_1_3)
set.seed(1234)
mlp_2_2_1 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=c(2,1), act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.02, algorithm = "rprop+")
plot(mlp_2_2_1)
set.seed(1234)
mlp_2_2_2 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=c(2,2), act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_2_2_2)
set.seed(1234)
mlp_2_2_3 = neuralnet(nilai_asli~nilai_lag, data=trainy, hidden=c(2,3), act.fct="tanh", linear.output = TRUE, learningrate = 0.005, stepmax = 10000, startweights = NULL, threshold = 0.01, algorithm = "rprop+")
plot(mlp_2_2_3)

Dikarenakan terdapat cukup banyak arsitektur yang telah didapatkan dari hasil training. Selanjutnya akan dilakukan seleksi model dengan melihat nilai Mean Absolute Percentage Error (MAPE). Root Mean Square Error (RMSE), dan Symmetrical Mean Absolute Percentage Error (SMAPE).

6.4 Tahap Prediksi

Sebelum menghitung nilai MAPE, RMSE, dan SMAPE maka terlebih dahulu dilakukan proses prediksi data menggunakan seluruh arsitektur Neural Network yang telah terbentuk. Adapun langkah-langkah nya sebagai berikut.

6.4.1 1 hidden layer

NN(1)

predict_NN1 = ts(mlp_1_1$net.result[[1]])
kembali_NN1 = ((predict_NN1 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(2)

predict_NN2 = ts(mlp_1_2$net.result[[1]])
kembali_NN2 = ((predict_NN2 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(3)

predict_NN3 = ts(mlp_1_3$net.result[[1]])
kembali_NN3 = ((predict_NN3 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

6.4.2 2 hidden layer

NN(1,1)

predict_NN_1_1 = ts(mlp_2_1_1$net.result[[1]])
kembali_NN_1_1 = ((predict_NN_1_1 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(1,2)

predict_NN_1_2 = ts(mlp_2_1_2$net.result[[1]])
kembali_NN_1_2 = ((predict_NN_1_2 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(1,3)

predict_NN_1_3 = ts(mlp_2_1_3$net.result[[1]])
kembali_NN_1_3 = ((predict_NN_1_3 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(2,1)

predict_NN_2_1 = ts(mlp_2_2_1$net.result[[1]])
kembali_NN_2_1 = ((predict_NN_2_1 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(2,2)

predict_NN_2_2 = ts(mlp_2_2_2$net.result[[1]])
kembali_NN_2_2 = ((predict_NN_2_2 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

NN(2,3)

predict_NN_2_3 = ts(mlp_2_2_3$net.result[[1]])
kembali_NN_2_3 = ((predict_NN_2_3 + 1) / 2) * (max(harga_bawang) - min(harga_bawang)) + min(harga_bawang)

6.5 Pemilihan Model NN Terbaik

Selanjutnya dilakukan tahapan seleksi arsitektur Neural Network terbaik dari ketiga matriks evaluasi (MAPE. RMSE, dan SMAPE).

cat("================ MAPE =============")
## ================ MAPE =============
cat("\nMAPE Neural Network (1) = ",MAPE(ts(kembali_NN1),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (1) =  5.815504
cat("\nMAPE Neural Network (2) = ",MAPE(ts(kembali_NN2),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (2) =  5.809559
cat("\nMAPE Neural Network (3) = ",MAPE(ts(kembali_NN3),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (3) =  5.80157
cat("\nMAPE Neural Network (1,1) = ",MAPE(ts(kembali_NN_1_1),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (1,1) =  5.816126
cat("\nMAPE Neural Network (1,2) = ",MAPE(ts(kembali_NN_1_2),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (1,2) =  5.815228
cat("\nMAPE Neural Network (1,3) = ",MAPE(ts(kembali_NN_1_3),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (1,3) =  5.797329
cat("\nMAPE Neural Network (2,1) = ",MAPE(ts(kembali_NN_2_1),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (2,1) =  5.818447
cat("\nMAPE Neural Network (2,2) = ",MAPE(ts(kembali_NN_2_2),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (2,2) =  5.803526
cat("\nMAPE Neural Network (2,3) = ",MAPE(ts(kembali_NN_2_3),ts(data_train[3:111]))*100)
## 
## MAPE Neural Network (2,3) =  5.816668
cat("\n================ RMSE =============")
## 
## ================ RMSE =============
cat("\nRMSE Neural Network (1) = ",RMSE(ts(kembali_NN1),ts(data_train[3:111])))
## 
## RMSE Neural Network (1) =  3158.843
cat("\nRMSE Neural Network (2) = ",RMSE(ts(kembali_NN2),ts(data_train[3:111])))
## 
## RMSE Neural Network (2) =  3174.902
cat("\nRMSE Neural Network (3) = ",RMSE(ts(kembali_NN3),ts(data_train[3:111])))
## 
## RMSE Neural Network (3) =  3198.161
cat("\nRMSE Neural Network (1,1) = ",RMSE(ts(kembali_NN_1_1),ts(data_train[3:111])))
## 
## RMSE Neural Network (1,1) =  3159.095
cat("\nRMSE Neural Network (1,2) = ",RMSE(ts(kembali_NN_1_2),ts(data_train[3:111])))
## 
## RMSE Neural Network (1,2) =  3158.865
cat("\nRMSE Neural Network (1,3) = ",RMSE(ts(kembali_NN_1_3),ts(data_train[3:111])))
## 
## RMSE Neural Network (1,3) =  3194.581
cat("\nRMSE Neural Network (2,1) = ",RMSE(ts(kembali_NN_2_1),ts(data_train[3:111])))
## 
## RMSE Neural Network (2,1) =  3165.793
cat("\nRMSE Neural Network (2,2) = ",RMSE(ts(kembali_NN_2_2),ts(data_train[3:111])))
## 
## RMSE Neural Network (2,2) =  3195.341
cat("\nRMSE Neural Network (2,3) = ",RMSE(ts(kembali_NN_2_3),ts(data_train[3:111])))
## 
## RMSE Neural Network (2,3) =  3191.387
cat("\n================ SMAPE =============")
## 
## ================ SMAPE =============
cat("\nSMAPE Neural Network (1) = ",smape(ts(data_train[3:111]),ts(kembali_NN1))*100)
## 
## SMAPE Neural Network (1) =  5.830796
cat("\nSMAPE Neural Network (2) = ",smape(ts(data_train[3:111]),ts(kembali_NN2))*100)
## 
## SMAPE Neural Network (2) =  5.817665
cat("\nSMAPE Neural Network (3) = ",smape(ts(data_train[3:111]),ts(kembali_NN3))*100)
## 
## SMAPE Neural Network (3) =  5.806996
cat("\nSMAPE Neural Network (1,1) = ",smape(ts(data_train[3:111]),ts(kembali_NN_1_1))*100)
## 
## SMAPE Neural Network (1,1) =  5.831195
cat("\nSMAPE Neural Network (1,2) = ",smape(ts(data_train[3:111]),ts(kembali_NN_1_2))*100)
## 
## SMAPE Neural Network (1,2) =  5.830252
cat("\nSMAPE Neural Network (1,3) = ",smape(ts(data_train[3:111]),ts(kembali_NN_1_3))*100)
## 
## SMAPE Neural Network (1,3) =  5.803836
cat("\nSMAPE Neural Network (2,1) = ",smape(ts(data_train[3:111]),ts(kembali_NN_2_1))*100)
## 
## SMAPE Neural Network (2,1) =  5.829098
cat("\nSMAPE Neural Network (2,2) = ",smape(ts(data_train[3:111]),ts(kembali_NN_2_2))*100)
## 
## SMAPE Neural Network (2,2) =  5.809709
cat("\nSMAPE Neural Network (2,3) = ",smape(ts(data_train[3:111]),ts(kembali_NN_2_3))*100)
## 
## SMAPE Neural Network (2,3) =  5.815018

berdasarkan evaluasi model maka didapatkan model Neural Network terbaik adalah NN(3)

6.6 Peramalan NN(3)

Berdasarkan tahapan sebelumnnya dapat diketahui bahwa model Neural Network dengan 1 hidden layer dan 3 neuron merupakan model terbaik yang dapat meramalkan data harga bawang. Berikut proses peramalan menggunakan Neural Network dengan 1 hidden layer dan 3 neuron

last_lag = tail(trainy$nilai_asli, 1)

forecast_normalized = numeric(16)

current_lag = last_lag

for (i in 1:16) {
  new_data = data.frame(nilai_lag = current_lag)
  pred = neuralnet::compute(mlp_1_3, covariate = new_data)
  forecast_normalized[i] = pred$net.result[1, 1]
  current_lag = forecast_normalized[i]
}

forecast_denormalized = ((forecast_normalized + 1) / 2) * (max_asli - min_asli) + min_asli

6.7 Grafik prediksi dan Peramalan Neural Newtork

Setelah didapatkan hasil prediksi dan peramalan menggunakan model Neural Network dengan 1 hidden layer serta 3 neuron kemudian dibentuk grafik peramalan dan prediksinya sebagai berikut.

Hasil_NN = ts(c(NA,NA,NA,kembali_NN_1_3,forecast_denormalized[1:11],forecast_denormalized[12:16]))

plot(1:123,harga_bawang, type = "l", main = "Grafik Prediksi dan Peramalan NN", ylab = "Nilai Kurs IDR", xlab = "Time") +
  points(harga_bawang, cex = 0.9, pch = 21) +
  lines(1:111,Hasil_NN[1:111], col = "blue") + 
  lines(112:123,Hasil_NN[112:123], col = "red") +
  lines(124:127,Hasil_NN[124:127], col = "green") +
  abline(v = 111, lty = 2) + 
  abline(v = 123, lty = 2)
## integer(0)
legend("topleft", legend = c("Data aktual","Prediksi In sample", "Prediksi Out Sample", "Peramalan"), 
       col = c("black","blue","red","green"), lty = 1, pch = 20, lwd = 3, bty = "o", cex = 0.8)
grid()

Berdasarkan output grafik tersebut dapat diketahui bahwa hasil prediksi in sample hampir mirip dengan pola data aslinya, namun hasil prediksi pada data out sample nya kurang menyerupai pola data aslinya.

6.8 Evaluasi model NN terbaik

Pada tahapan ini akan dilakukan evaluasi dari model Neural Network dengan 1 hidden layer serta dengan menggunakan 3 neuron, adapun matriks evaluasi nya sebagai berikut.

cat("================ MAPE In Sample =============")
## ================ MAPE In Sample =============
cat("\nMAPE Neural In Sample = ",MAPE(ts(kembali_NN3),ts(data_train[3:111]))*100)
## 
## MAPE Neural In Sample =  5.80157
cat("\nRMSE Neural Network In Sample = ",RMSE(ts(kembali_NN3),ts(data_train[3:111])))
## 
## RMSE Neural Network In Sample =  3198.161
cat("\nSMAPE Neural Network In Sample = ",smape(ts(data_train[3:111]),ts(kembali_NN3))*100)
## 
## SMAPE Neural Network In Sample =  5.806996
cat("\n================ MAPE Out Sample =============")
## 
## ================ MAPE Out Sample =============
cat("\nMAPE Neural Network Out Sample = ",MAPE(forecast_denormalized[1:12],data_test)*100)
## 
## MAPE Neural Network Out Sample =  11.10248
cat("\nRMSE Neural Network Out Sample = ",RMSE(forecast_denormalized[1:12],data_test))
## 
## RMSE Neural Network Out Sample =  5746.719
cat("\nSMAPE Neural Network Out Sample = ",smape(data_test,forecast_denormalized[1:12])*100)
## 
## SMAPE Neural Network Out Sample =  11.88043

7. Kesimpulan

Berdasarkan perbandingan yang telah dilakukan dapat diketahui bahwa ARIMA (1,1,0) + Outlier 53 lebih baik dalam memprediksi data insample karena memiliki nilai RMSE, MAPE, dan SMAPE yang lebih kecil. Walaupun demikian, dapat diketahui bahwa metode Neural Network (NN) lebih baik dalam memprediksi data outsample karena memiliki nilai RMSE, MAPE, dan SMAPE yang lebih kecil. Sehingga dapat disimpulkan bahwa ARIMA (1,1,0) + Outlier 53 lebih baik dalam memprediksi harga bawang merah sedangkan Neural Network (NN) lebih baik dalam meramalkan harga bawang merah.