Chapter Simple Exponential Smoothing ditutup dengan temuan yang mengganjal: pada deret beras yang bertren, sebelas prediksi SES meleset searah tanpa kecuali, dan forecast Januari-nya tertinggal 602.69 Rp dari garis regresi — satu angka level memang tidak cukup untuk deret yang bergerak searah. Holt memperbaiki kekurangan itu dengan komponen slope yang diperbarui berdampingan dengan level, sehingga model mengetahui tidak hanya di mana deret berada, tetapi juga ke arah mana deret melangkah. Holt-Winters melengkapi keluarga ini dengan komponen musiman agar lonjakan kuartal pada penjualan es krim ikut diramal. Chapter ini mengerjakan rekursi Holt dengan tangan pada deret kecil yang bertren, mengujinya pada beras dari dua sisi — kecocokan dengan regresi tren dan MAE out-of-sample — lalu menjalankan Holt-Winters pada es krim dan menutup section dengan panduan memilih metode perata.
Menambahkan Komponen Slope #
SES hanya menyimpan satu angka, dan hukumannya sudah terukur: pada deret berslope b, level SES tertinggal stabil di sekitar b × (1 − α) / α — untuk beras dengan α = 0.3, sekitar 424.25 Rp di bawah data. Holt menambahkan komponen kedua bernama slope: model kini menyimpan level Lt (di mana deret berada) dan slope bt (seberapa cepat deret bergerak), keduanya diperbarui setiap periode lewat parameter pemulus masing-masing. Tiga rumusnya:
Lt = α × Yt + (1 − α) × (Lt-1 + bt-1)
bt = β × (Lt − Lt-1) + (1 − β) × bt-1
ŷt+h = Lt + h × btRumus level terbaca seperti rekursi SES dengan satu perubahan kunci: sisi (1 − α) tidak lagi menempel pada level kemarin Lt-1, melainkan pada perkiraan satu-langkah Lt-1 + bt-1 — level kemarin ditambah slope yang diantisipasi terjadi. Kenaikan yang memang diharapkan tidak dihitung sebagai kejutan, sehingga level tidak terus tertinggal hanya karena deret menanjak; tren terserap kembali ke dalam pembaruan level, dan bias searah yang menimpa SES pada data bertren hilang dari akarnya.
Rumus slope memperlakukan kemiringan seperti level: slope baru adalah β bagian perubahan level yang baru terjadi (Lt − Lt-1) ditambah (1 − β) slope lama. Parameter β adalah laju penyesuaian slope; karena arah pergerakan biasanya lebih stabil daripada posisi, β lazim dipilih lebih kecil daripada α. Rumus ketiga adalah perubahan paling terasa bagi pengguna: forecast SES berupa angka tunggal yang sama untuk semua horizon, sedangkan forecast Holt berupa garis — setiap horizon h menambahkan h kali slope, sehingga prediksi satu bulan, tiga bulan, dan satu tahun ke depan tidak lagi sama.
Contoh Manual: Pesanan Nasi Kotak Katering #
Katering Bu Sari (fiktif) mencatat pesanan nasi kotak selama tujuh minggu pertama membuka layanan; pelanggan terus bertambah sehingga deret menanjak. Slope regresi waktunya tepat 10 kotak per minggu — jauh dari datar, kandidat yang salah untuk SES dan tepat untuk Holt:
| Minggu | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| Pesanan (kotak) | 120 | 132 | 138 | 152 | 158 | 172 | 180 |
Inisialisasi Holt membutuhkan dua angka — level dan slope — dan dua observasi pertama cukup untuk keduanya: L2 = Y2 = 132 serta b2 = Y2 − Y1 = 12, lalu rekursi berjalan mulai minggu ketiga. Kita pakai α = 0.5 dan β = 0.4. Tiga langkah pertama dihitung terbuka (nilai penuh dibawa sepanjang perhitungan; tampilan dibulatkan ke dua desimal):
alpha = 0.5, beta = 0.4, inisialisasi L2 = 132, b2 = 12
t=3 : L3 = 0.5 × 138 + 0.5 × (132 + 12) = 69.00 + 72.00 = 141.00
b3 = 0.4 × (141 − 132) + 0.6 × 12 = 3.60 + 7.20 = 10.80
t=4 : L4 = 0.5 × 152 + 0.5 × (141 + 10.80) = 76.00 + 75.90 = 151.90
b4 = 0.4 × (151.90 − 141) + 0.6 × 10.80 = 4.36 + 6.48 = 10.84
t=5 : L5 = 0.5 × 158 + 0.5 × (151.90 + 10.84) = 79.00 + 81.37 = 160.37
b5 = 0.4 × (160.37 − 151.90) + 0.6 × 10.84 = 3.39 + 6.50 = 9.89Tabel kerja lengkap tujuh minggu, lengkap dengan prediksi satu-langkah ŷt yang dibuat dari state minggu sebelumnya:
t Yt ŷt satu-langkah Lt bt
2 132 - 132.00 12.00
3 138 144.00 141.00 10.80
4 152 151.80 151.90 10.84
5 158 162.74 160.37 9.89
6 172 170.26 171.13 10.24
7 180 181.37 180.69 9.97
forecast minggu 8 = L7 + b7 = 180.69 + 9.97 = 190.65
forecast minggu 9 = L7 + 2 × b7 = 180.69 + 19.93 = 200.62Dua komponen bekerja seperti dirancang. Slope bt berdiam di sekitar 10 — model menemukan arah yang sama dengan regresi — dan level Lt menempel pada data tanpa tertinggal: pada minggu ke-7, L7 = 180.69 berbanding Y7 = 180. Prediksi satu-langkah meleset −6.00, +0.20, −4.74, +1.74, −1.37 — kecil dan campuran tanda. SES dengan α = 0.5 pada deret yang sama menghasilkan error +12, +20, +16, +22, +19: semuanya positif, gejala satu tanda yang sama dengan beras pada chapter sebelumnya, karena prediksi SES selalu berada di bawah data yang menanjak.
Di ujung deret, forecast minggu 8 memisahkan kedua model dengan tuntas. SES memberi 170.50; Holt memberi 190.65 — jarak 20.15 kotak. Jarak itu terurai dua sumber: level SES tertinggal 10.19 di bawah level Holt (nyaris tepat lag b × (1 − α) / α = 10 yang dijanjikan rumus ketertinggalan SES), dan SES tidak menambahkan slope 9.97 ke prediksinya. SES tertinggal dua kali pada deret bertren; Holt menutup kedua celah sekaligus.
Holt pada Harga Beras #
Kode berikut memasang Holt pada dua belas bulan beras dengan parameter yang sama dengan contoh manual — α = 0.5, β = 0.4 — lalu memasang model kedua hanya pada sepuluh bulan pertama untuk keperluan evaluasi (dokumentasi kelas Holt tersedia di statsmodels.org
):
import numpy as np
from statsmodels.tsa.holtwinters import Holt
beras = np.asarray([12500, 12800, 12700, 13100, 13400, 13300,
13600, 13900, 13800, 14200, 14500, 14400], dtype=float)
latih = beras[:10] # train Jan-Okt, split dari chapter Evaluasi Forecast
penuh = Holt(beras, initialization_method="estimated").fit(
smoothing_level=0.5, smoothing_trend=0.4, optimized=False)
ujian = Holt(latih, initialization_method="estimated").fit(
smoothing_level=0.5, smoothing_trend=0.4, optimized=False)
prediksi = ujian.forecast(2)
mae = np.mean(np.abs(beras[10:] - prediksi))
lvl_awal = penuh.params["initial_level"]
slope_awal = penuh.params["initial_trend"]
print(f"level/slope awal : {lvl_awal:.2f} / {slope_awal:.2f}")
print(f"level/slope akhir : {penuh.level[-1]:.2f} / {penuh.trend[-1]:.2f}")
print(f"forecast t=13 Holt : {penuh.forecast(1)[0]:.2f}")
print(f"forecast t=13 regresi: 14698.48") # chapter Tren dan Musiman
print(f"prediksi Nov, Des : {prediksi[0]:.2f}, {prediksi[1]:.2f}")
print(f"MAE Holt (test) : {mae:.2f}")
print(f"MAE naive/mean/tren: 200 / 1120 / 140") # chapter Evaluasi ForecastOutput yang Dihasilkan:
level/slope awal : 12340.00 / 180.00
level/slope akhir : 14512.55 / 172.14
forecast t=13 Holt : 14684.69
forecast t=13 regresi: 14698.48
prediksi Nov, Des : 14315.87, 14496.21
MAE Holt (test) : 140.17
MAE naive/mean/tren: 200 / 1120 / 140Mari kita bedah kode di atas:
- Baris 6 (
latih): irisan sepuluh bulan pertama menyiapkan split train-test dari chapter Evaluasi Forecast, dipakai pada bagian berikutnya. - Baris 8-11 (
penuhdanujian): dua model Holt dipasang — satu pada seluruh dua belas bulan untuk forecast t=13, satu pada sepuluh bulan train untuk ujian;smoothing_leveldansmoothing_trendmematok α dan β, sedangkanoptimized=Falsemematikan optimasi sehingga hasil identik setiap dijalankan. - Baris 13-14 (
prediksidanmae): model train meramal dua bulan test, lalu MAE dihitung terhadap aktual Nov dan Des. - Baris 16-24 (variabel dan cetak): parameter pemulus, state akhir, forecast, dan hasil ujian dicetak dengan pembulatan dua desimal.
Level dan slope awal 12340.00 dan 180.00 bukan angka pilihan bebas: initialization_method="estimated" membuat statsmodels menaksir titik berangkat lewat regresi waktu pada sepuluh observasi pertama — pada beras, hasilnya persis model tren train dari chapter Evaluasi Forecast (b0 = 12340, b1 = 180). Holt secara harfiah berangkat dari garis tren itu, lalu memperbaruinya bulan demi bulan dengan bobot yang menekankan bulan-bulan akhir.
Setelah dua belas pembaruan, level berakhir di 14512.55 dan slope di 172.14 — slope dekat dengan 181.82 milik regresi, sedikit lebih kecil karena Desember tidak melanjutkan kenaikan (14400 di bawah 14500). Forecast bulan ketiga belas: 14684.69, berbanding 14698.48 dari regresi tren — selisih 13.79 Rp atau sekitar 0.09 persen. Dua jalur yang tidak berbagi mekanisme — kuadrat terkecil atas dua belas bulan berbobot sama, lawan rekursi berbobot geometris — tiba di angka yang nyaris sama karena keduanya membaca struktur yang sama: level sekitar 14.5 ribu dan slope sekitar 172 sampai 182 Rp per bulan. Struktur yang nyata bertahan lintas metode; kesepakatan ini juga menegaskan bahwa forecast SES 14095.79 pada chapter sebelumnya tertinggal bukan karena datanya sulit, melainkan karena alatnya kehilangan komponen arah.
Ujian Out-of-Sample: Holt Lawan Baseline #
Kecocokan dengan regresi masih diukur di atas data latih. Ujian yang berbicara tentang masa depan tetap split kronologis chapter Evaluasi Forecast: model dibentuk hanya dari Januari sampai Okt, lalu meramal Nov dan Des. Holt versi train memprediksi 14315.87 dan 14496.21; aktual 14500 dan 14400, error +184.13 dan −96.21 — dua tanda, tanpa bias searah, tanda bahwa komponen slope menangkap struktur. MAE 140.17 Rp menempatkan Holt di tabel pembanding:
| Model | MAE dua bulan test (Rp) |
|---|---|
| tren linear | 140.00 |
| Holt (α = 0.5, β = 0.4) | 140.17 |
| naive | 200.00 |
| mean | 1120.00 |
Angkanya jujur: Holt tidak mengalahkan tren linear. Selisih 0.17 Rp adalah seri praktis, dan dua bulan ujian terlalu pendek untuk memutuskan lewat selisih sekecil itu. Prediksi Holt nyaris menempel pada prediksi tren (14320 dan 14500) karena titik berangkatnya memang garis tren itu; pada deret pendek yang nyaris lurus, keduanya menyimpulkan hal yang sama. Kerumitan tambahan Holt belum membeli kemenangan pada data ini — pembayarannya datang di tempat lain: model ini memperbarui level dan slope setiap bulan, sehingga ketika tren berubah arah di tengah jalan (kebijakan harga baru, musim panen) Holt menyesuaikan tanpa memasang ulang satu garis untuk seluruh riwayat, dan jalurnya bermuara alami ke Holt-Winters, sesuatu yang tidak dimiliki regresi. Pelajaran chapter Evaluasi Forecast tetap berdiri: model terbaik ditentukan data ujian, bukan kerumitan rumus.
Holt-Winters: Level, Slope, dan Musiman #
Dua komponen menyelesaikan beras; es krim masih menyisakan satu pola besar yang belum tersentuh — musiman yang berulang tiap empat kuartal. Holt-Winters menambah state ketiga, St, satu untuk setiap posisi musim: empat angka musiman untuk data kuartalan, yang bergilir dipakai dan diperbarui mengikuti kalender. Dengan m sebagai panjang periode musiman, bentuk additive-nya (pembahasan keluarga lengkap tersedia di NIST/SEMATECH e-Handbook ):
Lt = α × (Yt − St-m) + (1 − α) × (Lt-1 + bt-1)
bt = β × (Lt − Lt-1) + (1 − β) × bt-1
St = γ × (Yt − Lt-1 − bt-1) + (1 − γ) × St-m
ŷt+1 = Lt + bt + St-m+1Setiap rumus memindahkan satu ide yang sudah kita kenal. Level kini membandingkan observasi yang telah dibebaskan dari musiman — Yt − St-m, dugaan musiman untuk posisi ini dari putaran sebelumnya — sehingga lonjakan kuartal panas tidak dibaca sebagai kenaikan level, dan sebaliknya. Slope tidak berubah dari Holt. State musiman diperbarui hanya saat posisinya tiba: deviasi musiman terbaru (Yt dikurangi perkiraan satu-langkah Lt-1 + bt-1) dicampur dengan state lama posisi yang sama memakai parameter pemulus γ — satu-satunya parameter baru. Forecast menjumlahkan ketiganya: level, satu langkah slope, dan musiman posisi target; horizon berikutnya menambah slope lagi dan memakai musiman posisi masing-masing.
Bentuk multiplicative mengganti penjumlahan musiman dengan perkalian: St menjadi indeks di sekitar 1 — seperti indeks 1.45 untuk Q2 dari chapter Tren dan Musiman — dan forecast mengalikan level dan slope dengan indeks posisi target. Pemilihan antara keduanya mengikuti diskusi amplitudo pada chapter Time Series Decomposition: amplitudo musiman yang kira-kira konstan meski level naik — es krim kita, rentang 200 lalu 205 porsi — memilih additive; amplitudo yang membesar sebanding level memilih multiplicative (seasonal="mul" di statsmodels).
Holt-Winters pada Penjualan Es Krim #
Kode berikut memasang Holt-Winters additive pada delapan kuartal es krim dengan α = 0.5, β = 0.4, dan γ = 0.4 (dokumentasi kelas ExponentialSmoothing di statsmodels.org
):
import numpy as np
from statsmodels.tsa.holtwinters import ExponentialSmoothing
es_krim = np.asarray([180, 320, 260, 120, 190, 335, 275, 130], dtype=float)
hasil = ExponentialSmoothing(es_krim, trend="add", seasonal="add",
seasonal_periods=4,
initialization_method="estimated").fit(
smoothing_level=0.5, smoothing_trend=0.4, smoothing_seasonal=0.4,
optimized=False)
lvl_awal = hasil.params["initial_level"]
tren_awal = hasil.params["initial_trend"]
musiman_awal = ", ".join(f"{s:+.1f}" for s in hasil.params["initial_seasons"])
musiman_akhir = ", ".join(f"{s:+.1f}" for s in hasil.season[-4:])
print(f"level awal / tren awal : {lvl_awal:.2f} / {tren_awal:.3f}")
print(f"musiman awal Q1-Q4 : {musiman_awal}")
print(f"level akhir / tren : {hasil.level[-1]:.2f} / {hasil.trend[-1]:.2f}")
print(f"musiman akhir Q1-Q4 : {musiman_akhir}")
print("fitted tahun 2 :", " ".join(f"{v:.2f}" for v in hasil.fittedvalues[4:]))
print("forecast tahun 3 Q1-Q4 :", " ".join(f"{v:.2f}" for v in hasil.forecast(4)))Output yang Dihasilkan:
level awal / tren awal : 220.00 / 3.125
musiman awal Q1-Q4 : -40.0, +100.0, +40.0, -100.0
level akhir / tren : 235.74 / 1.98
musiman akhir Q1-Q4 : -37.5, +101.5, +38.5, -104.8
fitted tahun 2 : 180.53 327.17 275.06 139.23
forecast tahun 3 Q1-Q4 : 200.26 341.21 280.17 142.55Mari kita bedah kode di atas:
- Baris 6-10 (
hasil):trend="add"danseasonal="add"memilih bentuk additive,seasonal_periods=4menyatakan satu putaran musiman, dan tiga parameter pemulus dipatok denganoptimized=Falseagar hasil deterministik. - Baris 12-15 (empat variabel): inisialisasi diambil dari
params, sedangkan state level, trend, dan musiman di akhir deret diambil dari atributlevel,trend, danseason. - Baris 17-22 (cetak): fitted tahun kedua dan forecast empat kuartal tahun ketiga dicetak dengan pembulatan dua desimal.
Inisialisasinya terbaca tanpa kotak gelap: dengan delapan observasi, statsmodels memakai bentuk sederhana — level awal 220.00 (rata-rata tahun pertama), tren awal 3.125 (rata-rata kenaikan antar-tahun dibagi empat), dan musiman awal −40, +100, +40, −100 (deviasi kuartal tahun pertama terhadap 220). Semua angka itu sudah pernah kita hitung di chapter Tren dan Musiman dan Time Series Decomposition. Setelah delapan kuartal pembaruan, level berakhir di 235.74 — dekat tren MA terpusat 232.5 di ujung data — tren di 1.98 porsi per kuartal, dan musiman di −37.5, +101.5, +38.5, −104.8, nyaris kembaran komponen −38.125, +103.75, +38.75, −104.375 dari dekomposisi klasik.
Nilai fitted tahun kedua — prediksi satu-langkah — adalah 180.53, 327.17, 275.06, 139.23, berbanding aktual 190, 335, 275, 130: error +9.47, +7.83, −0.06, −9.23 dengan MAE 6.65 porsi, sekitar 2.9 persen dari rata-rata tahun kedua 232.5. Pola errornya informatif: model di bawah aktual pada Q1 dan Q2, lalu di atas pada Q4, karena state musiman warisan tahun pertama belum selesai menyesuaikan dengan tahun kedua yang lebih tinggi — γ = 0.4 memindahkan state sekitar 40 persen setiap kali posisinya tiba. Error tetap campuran tanda dan mengecil; tidak ada gejala satu arah seperti SES pada deret bertren.
Forecast empat kuartal tahun ketiga: 200.26, 341.21, 280.17, 142.55. Rumus forecast bisa diperiksa langsung pada kuartal pertama: 235.74 + 1.98 − 37.46 = 200.26. Cerita empat angka itu dibandingkan dengan pola yang sudah diterbitkan chapter-chapter sebelumnya:
- Puncak tetap di Q2: 341.21, melampaui rata-rata puncak 327.5 dan realisasi 335 pada tahun kedua.
- Lembah tetap di Q4: 142.55, kuartal terendah, dengan state musiman Q4 sebesar −104.8 yang hampir persis komponen −104.375 dari dekomposisi.
- Setiap posisi naik dibanding tahun kedua — +10.26, +6.21, +5.17, +12.55 — drift naik yang konsisten dengan slope positif; tren akhir 1.98 porsi per kuartal lebih landai daripada 3.33 hasil dekomposisi karena kenaikan tahun kedua terkonsentrasi di awal tahun.
- Rentang puncak-ke-lembah forecast 341.21 − 142.55 = 198.66, dekat rentang musiman 208.125 dari dekomposisi.
Satu detail implementasi perlu diungkap agar hitungan ulang Anda tidak tampak salah: prediksi Q4 menurut rumus baku — level ditambah empat kali slope ditambah musiman Q4 termutakhir — adalah 138.86, sedikit di bawah keluaran statsmodels 142.55. Untuk horizon yang tepat satu putaran musiman penuh, implementasi statsmodels 0.14 memakai state musiman dari satu putaran sebelum termutakhir; selisih 3.69 porsi ini tidak memindahkan letak lembah, dan seluruh kesimpulan di atas tetap berdiri untuk kedua versi angka.
Holt-Winters pada dasarnya adalah dekomposisi yang bisa meramal: komponen yang dihitung chapter Time Series Decomposition secara historis kini diperbarui rekursif dan diekstrapolasi ke depan. Dengan data hanya dua putaran, tiga parameter tetap tanpa optimasi adalah pilihan yang disengaja; pada riwayat lima tahun ke atas, γ akan menyerap variasi musiman lintas tahun dan optimasi parameter mulai layak dijalankan sebelum model dipercaya.
Panduan Memilih Metode Perata #
Tiga chapter terakhir melengkapi alat deret waktu yang kita kumpulkan sejak chapter pengenalan. Pemilihan metode mengikuti pola pada data, dan pola itu diperiksa lebih dulu — line chart untuk bentuk umum, perbandingan mean paruh awal lawan paruh akhir untuk stasioneritas, indeks musiman untuk kalender, dekomposisi untuk bedah komponen:
| Pola pada data | Metode yang tepat | Parameter |
|---|---|---|
| level kira-kira tetap, tanpa arah | SES | α |
| arah konsisten, tanpa musiman | Holt | α, β |
| arah dan musiman berulang | Holt-Winters | α, β, γ |
| musiman stabil, riwayat panjang | dekomposisi klasik atau STL | jendela MA |
| tren lurus sederhana, horizon pendek | regresi tren | b0, b1 |
Urutan pemeriksaan praktisnya dari yang paling sederhana: SES bila deret mendekati datar, Holt bila muncul arah konsisten, Holt-Winters bila musiman terverifikasi berulang minimal dua putaran. Setiap kenaikan kompleksitas wajib dibayar dengan kemenangan MAE out-of-sample melawan model yang lebih sederhana — semangat baseline dari chapter Evaluasi Forecast. Dengan itu kotak perkakas peramal dasar kita lengkap: SES untuk level, Holt untuk arah, Holt-Winters untuk kalender, dekomposisi untuk bedah, regresi untuk garis, dan evaluasi out-of-sample untuk mengadili semuanya secara adil. Section berikutnya, Statistika dengan Python, membawa alat-alat ini — bersama seluruh statistika yang kita kerjakan manual sejak mean pertama — ke dalam alur kerja kode yang sistematis: pandas menyiapkan deret panjang, matplotlib memeriksa pola sebelum metode dipilih, dan statsmodels menjalankan seluruh keluarga perata pada data berukuran nyata.