Artificial Neural Network (ANN)
Artificial Neural Networks (Jaringan Syaraf Tiruan) adalah model yang terinspirasi oleh bagaimana neuran dalam otak manusia bekerja. Tiap neuron saling berhubungan dan informasi mengalir dari setiap neuron. Tiap neuron menerima input dan melakukan operasi dot dengan sebuah bobot, menjumlahkan bobot, dan menambahkan bias. Hasil dari operasi ini dijadikan parameter dari activation function yang akan dijadikan output dari neuron tersebut.
Pada umumnya, jaringan syaraf terdiri dari tiga jenis lapisan, yaitu lapisan input, lapisan tersembunyi (hidden layers), dan lapisan output. Setiap lapisan terdisi atas satu atau beberapa unit neuron yang mempunyai sebuah fungsi aktivasi yang menentukan keluaran dari unit tersebut.
Keunggulan neural network dibandingkan metode tradisional lainnya adalah kemampuannya dalam menangani hubungan yang lebih kompleks dan non-linier antara variabel input dan output. Dengan pelatihan yang tepat menggunakan algoritma backpropagation, jaringan syaraf dapat menyesuaikan bobot dan biasnya untuk mengoptimalkan prediksi.
Seorang peneliti ingin memprediksi data perjalanan penumpang udara internasional 1 tahun ke depan.
library(readxl) # membaca data
library(tseries) # ubah data dalam format time series
library(ggplot2) # visualisasi plot time series
library(neuralnet) # neural network model
df <- read_excel("data_penumpang.xlsx")
# Ubah ke format waktu
ts_data <- ts(df$Data, start=c(1949, 1), frequency=12)
str(ts_data)
## Time-Series [1:96] from 1949 to 1957: 112 115 145 171 196 204 242 284 118 126 ...
ts_data
## Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 1949 112 115 145 171 196 204 242 284 118 126 150 180
## 1950 196 188 233 277 132 141 178 193 236 235 267 317
## 1951 129 135 163 181 235 227 269 313 121 125 172 183
## 1952 229 234 270 318 135 149 178 218 243 264 315 374
## 1953 148 170 199 230 264 302 364 413 148 170 199 242
## 1954 272 293 347 405 136 158 184 209 237 259 312 355
## 1955 119 133 162 191 211 229 274 306 104 114 146 172
## 1956 180 203 237 271 118 140 166 194 201 229 278 306
summary(ts_data)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 104.0 156.0 200.0 213.7 264.8 413.0
Data memiliki rata-rata 213.7, median 200, nilai minimal 104, dan nilai maksimal 413.
Berdasarkan gambar di atas, plot menunjukkan tren musiman yang kuat dari tahun ke tahun.
Lag 1 dan lag 2 ditambahkan sebagai variabel independen. Kemudian,
semua variabel dinormalisasi dengan standard scaling. Secara
matematis, standard scaling didefiniskan sebagai berikut. \[
X_{scaled} = \frac{X-\mu}{\sigma}
\] Keterangan:
\(X\) =
nilai asli variabel
\(\mu\) =
nilai rata-rata variabel
\(\sigma\) = simpangan baku variabel
Melalui scaling, distribusi data tidak dibatasi pada rentang tertentu, melainkan dipusatkan di sekitar nol dengan sebaran yang seragam berdasarkan simpangan bakunya.
y <- as.numeric(ts_data)
embed_mat <- embed(y, 3)
colnames(embed_mat) <- c("y", "lag1", "lag2")
# Scaling data
df_embed <- as.data.frame(scale(embed_mat))
head(df_embed)
## y lag1 lag2
## 1 -0.9955955 -1.3862309 -1.3947875
## 2 -0.6301900 -0.9653469 -1.3529616
## 3 -0.2788385 -0.6005807 -0.9347034
## 4 -0.1664060 -0.2498439 -0.5722129
## 5 0.3676482 -0.1376082 -0.2236643
## 6 0.9579186 0.3955116 -0.1121288
Data dibagi menjadi data training dan testing dengan proporsi 80% pada data training dan 20% data testing
n <- floor(0.8*nrow(df_embed))
train <- as.data.frame(df_embed[1:n,])
test <- na.omit(as.data.frame(df_embed[n+1:nrow(df_embed),]))
Jumlah baris train = 75
Jumlah baris test = 19
set.seed(42)
iter <- 15
hidden <- 3
model <- neuralnet(y ~ lag1 + lag2, data=train, hidden=hidden, rep=iter)
pred_train <- model$net.result[[iter]]
# Prediksi Test
pred_test <- compute(model, test[, c("lag1","lag2")])$net.result[,1]
Setelah pembagian data, dilakukan pemodelan data menggunakan model neural network dengan 3 hidden layer sebanyak 15 iterasi. Model tersebut digunakan untuk peramalan data test.
Tahap post-processing dilakukan dengan pengembalian scaling data untuk mendapat nilai asli dari hasil peramalan data train dan test. Pengembalian scaling data dilakukan dengan mengambil mean dan standar deviasi yang digunakan saat melakukan scaling, kemudian membuat rumus inverse scaling.
scaler <- scale(embed_mat)
center <- attr(scaler, "scaled:center") # mean
scale_ <- attr(scaler, "scaled:scale") # std.s
inv_scale <- function(x) { # cukup proses kolom y
x[,1] * scale_[1] + center[1] # inverse scale = x*std - mean
}
pred_train_ori <- inv_scale(as.matrix(pred_train))
pred_test_ori <- inv_scale(as.matrix(pred_test))
Untuk mengukur performa model neural network digunakan dua ukuran, yaitu Root Mean Square Error (RMSE) dan Mean Absolute Percentage Error (MAPE). Nilai RMSE terendah menunjukkan hasil akurasi yang terbaik. Formula RMSE dan MAPE dirumuskan sebagai berikut.
RMSE (Root Mean Square Error) \[ RMSE = \sqrt{ \frac{1}{n} \sum_{i=1}^{n}(y_i - \hat{y}_i)^2} \]
MAPE (Mean Absolute Percentage Error) \[ MAPE = ( \frac{1}{n}\sum_{i=1}^{n}\left|\frac{y_i - \hat{y}_i}{y_i}\right| ) 100\% \]
Keterangan:
\(y_i\) = nilai
aktual data ke-i
\(\hat{y}_i\) =
nilai prediksi data ke-i
\(n\) =
banyak observasi
# evaluasi train
aktual_train <- ts_df[3:(n+2),2] # ambil 75 data mulai dari data ke-3 karena ada 2 lag
prediksi_train <- pred_train_ori
error_train <- aktual_train - prediksi_train
rmse_train <- sqrt(mean(error_train^2))
mape_train <- mean(abs(error_train/aktual_train)) * 100
# evaluasi test
aktual_test <- na.omit(ts_df[n+3:nrow(ts_df),2])[1]
prediksi_test <- pred_test_ori
error_test <- aktual_test - prediksi_test
rmse_test <- sqrt(mean(error_test^2))
mape_test <- mean(abs(error_test/aktual_test)) * 100
RMSE
RMSE NN train = 49.9159007
RMSE NN
test = 50.6784631
Dari model neural network, diperoleh nilai RMSE train = 49.92 dan RMSE test = 50.68. Nilai RMSE train yang sedikit lebih kecil dari RMSE test menunjukkan tidak adanya masalah yang terlalu serius dan dapat dikatakan cukup wajar.
MAPE
MAPE NN train = 14.9786888 %
MAPE NN
test = 17.9360719%
Dari model neural network, diperoleh nilai MAPE train 14.98% dan nilai MAPE test = 17.94%. Dengan selisih yang kecil, yaitu sekitar 2.96%, dapat dikatakan bahwa tidak ada tanda overfitting yang serius. Selain itu, nilai MAPE test = 17.94 menunjukkan bahwa model cukup baik dalam memprediksi data.
hasil_train <- as.data.frame(cbind(aktual_train, prediksi_train, error_train))
hasil_test <- as.data.frame(cbind(aktual_test, prediksi_test, error_test))
colnames(hasil_train) = c("aktual", "prediksi", "error")
colnames(hasil_test) = c("aktual", "prediksi", "error")
hasil = rbind(hasil_train, hasil_test)
hasil
## aktual prediksi error
## 1 145 165.2063 -20.2063411
## 2 171 164.6155 6.3845426
## 3 196 194.3447 1.6553080
## 4 204 217.4710 -13.4710253
## 5 242 244.3667 -2.3667129
## 6 284 252.5464 31.4535951
## 7 118 278.1471 -160.1470743
## 8 126 117.8976 8.1023617
## 9 150 170.5972 -20.5971537
## 10 180 176.4371 3.5628959
## 11 196 198.4549 -2.4549272
## 12 188 225.8951 -37.8950968
## 13 233 240.8369 -7.8368718
## 14 277 239.5254 37.4745977
## 15 132 272.2204 -140.2204189
## 16 141 140.1776 0.8223889
## 17 178 184.2060 -6.2059571
## 18 193 189.2397 3.7603496
## 19 236 224.3768 11.6231578
## 20 235 243.6742 -8.6741894
## 21 267 277.9602 -10.9601746
## 22 317 274.5484 42.4516132
## 23 129 292.2851 -163.2851308
## 24 135 132.0804 2.9195889
## 25 163 181.6968 -18.6968496
## 26 181 184.6672 -3.6672005
## 27 235 211.4292 23.5707627
## 28 227 232.8911 -5.8910505
## 29 269 277.9151 -8.9151476
## 30 313 268.4210 44.5790135
## 31 121 293.8291 -172.8290630
## 32 125 130.8277 -5.8276956
## 33 172 174.1168 -2.1167879
## 34 183 172.4251 10.5749059
## 35 229 219.8654 9.1345801
## 36 234 235.3948 -1.3948367
## 37 270 272.9839 -2.9839313
## 38 318 273.5611 44.4388903
## 39 135 294.0863 -159.0862885
## 40 149 132.2008 16.7992249
## 41 178 186.4416 -8.4415591
## 42 218 197.6622 20.3377835
## 43 243 231.9356 11.0644451
## 44 264 263.8216 0.1784322
## 45 315 280.4937 34.5063417
## 46 374 290.5290 83.4710231
## 47 148 138.5237 9.4762528
## 48 170 159.0064 10.9936223
## 49 199 197.5964 1.4035506
## 50 230 216.1774 13.8225965
## 51 264 249.4985 14.5015213
## 52 302 271.1217 30.8782512
## 53 364 291.4987 72.5012724
## 54 413 308.2830 104.7169511
## 55 148 147.6986 0.3014362
## 56 170 170.5379 -0.5379208
## 57 199 197.5964 1.4035506
## 58 242 216.1774 25.8225965
## 59 272 248.2930 23.7069651
## 60 293 279.1389 13.8611383
## 61 347 297.0959 49.9040968
## 62 405 305.5522 99.4478135
## 63 136 141.4309 -5.4309091
## 64 158 163.5470 -5.5469825
## 65 184 186.3837 -2.3836636
## 66 209 206.1229 2.8770539
## 67 237 235.4869 1.5131460
## 68 259 257.1767 1.8233291
## 69 312 276.6696 35.3304329
## 70 355 287.5145 67.4855129
## 71 119 139.0948 -20.0948141
## 72 133 146.0540 -13.0540388
## 73 162 170.8020 -8.8019845
## 74 191 182.6156 8.3843872
## 75 211 209.2910 1.7089951
## 76 229 230.4585 -1.4584548
## 77 229 256.5825 -27.5824977
## 78 229 279.2786 -50.2785703
## 79 229 280.1039 -51.1039459
## 80 229 125.7198 103.2802267
## 81 229 140.7242 88.2757502
## 82 229 175.0375 53.9625095
## 83 229 203.3978 25.6021655
## 84 229 209.5774 19.4225953
## 85 229 226.1254 2.8745678
## 86 229 263.7538 -34.7538426
## 87 229 279.1032 -50.1031598
## 88 229 134.8949 94.1051077
## 89 229 167.2186 61.7813788
## 90 229 197.2792 31.7207803
## 91 229 221.1693 7.8307113
## 92 229 224.6310 4.3689530
## 93 229 250.4343 -21.4342901
## 94 229 279.4590 -50.4589819
h <- 12
hasil_peramalan <- numeric(h)
lag1 <- tail(df_embed$y, 1)
lag2 <- tail(df_embed$y, 2)[1]
for(i in 1:h){
newdata <- data.frame(lag1 = lag1, lag2 = lag2)
pred <- compute(model, newdata)$net.result
hasil_peramalan[i] <- pred
# update lag
lag2 <- lag1
lag1 <- pred
}
hasil_peramalan_ori <- round(inv_scale(as.matrix(hasil_peramalan)))
hasil_peramalan_ori
## [1] 280 279 279 279 279 279 279 279 279 279 279 279
Model Jaringan Syaraf Tiruan yang dibangun mampu memberikan hasil peramalan yang cukup baik, ditunjukkan oleh nilai MAPE sebesar 14.98% pada data training dan 17.94% pada data testing. Selisih nilai kesalahan yang relatif kecil antara data training dan testing menunjukkan bahwa model tidak mengalami overfitting yang signifikan dan memiliki kemampuan generalisasi yang cukup baik.