Kita sudah menempuh perjalanan yang panjang: membangun model deret, mengukurnya dengan metrik yang jujur, dan memvalidasinya dengan walk-forward yang menghormati arah waktu. Dengan bekal selengkap itu, mudah sekali tergelincir ke keyakinan bahwa peramalan bisa menjawab segalanya. Chapter penutup Section ini bergerak ke arah sebaliknya: memetakan dengan terbuka apa yang tidak bisa diberikan model secanggih apa pun — ketidakpastian yang menumpuk di horizon panjang, perubahan struktural yang memutus pola, angka tunggal yang menipu, dan pertanyaan kapan sebuah forecast masih layak menjadi dasar keputusan.

Interval yang Melebar di Horizon Panjang #

Model meramal dengan mengekstrapolasi pola yang dipelajarinya, dan setiap langkah ke depan menumpuk ketidakpastian baru di atas ketidakpastian langkah sebelumnya. Kekeliruan kecil hari ini terbawa ke ramalan besok; ramalan besok yang keliru menjadi pijakan hari ketiga, dan seterusnya. Pada chapter ARIMA kita sudah melihatnya sekilas — interval 95% melebar dari 25,2 gelas di hari pertama menjadi 39,4 gelas di hari ketujuh — dan sekarang kita dorong horizon-nya sampai dua pekan penuh supaya bentuknya terlihat utuh.

python
import numpy as np
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA

rng = np.random.default_rng(42)
n = 42
tanggal = pd.date_range("2025-01-06", periods=n, freq="D")
bobot_hari = np.array([0, 1, 2, 3, 8, 14, 11], dtype=float)
gelas = 40 + 0.6 * np.arange(n) + bobot_hari[tanggal.dayofweek] + rng.normal(0, 4.0, n)
deret = pd.Series(gelas.round().astype(int), index=tanggal, name="gelas")

model = ARIMA(deret, order=(1, 1, 1)).fit()
ramalan = model.get_forecast(steps=14)
tengah = ramalan.predicted_mean
interval = ramalan.conf_int(alpha=0.05)

lebar = interval.iloc[:, 1] - interval.iloc[:, 0]
hasil = pd.DataFrame(
    {
        "ramalan": tengah.round(1).values,
        "batas_bawah": interval.iloc[:, 0].round(1).values,
        "batas_atas": interval.iloc[:, 1].round(1).values,
        "lebar_95pct": lebar.round(1).values,
    },
    index=[f"hari ke-{i}" for i in range(1, 15)],
)
print(hasil.iloc[[0, 3, 6, 10, 13]])

Output yang Dihasilkan:

text
            ramalan  batas_bawah  batas_atas  lebar_95pct
hari ke-1      75.2         62.6        87.8         25.3
hari ke-4      73.0         55.5        90.6         35.1
hari ke-7      72.8         53.1        92.5         39.4
hari ke-11     72.8         50.7        94.9         44.2
hari ke-14     72.8         49.1        96.5         47.5

Mari kita baca hasilnya:

  1. lebar = interval.iloc[:, 1] - interval.iloc[:, 0] menghitung lebar interval di tiap horizon; iloc[[0, 3, 6, 10, 13]] mengambil hari ke-1, 4, 7, 11, dan 14 supaya pola pertumbuhannya mudah dibaca.
  2. Lebar tumbuh terus tanpa henti: 25,3 → 47,5 gelas, kira-kira sebanding dengan akar horizon — sifat khas proses yang bergerak acak bertahap. Ramalannya sendiri cepat diam di 72,8, jadi pertumbuhan itu murni ketidakpastian.
  3. Di hari ke-14, interval 49,1-96,5 hampir seluas seluruh rentang nilai yang pernah terjadi pada 42 hari data kita (41-81 gelas) — ramalan dua pekan ke depan nyaris tidak bisa membedakan hari sepi dari hari ramai.
  4. Pesan praktisnya: ramalan 1-3 hari masih tajam untuk keputusan harian; ramalan dua pekan hanya layak dibaca sebagai level kasar beserta rentang besar.

Perubahan Struktural dan Peristiwa Tak Terduga #

Semua model kita belajar dari satu dunia yang sama: 42 hari dengan tren, musiman mingguan, dan derau yang stabil. Dunia nyata bisa berganti rezim tanpa peringatan — kafe pesaing membuka di seberang jalan, harga bahan baku melonjak, aturan baru menutup keramaian, sampai peristiwa sekelas pandemi 2020. Model tidak memiliki mekanisme untuk “mengetahui” perubahan seperti itu; data latihnya seluruhnya berasal dari dunia lama. Kita simulasikan patahan semacam itu secara eksplisit: mulai Senin 10 Februari, permintaan turun 20 gelas per hari karena pesaing membuka kedai.

python
import numpy as np
import pandas as pd
from statsmodels.tsa.holtwinters import ExponentialSmoothing

rng = np.random.default_rng(42)
n = 42
tanggal = pd.date_range("2025-01-06", periods=n, freq="D")
bobot_hari = np.array([0, 1, 2, 3, 8, 14, 11], dtype=float)
gelas = 40 + 0.6 * np.arange(n) + bobot_hari[tanggal.dayofweek] + rng.normal(0, 4.0, n)
deret = pd.Series(gelas.round().astype(int), index=tanggal, name="gelas")

deret_patah = deret.copy()
deret_patah.iloc[-7:] = deret_patah.iloc[-7:] - 20

latih = deret.iloc[:-7]
hw = ExponentialSmoothing(
    latih, trend="add", seasonal="add", seasonal_periods=7,
    initialization_method="estimated",
).fit()
ramalan = hw.forecast(7)

ujian_normal = deret.iloc[-7:]
ujian_patah = deret_patah.iloc[-7:]
mae_normal = np.abs(ramalan.values - ujian_normal.values).mean()
mae_patah = np.abs(ramalan.values - ujian_patah.values).mean()

naive_musiman = latih.iloc[-7:].values
mae_naive_patah = np.abs(naive_musiman - ujian_patah.values).mean()

banding = pd.DataFrame(
    {"aktual_normal": ujian_normal.values,
     "aktual_patah": ujian_patah.values,
     "ramalan_hw": ramalan.round(1).values},
    index=ujian_normal.index,
)
print(banding)
print()
print(f"MAE Holt-Winters tanpa perubahan : {mae_normal:.2f} gelas")
print(f"MAE Holt-Winters dengan patahan  : {mae_patah:.2f} gelas")
print(f"MAE naive musiman dengan patahan : {mae_naive_patah:.2f} gelas")

Output yang Dihasilkan:

text
            aktual_normal  aktual_patah  ramalan_hw
2025-02-10             66            46        62.2
2025-02-11             62            42        63.6
2025-02-12             61            41        67.2
2025-02-13             63            43        67.2
2025-02-14             74            54        71.8
2025-02-15             81            61        78.0
2025-02-16             78            58        78.4

MAE Holt-Winters tanpa perubahan : 3.06 gelas
MAE Holt-Winters dengan patahan  : 20.53 gelas
MAE naive musiman dengan patahan : 16.00 gelas

Mari kita baca hasilnya:

  1. deret_patah.iloc[-7:] = deret_patah.iloc[-7:] - 20 membangun dunia uji yang berbeda: tujuh hari terakhir dipangkas 20 gelas, sementara 35 hari data latih dibiarkan utuh — persis keadaan model saat dunia berganti di tengah jalan.
  2. MAE Holt-Winters melonjak dari 3,06 ke 20,53 gelas — hampir tujuh kali lipat. Model juara kita tidak rusak, tidak salah koding, dan baru divalidasi kemarin; ia hanya mewarisi dunia yang sudah tidak berlaku.
  3. Peringkat pun terbalik: naive musiman yang tadinya kalah (6,29 lawan 3,06 pada chapter Evaluasi Forecasting) kini mencatat 16,00, lebih baik daripada model. Tidak ada pemenang sejati — semua peramal sama-sama buta terhadap perubahan yang informasinya belum ada di data.
  4. Pelajaran penting justru di luar angka: keunggulan backtest tidak pernah menjamin masa depan, dan sistem yang cepat sadar (monitoring galat, latih ulang segera) lebih berharga daripada model yang lebih rumit.

Angka Tunggal Menipu: Selalu Bawa Interval #

Katakanlah laporan mingguan kedai menulis “perkiraan Minggu 16 Februari: 72,8 gelas”. Angka itu terdengar presisi padahal menyembunyikan segalanya — interval 95%-nya adalah 53,1 sampai 92,5 gelas. Keputusan pesan bahan berubah total tergantung sisi mana yang dipakai: menyiapkan stok untuk 73 gelas berarti sekitar separuh kemungkinan kedai kehabisan bahan; menyiapkan 93 gelas (batas atas) menekan risiko kehabisan menjadi sekitar 2,5%, dengan sisa bahan sebagai harga pembelinya. Interval membuat taruhan seperti itu terlihat sebelum diputuskan; angka tunggal membiarkannya berlalu diam-diam.

KeputusanInformasi yang layak dipakai
Pesan bahan harianramalan 1-3 hari + batas atas interval pendek
Penjadwalan pegawai pekan depanramalan 7 hari + bentuk musiman mingguannya
Rencana ekspansi tahun depanbukan satu angka — skenario bersyarat (optimis, moderat, pesimis)

Kapan Forecast Layak Menjadi Dasar Keputusan #

Batas-batas di atas tidak berarti peramalan tidak berguna; mereka berarti peramalan harus dipakai pada tempat yang tepat. Empat kondisi berikut adalah saringannya:

KondisiContoh di kedai kitaKesimpulan
Horizon pendek dan pola stabilpesan bahan 1-3 hari ke depanlayak — interval masih sempit
Model mengungguli baseline di backtest dengan stabilLinearRegression 4,19 +/- 1,24 vs naive 5,12 +/- 1,67layak — nilai tambah terbukti
Lebar interval serasi dengan biaya keputusansisa bahan murah, pelanggan yang hilang mahallayak, lengkapi dengan pemantauan galat
Horizon panjang atau ada sinyal dunia bergantirencana tahunan, pesaing baru di kawasanjangan pakai satu angka — pakai skenario

Pola umumnya: makin pendek horizon, makin stabil pola, dan makin murah keputusan yang bisa diperbaiki, makin layak sebuah forecast dijadikan dasar keputusan. Sebaliknya, ketika taruhannya besar dan satu arah — menutup gerai, mengunci kontrak tahunan — forecast seharusnya menjadi salah satu masukan diskusi skenario, bukan satu-satunya angka di meja. Peramalan yang baik justru tahu kapan dirinya berhenti menjadi alat yang tepat.

Rangkuman #

  • Ketidakpastian menumpuk seiring horizon: lebar interval 95% ARIMA tumbuh dari 25,3 gelas di hari pertama menjadi 47,5 di hari ke-14 — meramalan jauh ke depan berarti berbicara semakin pelan tentang semakin sedikit informasi.
  • Perubahan struktural memutus semua model sekaligus: simulasi pesaing baru melonjakkan MAE Holt-Winters dari 3,06 ke 20,53 dan membalik peringkatnya terhadap naive musiman; tidak ada model yang bisa mengetahui dunia yang berganti.
  • Angka tunggal menipu — laporkan ramalan selalu bersama intervalnya supaya taruhan di balik keputusan (misalnya stok) terlihat.
  • Forecast layak menjadi dasar keputusan ketika horizon pendek, backtest mengungguli baseline secara stabil, dan lebar interval masih serasi dengan biaya keputusannya; untuk taruhan besar, pakai skenario dan penilaian manusia.

Demikian perjalanan Section Analisis Deret Waktu: dari indeks waktu pandas, stasioneritas, dan dekomposisi, sampai exponential smoothing, ARIMA, machine learning berfitur lag, evaluasi, dan validasi — ditutup dengan peta batas ini. Kejujuran tentang keterbatasan bukan akhir yang suram, melainkan tanda kedewasaan praktisi: kita tahu persis di mana alat berhenti bekerja dan di mana penilaian manusia mengambil alih. Perjalanan Course berikutnya bergerak ke Teknik Data Science Lanjutan — di dalamnya ada topik yang tumbuh langsung dari kebutuhan bab ini, misalnya Drift Detection untuk memantau pergeseran pola secara otomatis.

Referensi #

  1. statsmodels — Time Series Analysis (tsa)
  2. pandas — User Guide: Time Series