Bab 4 Single Moving Average
Simple Moving Average adalah suatu teknik pemulusan yang bertujuan untuk melihat grafik secara eksploratif dengan cara menghitung rata-rata periode sekarang dengan periode sebelumnya. Hal ini bertujuan untuk melihat pola dari suatu data tanpa dipengaruhi data harian yang bergerak lebih ekstrem.(Montgomery et al. 2008)
Rumus dari Simple Moving Average.
$ M_{T} = (y_{T} + y_{(T-1)} + … + y_{(T-n+1)})/n = 1/N $ T∑t=T−n+1yt
4.1 Validasi silang untuk SMA
Lakukan validasi silang untuk SMA dengan jumlah data latih awal sebesar 36. Selebihnya, data dibagi menjadi 15 fold sehingga ada (276−36)/15=16 observasi di tiap fold. Nilai M yang diuji adalah dari 2 sampai 30.
<-fcCV(weeklyCrude[,3],initialn=36,folds=15,type="SMA",start=2,end=30,dist=1) SMACV
Hasil dari prosedur tersebut:
<-SMACV[[3]] resultSMA
Buat boxplot untuk melihat mana M yang memnimumkan error
library(ggplot2)
ggplot(resultSMA,aes(x=M,y=MSE,group=M))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MSE tiap M untuk SMA")+
xlab("M")+ylab(" ")
Dapat dilihat bahwa error dari tiap parameter cenderung hampir sama di tiap nilai parameter M. Tetapi, keragaman dari boxplot cenderung terus meningkat jika nilai perameter bertambah dan garis median cenderung sama, atau sedikit naik, dalam setiap nilai parameter Bagaimana dengan MAPE?
library(ggplot2)
ggplot(resultSMA,aes(x=M,y=MAPE,group=M))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAPE tiap M untuk SMA")+
xlab("M")+ylab(" ")
Hasil cukup mirip dengan MSE, tetapi ada sedikit perbedaan. Nilai outlier pada boxplot MAPE cenderung meningkat seiring dengan bertambahnya nilai parameter M. Bagaimana dengan MAE:
ggplot(resultSMA,aes(x=M,y=MAE,group=M))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap M untuk SMA")+
xlab("M")+ylab(" ")
Garis median terlihat sedikit membesar saat nilai parameter M makin membesar. Nilai outlier di nilai M≤6 terlihat menggerombol, sedangkan makin banyak M salah satu outlier bergabung ke boxplot dan satu lagi menjauh dari boxplot. Boxplot membesar sehingga kesalahan lebih beragam makin besar M. Lanjutkan dengan buat agregasi:
<-resultSMA[,`.`(meanMSE=mean(MSE),
aggregateSMAvarMSE=var(MSE),
meanMAPE=mean(MAPE),
varMAPE=var(MAPE),
meanMAE=mean(MAE),
varMAE=var(MAE)), by=list(M)]
Jika dilihat nilai M yang meminimumkan mean dari MSE, MAPE, dan MAE:
::kables(list(
knitr::kable(head(setorder(aggregateSMA, meanMSE)[,c(1,2)],n=7)),
knitr::kable(head(setorder(aggregateSMA, meanMAPE)[,c(1,4)],n=7)),
knitr::kable(head(setorder(aggregateSMA, meanMAE)[,c(1,6)],n=7))
knitr
), )
|
|
|
Nilai MSE dan MAPE berurutan dari 2, 3, …, 8 dari yang terkecil hingga terbesar. Kemudian, hitung nilai M yang meminimumkan ragam MSE dan MAPE:
::kables(list(
knitr::kable(head(setorder(aggregateSMA, varMSE)[,c(1,3)],n=7)),
knitr::kable(head(setorder(aggregateSMA, varMAPE)[,c(1,5)],n=7)),
knitr::kable(head(setorder(aggregateSMA, varMAE)[,c(1,7)],n=7))
knitr
), )
|
|
|
Urutan nilai M yang meminimumkan ragam metrik-metrik tersebut sedikit berbeda. Walaupun M=2 memiliki performa terbaik dalam meminimumkan rata-rata metrik, M=3 sepertinya lebih baik dalam meminimumkan ragam dari metrik-metrik tersebut. Ini secara umum berarti kesalahan-kesalahan dari M=3 akan lebih sering mendekati suatu nilai tertentu, walaupun rataannya lebih besar dari M=2.
library(ggplot2)
ggplot(resultSMA,aes(x=iter,y=MSE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MSE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Boxplot untuk iterasi ke-9 (saat pandemi) dan ke-15 (pasca pandemi dan perang Rusia-Ukraina) memiliki rataan dan keragaman yang cukup besar dibandingkan iterasi lainnya pada data testing karena adanya fluktuasi yang ekstrem pada rentang waktu tersebut. Fluktuasi tersebut tidak cocok untuk SMA karena kurang dapat menangani data dengan tren.
library(ggplot2)
ggplot(resultSMA,aes(x=iter,y=MAPE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAPE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Boxplot untuk iterasi ke-15 ternyata tidak memiliki MAPE besar. Ini terjadi karena MAPE lebih memboboti observasi dengan nilai amatan kecil (COVID saat harga minyak turun) daripada saat nilai amatan besar (Ukraina-Rusia saat terjadi inflasi harga minyak).
library(ggplot2)
ggplot(resultSMA,aes(x=iter,y=MAE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Boxplot MAE per iterasi secara umum lebih mengikuti MSE.
4.2 DMA
Lakukan validasi silang untuk DMA dengan jumlah data latih awal sebesar 36. Selebihnya, data dibagi menjadi 15 fold sehingga ada (276−36)/15=16 observasi di tiap fold. Nilai M yang diuji adalah dari 2 sampai 16.
<-fcCV(weeklyCrude[,3],initialn=36,folds=15,type="DMA",start=2,end=16,dist=1) DMACV
Ambil hasil dari prosedur tersebut:
<-DMACV[[3]] resultDMA
Buat boxplot untuk melihat mana M yang memnimumkan error
library(ggplot2)
ggplot(resultDMA,aes(x=M,y=MSE,group=M))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MSE tiap M")+
xlab("M")+ylab(" ")
Dapat dilihat bahwa error dari tiap parameter cukup bervariasi di tiap iterasi. Hampir semua boxplot memiliki outlier yang sangat jauh dari kebanyakan observasi. Namun, terlihat bahwa di 9≤M≤12 boxplot lebih kecil, outlier lebih dekat, dan garis median lebih rendah dari boxplot lainnya. Ini berarti kesalahan di DMA dengan parameter tersebut biasanya rendah. Bagaimana dengan MAPE?
library(ggplot2)
ggplot(resultDMA,aes(x=M,y=MAPE,group=M))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAPE tiap M")+
xlab("M")+ylab(" ")
Hasil cukup mirip dengan MSE, tetapi ada sedikit perbedaan. Terlihat bahwa di 4≤M≤7, boxplot tidak memiliki outlier sama sekali. Justru, daerah yang sebelumnya dianggap baik, 9≤M≤12 memiliki beberapa outlier.
library(ggplot2)
ggplot(resultDMA,aes(x=M,y=MAE,group=M))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap M")+
xlab("M")+ylab(" ")
Boxplot MAE memiliki pola yang mengikuti MSE. Untuk memastikan, buat agregasi data error dari tiap nilai M:
<-resultDMA[,`.`(meanMSE=mean(MSE),
aggregateDMAvarMSE=var(MSE),
meanMAPE=mean(MAPE),
varMAPE=var(MAPE),
meanMAE=mean(MAE),
varMAE=var(MAE)), by=list(M)]
Jika dilihat nilai M yang meminimumkan mean dari MSE:
::kables(list(
knitr::kable(head(setorder(aggregateDMA, meanMSE)[,c(1,2)],n=7)),
knitr::kable(head(setorder(aggregateDMA, meanMAPE)[,c(1,4)],n=7)),
knitr::kable(head(setorder(aggregateDMA, meanMAE)[,c(1,6)],n=7))
knitr
), )
|
|
|
Tampak bahwa nilai M=10 cukup konsisten baik (ranking 2) di MSE, MAPE, dan MAE. Nilai M=11 juga memeinimumkan nilai harapan MAE dan MSE, tetapi tidad meminimumkan MSE. Bagaimana dengan ragam dari MSE, MAPE, dan MAE?
::kables(list(
knitr::kable(head(setorder(aggregateDMA, varMSE)[,c(1,3)],n=7)),
knitr::kable(head(setorder(aggregateDMA, varMAPE)[,c(1,5)],n=7)),
knitr::kable(head(setorder(aggregateDMA, varMAE)[,c(1,7)],n=7))
knitr
), )
|
|
|
M=10 dan 11 konsisten baik di bebrbagai metrik kecuali ragam dari MAPE.
Dapat juga dilihat iterasi mana yang memiliki error tinggi:
library(ggplot2)
ggplot(resultDMA,aes(x=iter,y=MSE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MSE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Error terbesar ada di iterasi 5, 9, 10, dan 15. Iterasi 15 merupakan perang Rusia-Ukraina. Ada apa di iterasi 9 dan 10 tersebut?
::kables(list(
knitr::kable(c(DMACV[[1]][5],DMACV[[2]][5]),col.names =
knitr"Range data iterasi 5"),
::kable(c(DMACV[[1]][9],DMACV[[1]][10],DMACV[[2]][10]),col.names =
knitr"Range data iterasi 9-10")
) )
|
|
Cari tanggal tanggal tersebut:
::kable(weeklyCrude[,2][c(101,116,165,181,196)]) knitr
Date |
---|
2018-12-07 |
2019-03-22 |
2020-02-28 |
2020-06-19 |
2020-10-02 |
Dari 2018-2019, harga turun. Tentu, 2020 adalah COVID. Namun, dari MSE terlihat bahwa performa DMA beragam. Di SMA, di iterasi tersebut boxplot hampir homogen memiliki nilai error tinggi. Ini berarti, ada nilai-nilai M tertentu yang dapat meminimukan error di data tren tersebut.
library(ggplot2)
ggplot(resultDMA,aes(x=iter,y=MAE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Profil boxplot MAE untuk iterasi relatif sama dengan boxplot MSE.
library(ggplot2)
ggplot(resultDMA,aes(x=iter,y=MAPE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAPE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
MAPE tidak memboboti error saat perang Ukraina dan Rusia, sama seperti saat SMA. Parameter terbaika dalah M=10 dan M=11.
4.3 SES
<-fcCV(weeklyCrude[,3],initialn=36,folds=15,type="SES",alphrange=seq(0.01,1,0.01)) SESCV
Masukkan hasilnya:
<-SESCV[[3]] resultSES
Karena ada 100 nilai alpha yang berbeda, tidak praktis untuk membuat boxplot untuk semua nilai tersebut. Bulatkan nilai alpha sebesar satu desimal (0.1,0.2,…) lalu buat boxplot:
ggplot(resultSES,aes(x=alpha,y=MSE,group=round(alpha,1)))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MSE tiap Alpha")+
xlab("Alpha")+ylab(" ")
Sepertinya, makin besar nilai alpha hasil pemulusan semakin baik. Ini berarti bobot observasi sekarang lebih besar dari observasi sebelumnya. :
ggplot(resultSES,aes(x=alpha,y=MAE,group=round(alpha,1)))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap Alpha")+
xlab("Alpha")+ylab(" ")
MAE nampaknya juga mengikuti pola tersebut.
ggplot(resultSES,aes(x=alpha,y=MAPE,group=round(alpha,1)))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap Alpha")+
xlab("Alpha")+ylab(" ")
MAPE juga mengikuti pola umum tersebut, tetapi nampaknya di α=0.5 nilai outlier minimum. Lakukan agregasi:
<-resultSES[,`.`(meanMSE=mean(MSE),
aggregateSESvarMSE=var(MSE),
meanMAPE=mean(MAPE),
varMAPE=var(MAPE),
meanMAE=mean(MAE),
varMAE=var(MAE)), by=list(alpha)]
Jika dilihat nilai α yang meminimumkan mean dari MSE, MAPE, MAE:
::kables(list(
knitr::kable(head(setorder(aggregateSES, meanMSE)[,c(1,2)],n=20)),
knitr::kable(head(setorder(aggregateSES, meanMAPE)[,c(1,4)],n=20)),
knitr::kable(head(setorder(aggregateSES, meanMAE)[,c(1,6)],n=20))
knitr
), )
|
|
|
Nilai-nilai dari tabel ini cukup kontradiktif. Untuk meminimumkan MSE, sebaiknya mengambil α sekitar 0.9. MAPE minimum di α 0.6 sampai 0.7, sedangkan MAE minimum di α 0.8. Bagaimana dengan ragam dari MSE, MAPE, dan MAE?
::kables(list(
knitr::kable(head(setorder(aggregateSES, varMSE)[,c(1,3)],n=7)),
knitr::kable(head(setorder(aggregateSES, varMAPE)[,c(1,5)],n=7)),
knitr::kable(head(setorder(aggregateSES, varMAE)[,c(1,7)],n=7))
knitr
), )
|
|
|
Ragam minimum MSE dan MAE minimum saat alpha mendekati 1, sedangkan ragam MAPE minimum saat alpha mendekati 0.5. Bagaimana dengan performa di tiap iterasi?
library(ggplot2)
ggplot(resultSES,aes(x=iter,y=MSE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MSE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Boxplot untuk iterasi ke-9 (saat pandemi) dan ke-15 (pasca pandemi dan perang Rusia-Ukraina) memiliki rataan dan keragaman yang cukup besar dibandingkan iterasi lainnya pada data testing karena adanya fluktuasi yang ekstrem pada rentang waktu tersebut. Fluktuasi tersebut tidak cocok untuk SES karena kurang dapat menangani data dengan tren.
library(ggplot2)
ggplot(resultSES,aes(x=iter,y=MAPE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAPE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Boxplot untuk iterasi ke-15 ternyata tidak memiliki MAPE besar. Ini terjadi karena MAPE lebih memboboti observasi dengan nilai amatan kecil (COVID saat harga minyak turun) daripada saat nilai amatan besar (Ukraina-Rusia saat terjadi inflasi harga minyak).
library(ggplot2)
ggplot(resultSES,aes(x=iter,y=MAE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Boxplot MAE per iterasi secara umum lebih mengikuti MSE. Sama seperti SMA, nilai error homogen buruk di iterasi 9 dan 16.
4.4 DES
Load fungsi:
<-fcCV(weeklyCrude[,3],initialn=36,folds=15,type="DES",alphrange=seq(0.1,1,0.1),betarange=seq(0.1,1,0.1)) DESCV
Masukkan hasilnya:
<-DESCV[[3]] resultDES
Karena parameter DES memiliki dua dimensi (alpha dan beta), cukup susah untuk menampilkan hasil optimalisasi parameter dalam suatu boxplot atau scatterplot. Oleh karena itu langsung buat agregasi:
<-resultDES[,`.`(meanMSE=mean(MSE),
aggregateDESvarMSE=var(MSE),
meanMAPE=mean(MAPE),
varMAPE=var(MAPE),
meanMAE=mean(MAE),
varMAE=var(MAE)), by=list(alphrange,betarange)]
Buat heatmap untuk melihat titik mana memiliki rata-rata MSE yang rendah:
ggplot(aggregateDES, aes(alphrange, betarange)) +
geom_tile(aes(fill = sqrt(meanMSE)), colour = "white") +
scale_fill_gradient(low="#FFFFE0",high="#DB0000")+
theme_minimal()+xlab("Alpha")+ylab("Beta")
Terlihat bahwa di beta lebih dari 0.1 rata-rata dari MSE relatif lebih besar. Bagaimana dengan ragam dari MSE (menggunakan skala log agar mudah dilihat).
ggplot(aggregateDES, aes(alphrange, betarange)) +
geom_tile(aes(fill = log(varMSE)), colour = "white") +
scale_fill_gradient(low="#FFFFE0",high="#DB0000")+
theme_minimal()+xlab("Alpha")+ylab("Beta")
Ragam dari MSE mengikuti rata-rata MSE. Di beta lebih dari 0.1, ragam MSE relatif besar. Tampak bahwa ragam MSE juga mengecil jika alpha mendekati 1. Bagaimana dengan MAPE?
ggplot(aggregateDES, aes(alphrange, betarange)) +
geom_tile(aes(fill = meanMAPE), colour = "white") +
scale_fill_gradient(low="#FFFFE0",high="#DB0000")+
theme_minimal()+xlab("Alpha")+ylab("Beta")
Pola cukup mengikuti MSE sebelumnya, tetapi tampaknya MAPE minimum di alpha mendekati 0.5. Bagaimana dengan ragamnya:
ggplot(aggregateDES, aes(alphrange, betarange)) +
geom_tile(aes(fill = sqrt(varMAPE)), colour = "white") +
scale_fill_gradient(low="#FFFFE0",high="#DB0000")+
theme_minimal()+xlab("Alpha")+ylab("Beta")
Ragam MAPE memiliki pola yang cukup beda. Ragam tersebut nampak minimum di diagonal antara Beta 0.5 dan alpha mendekati nol ke Beta 0.2 dan Alpha 0.25. Lakukan pemeringkatan:
ggplot(aggregateDES, aes(alphrange, betarange)) +
geom_tile(aes(fill = meanMAE), colour = "white") +
scale_fill_gradient(low="#FFFFE0",high="#DB0000")+
theme_minimal()+xlab("Alpha")+ylab("Beta")
Mean dari MAE memiliki pola sama seperti sebelumnya.
ggplot(aggregateDES, aes(alphrange, betarange)) +
geom_tile(aes(fill = sqrt(varMAE)), colour = "white") +
scale_fill_gradient(low="#FFFFE0",high="#DB0000")+
theme_minimal()+xlab("Alpha")+ylab("Beta")
Akar dari ragam MAE tampak minimum di diagonal dan di alpha 0.3 sampai 0.6.
::kables(list(
knitr::kable(head(setorder(aggregateDES, meanMSE)[,c(1,2,3)],n=5)),
knitr::kable(head(setorder(aggregateDES, meanMAPE)[,c(1,2,5)],n=5)),
knitr::kable(head(setorder(aggregateDES, meanMAE)[,c(1,2,7)],n=5))
knitr
), )
|
|
|
Nampak kombinasi alpha dan beta 0.4 dan 0.1 cukup baik dalam meminmumkan rataan error. Terlihat bahwa range alpha yang meminimumkan MSE dan MAPE kira kira 0.3 sampai 0.6. Pencarian lebih detail dapat dilakukan di daerah ini.
::kables(list(
knitr::kable(head(setorder(aggregateDES, varMSE)[,c(1,2,4)],n=7)),
knitr::kable(head(setorder(aggregateDES, varMAPE)[,c(1,2,6)],n=7)),
knitr::kable(head(setorder(aggregateDES, varMAE)[,c(1,2,8)],n=7))
knitr
), )
|
|
|
Terlihat bahwa kriteria peminimuman ragam MSE dan MAPE berbeda dari peminimuman rata-rata MSE dan MAPE.
Lakukan iterasi kedua untuk range α 0.3−0.6, β 0.01−0.2:
<-fcCV(weeklyCrude[,3],initialn=36,folds=15,type="DES",alphrange=seq(0.3,0.6,0.01),betarange=seq(0.01,0.2,0.01)) DESCV2
Masukkan hasilnya:
<-DESCV2[[3]] resultDES2
Langsung lakukan agregasi:
<-resultDES2[,`.`(meanMSE=mean(MSE),
aggregateDES2varMSE=var(MSE),
meanMAPE=mean(MAPE),
varMAPE=var(MAPE),
meanMAE=mean(MAE),
varMAE=var(MAE)), by=list(alphrange,betarange)]
Nilai nilai apa saja yang menimumkan MSE, MAPE, dan MAE:
::kables(list(
knitr::kable(head(setorder(aggregateDES2, meanMSE)[,c(1,2,3)],n=5)),
knitr::kable(head(setorder(aggregateDES2, meanMAPE)[,c(1,2,5)],n=5)),
knitr::kable(head(setorder(aggregateDES2, meanMAE)[,c(1,2,7)],n=5))
knitr
), )
|
|
|
Dan ragamnya.
::kables(list(
knitr::kable(head(setorder(aggregateDES2, varMSE)[,c(1,2,4)],n=5)),
knitr::kable(head(setorder(aggregateDES2, varMAPE)[,c(1,2,6)],n=5)),
knitr::kable(head(setorder(aggregateDES2, varMAE)[,c(1,2,8)],n=5))
knitr
), )
|
|
|
Plot iterasi mana yang susah:
ggplot(resultDES,aes(x=iter,y=MAPE,group=iter))+
geom_boxplot()+theme_bw()+
ggtitle("Boxplot MAPE tiap Iterasi")+
xlab("Iterasi")+ylab(" ")
Sama seperti sebelumnya, performa pemulusan buruk saat COVID.
4.5 Bantuan untuk kesimpulan
::kables(list(
knitr::kable(head(setorder(aggregateSMA, meanMSE)[,c(1,2)],n=1)),
knitr::kable(head(setorder(aggregateSMA, meanMAPE)[,c(1,4)],n=1)),
knitr::kable(head(setorder(aggregateSMA, meanMAE)[,c(1,6)],n=1))
knitrcaption="SMA"
), )
|
|
|
::kables(list(
knitr::kable(head(setorder(aggregateDMA, meanMSE)[,c(1,2)],n=1)),
knitr::kable(head(setorder(aggregateDMA, meanMAPE)[,c(1,4)],n=1)),
knitr::kable(head(setorder(aggregateDMA, meanMAE)[,c(1,6)],n=1))
knitrcaption="DMA"
), )
|
|
|
::kables(list(
knitr::kable(head(setorder(aggregateSES, meanMSE)[,c(1,2)],n=1)),
knitr::kable(head(setorder(aggregateSES, meanMAPE)[,c(1,4)],n=1)),
knitr::kable(head(setorder(aggregateSES, meanMAE)[,c(1,6)],n=1))
knitrcaption="SES"
), )
|
|
|
::kables(list(
knitr::kable(head(setorder(aggregateDES2, meanMSE)[,c(1,2,3)],n=1)),
knitr::kable(head(setorder(aggregateDES2, meanMAPE)[,c(1,2,5)],n=1)),
knitr::kable(head(setorder(aggregateDES2, meanMAE)[,c(1,2,7)],n=1))
knitrcaption="DES"
), )
|
|
|