Tugas Mata Kuliah Penambangan Data – Reproduksi Analisis Explainability Skforecast#
Nama: Zakaria Mujur Prasetyo
NIM: 240411100144
Mata Kuliah: Penambangan Data Kelas A
Sumber reproduksi: https://skforecast.org/0.15.1/user_guides/explainability.html
Pada tugas ini, saya mereproduksi studi kasus dari dokumentasi resmi Skforecast tentang model explainability pada data time series.
Kasus yang saya angkat adalah prediksi permintaan listrik harian di Victoria, Australia menggunakan ForecasterRecursive dan LGBMRegressor.
Saya memilih kasus ini karena relevan dengan topik penambangan data, khususnya pada aspek bagaimana model machine learning bisa dijelaskan hasilnya, bukan sekadar menghasilkan angka prediksi.
Pertanyaan tugas yang saya jawab dalam notebook ini:
Analisa prediksi tentang apa?
Bagaimana bentuk data trainingnya, apa input dan outputnya?
Apa itu lag?
Jelaskan proses analysis yang dilakukan dari kasus tersebut.
Daftar Isi#
Bagian A – Reproduksi Kode
Bagian B – Jawaban Pertanyaan Tugas
Bagian C – Ringkasan Akhir
1. Instalasi Library#
Pertama-tama, saya perlu menginstal beberapa library yang dibutuhkan.
Saya menjalankan notebook ini di Google Colab, jadi saya menginstal library di sini.
Kalau teman-teman menjalankan di localhost dan library-nya sudah terpasang, bagian ini bisa dilewati saja.
!pip install -q skforecast==0.15.1 lightgbm shap scikit-learn pandas numpy matplotlib
[notice] A new release of pip is available: 25.3 -> 26.1.2
[notice] To update, run: C:\Python314\python.exe -m pip install --upgrade pip
2. Import Library#
Setelah instalasi selesai, saya meng-import semua library yang saya butuhkan.
Library yang saya pakai mengikuti dokumentasi Skforecast, yaitu pandas untuk manipulasi data, matplotlib untuk visualisasi, shap untuk explainability, sklearn untuk evaluasi model, lightgbm sebagai algoritma machine learning, dan skforecast sebagai framework forecasting.
import warnings
warnings.filterwarnings("ignore")
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import shap
from lightgbm import LGBMRegressor
from sklearn.inspection import permutation_importance
from sklearn.inspection import PartialDependenceDisplay
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error
from skforecast.datasets import fetch_dataset
from skforecast.recursive import ForecasterRecursive
pd.set_option("display.max_columns", None)
pd.set_option("display.width", 120)
3. Mengambil Dataset#
Di sini saya mengambil dataset vic_electricity yang sudah disediakan oleh Skforecast.
Dataset ini berisi data permintaan listrik di Victoria, Australia. Saya menggunakan kolom-kolom berikut:
Kolom |
Keterangan |
|---|---|
|
jumlah permintaan listrik |
|
suhu rata-rata di Melbourne |
|
tanggal pencatatan |
|
penanda apakah hari tersebut hari libur |
Saya memilih dataset ini karena datanya cukup lengkap dan cocok untuk menunjukkan bagaimana time series forecasting bekerja dalam konteks penambangan data.
data = fetch_dataset(name="vic_electricity")
print("Ukuran data awal:", data.shape)
display(data.head())
display(data.tail())
vic_electricity
---------------
Half-hourly electricity demand for Victoria, Australia
O'Hara-Wild M, Hyndman R, Wang E, Godahewa R (2022).tsibbledata: Diverse
Datasets for 'tsibble'. https://tsibbledata.tidyverts.org/,
https://github.com/tidyverts/tsibbledata/.
https://tsibbledata.tidyverts.org/reference/vic_elec.html
Shape of the dataset: (52608, 4)
Ukuran data awal: (52608, 4)
| Demand | Temperature | Date | Holiday | |
|---|---|---|---|---|
| Time | ||||
| 2011-12-31 13:00:00 | 4382.825174 | 21.40 | 2012-01-01 | True |
| 2011-12-31 13:30:00 | 4263.365526 | 21.05 | 2012-01-01 | True |
| 2011-12-31 14:00:00 | 4048.966046 | 20.70 | 2012-01-01 | True |
| 2011-12-31 14:30:00 | 3877.563330 | 20.55 | 2012-01-01 | True |
| 2011-12-31 15:00:00 | 4036.229746 | 20.40 | 2012-01-01 | True |
| Demand | Temperature | Date | Holiday | |
|---|---|---|---|---|
| Time | ||||
| 2014-12-31 10:30:00 | 3873.448714 | 19.0 | 2014-12-31 | False |
| 2014-12-31 11:00:00 | 3791.637322 | 18.5 | 2014-12-31 | False |
| 2014-12-31 11:30:00 | 3724.835666 | 17.7 | 2014-12-31 | False |
| 2014-12-31 12:00:00 | 3761.886854 | 17.3 | 2014-12-31 | False |
| 2014-12-31 12:30:00 | 3809.414586 | 17.1 | 2014-12-31 | False |
4. Agregasi Data ke Harian#
Data aslinya memiliki interval pencatatan setiap setengah jam, jadi terlalu detail kalau langsung dipakai.
Maka dari itu, saya mengubah data ini menjadi data harian dengan cara:
Demandsaya jumlahkan per hari (karena kita ingin tahu total permintaan listrik satu hari penuh).Temperaturesaya hitung rata-ratanya per hari (karena kita ingin tahu suhu rata-rata harian).
Ini adalah salah satu tahap preprocessing yang penting dalam penambangan data sebelum data dimasukkan ke model.
data_daily = data.resample("D").agg({
"Demand": "sum",
"Temperature": "mean"
})
print("Ukuran data setelah agregasi harian:", data_daily.shape)
display(data_daily.head())
display(data_daily.tail())
Ukuran data setelah agregasi harian: (1097, 2)
| Demand | Temperature | |
|---|---|---|
| Time | ||
| 2011-12-31 | 82531.745918 | 21.047727 |
| 2012-01-01 | 227778.257304 | 26.578125 |
| 2012-01-02 | 275490.988882 | 31.751042 |
| 2012-01-03 | 258955.329422 | 24.567708 |
| 2012-01-04 | 213792.376946 | 18.191667 |
| Demand | Temperature | |
|---|---|---|
| Time | ||
| 2014-12-27 | 173292.325672 | 18.189583 |
| 2014-12-28 | 196116.228892 | 24.539583 |
| 2014-12-29 | 188570.258296 | 17.677083 |
| 2014-12-30 | 187212.226846 | 17.391667 |
| 2014-12-31 | 104963.021342 | 21.034615 |
5. Visualisasi Data Harian#
Selanjutnya saya membuat grafik untuk melihat pola permintaan listrik dan suhu dari waktu ke waktu.
Dari visualisasi ini, saya bisa mengamati apakah ada pola musiman atau tren tertentu yang bisa dimanfaatkan oleh model.
fig, ax = plt.subplots(figsize=(12, 5))
data_daily["Demand"].plot(ax=ax)
ax.set_title("Permintaan Listrik Harian")
ax.set_xlabel("Tanggal")
ax.set_ylabel("Demand")
plt.show()
fig, ax = plt.subplots(figsize=(12, 5))
data_daily["Temperature"].plot(ax=ax)
ax.set_title("Suhu Harian")
ax.set_xlabel("Tanggal")
ax.set_ylabel("Temperature")
plt.show()
6. Split Data Training dan Testing#
Di tahap ini saya membagi data menjadi dua bagian:
Bagian |
Rentang |
|---|---|
Data training |
sampai 2014-12-21 |
Data testing |
mulai 2014-12-22 |
Data training saya gunakan untuk melatih model, sedangkan data testing saya pakai untuk menguji seberapa akurat prediksi model.
Pembagian ini penting dalam penambangan data agar kita bisa mengevaluasi performa model secara objektif, yaitu dengan data yang belum pernah dilihat oleh model sebelumnya.
data_train = data_daily.loc[: "2014-12-21"]
data_test = data_daily.loc["2014-12-22":]
print("Jumlah data training:", data_train.shape)
print("Jumlah data testing :", data_test.shape)
display(data_train.tail())
display(data_test.head())
Jumlah data training: (1087, 2)
Jumlah data testing : (10, 2)
| Demand | Temperature | |
|---|---|---|
| Time | ||
| 2014-12-17 | 215507.677076 | 17.675000 |
| 2014-12-18 | 214934.022460 | 16.520833 |
| 2014-12-19 | 197129.766534 | 16.543750 |
| 2014-12-20 | 186486.896670 | 18.506250 |
| 2014-12-21 | 216483.631690 | 24.031250 |
| Demand | Temperature | |
|---|---|---|
| Time | ||
| 2014-12-22 | 231957.371966 | 22.950000 |
| 2014-12-23 | 210444.465956 | 18.829167 |
| 2014-12-24 | 184197.155182 | 18.312500 |
| 2014-12-25 | 165398.200578 | 16.933333 |
| 2014-12-26 | 168797.125272 | 16.429167 |
fig, ax = plt.subplots(figsize=(12, 5))
data_train["Demand"].plot(ax=ax, label="Training")
data_test["Demand"].plot(ax=ax, label="Testing")
ax.set_title("Pembagian Data Training dan Testing")
ax.set_xlabel("Tanggal")
ax.set_ylabel("Demand")
ax.legend()
plt.show()
7. Membuat dan Melatih Model Forecasting#
Di sini saya membuat model peramalan menggunakan:
ForecasterRecursivesebagai metode peramalan multi-step secara rekursif.LGBMRegressorsebagai algoritma machine learning berbasis pohon keputusan.lags = 7, artinya saya menggunakan 7 nilai permintaan listrik sebelumnya sebagai fitur.Temperaturesaya tambahkan sebagai variabel eksogen (variabel tambahan dari luar target).
Target yang saya prediksi adalah Demand, yaitu permintaan listrik harian.
Saya memilih LightGBM karena algoritma ini dikenal cepat dan cocok untuk data tabular seperti kasus ini.
forecaster = ForecasterRecursive(
regressor = LGBMRegressor(random_state=123, verbose=-1),
lags = 7
)
forecaster.fit(
y = data_train["Demand"],
exog = data_train["Temperature"]
)
forecaster
ForecasterRecursive
General Information
- Regressor: LGBMRegressor
- Lags: [1 2 3 4 5 6 7]
- Window features: None
- Window size: 7
- Exogenous included: True
- Weight function included: False
- Differentiation order: None
- Creation date: 2026-06-11 16:27:42
- Last fit date: 2026-06-11 16:27:59
- Skforecast version: 0.15.1
- Python version: 3.14.3
- Forecaster id: None
Exogenous Variables
-
Temperature
Data Transformations
- Transformer for y: None
- Transformer for exog: None
Training Information
- Training range: [Timestamp('2011-12-31 00:00:00'), Timestamp('2014-12-21 00:00:00')]
- Training index type: DatetimeIndex
- Training index frequency: D
Regressor Parameters
-
{'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0, 'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1, 'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0, 'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None, 'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0, 'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1}
Fit Kwargs
-
{}
8. Membentuk Data Training Model#
Pada bagian ini, saya ingin menunjukkan bagaimana Skforecast mengubah data time series menjadi bentuk tabel supervised learning.
Ini adalah konsep penting dalam penambangan data, yaitu transformasi data agar bisa diolah oleh algoritma machine learning.
Input model yang terbentuk terdiri dari:
lag_1sampailag_7(nilai Demand hari-hari sebelumnya)Temperature(suhu pada hari yang diprediksi)
Sedangkan output atau target modelnya adalah:
y, yaitu nilaiDemandyang ingin saya prediksi.
X_train, y_train = forecaster.create_train_X_y(
y = data_train["Demand"],
exog = data_train["Temperature"]
)
print("Bentuk X_train:", X_train.shape)
print("Bentuk y_train:", y_train.shape)
display(X_train.head())
display(y_train.head())
Bentuk X_train: (1080, 8)
Bentuk y_train: (1080,)
| lag_1 | lag_2 | lag_3 | lag_4 | lag_5 | lag_6 | lag_7 | Temperature | |
|---|---|---|---|---|---|---|---|---|
| Time | ||||||||
| 2012-01-07 | 205338.714620 | 211066.426550 | 213792.376946 | 258955.329422 | 275490.988882 | 227778.257304 | 82531.745918 | 24.098958 |
| 2012-01-08 | 200693.270298 | 205338.714620 | 211066.426550 | 213792.376946 | 258955.329422 | 275490.988882 | 227778.257304 | 20.223958 |
| 2012-01-09 | 200061.614738 | 200693.270298 | 205338.714620 | 211066.426550 | 213792.376946 | 258955.329422 | 275490.988882 | 19.161458 |
| 2012-01-10 | 216201.836844 | 200061.614738 | 200693.270298 | 205338.714620 | 211066.426550 | 213792.376946 | 258955.329422 | 16.042708 |
| 2012-01-11 | 217176.907910 | 216201.836844 | 200061.614738 | 200693.270298 | 205338.714620 | 211066.426550 | 213792.376946 | 14.815625 |
Time
2012-01-07 200693.270298
2012-01-08 200061.614738
2012-01-09 216201.836844
2012-01-10 217176.907910
2012-01-11 217517.475010
Freq: D, Name: y, dtype: float64
Penjelasan Bentuk Data Training#
Untuk lebih jelasnya, berikut arti dari setiap kolom yang saya dapatkan:
Kolom |
Arti |
|---|---|
|
Demand 1 hari sebelumnya |
|
Demand 2 hari sebelumnya |
|
Demand 3 hari sebelumnya |
|
Demand 4 hari sebelumnya |
|
Demand 5 hari sebelumnya |
|
Demand 6 hari sebelumnya |
|
Demand 7 hari sebelumnya |
|
suhu pada hari yang diprediksi |
|
Demand aktual yang menjadi target prediksi |
Jadi bisa saya simpulkan bahwa model ini belajar dari pola 7 hari terakhir ditambah informasi suhu untuk memprediksi permintaan listrik hari berikutnya.
9. Model-specific Feature Importance#
Di sini saya melihat fitur mana yang dianggap paling penting oleh model LGBMRegressor.
Feature importance ini merupakan salah satu teknik explainability dalam penambangan data yang membantu saya memahami alasan di balik prediksi model.
feature_importance = forecaster.get_feature_importances()
display(feature_importance)
| feature | importance | |
|---|---|---|
| 7 | Temperature | 570 |
| 0 | lag_1 | 470 |
| 2 | lag_3 | 387 |
| 1 | lag_2 | 362 |
| 6 | lag_7 | 325 |
| 5 | lag_6 | 313 |
| 4 | lag_5 | 298 |
| 3 | lag_4 | 275 |
fig, ax = plt.subplots(figsize=(9, 5))
feature_importance.sort_values("importance").plot(
x="feature",
y="importance",
kind="barh",
ax=ax,
legend=False
)
ax.set_title("Feature Importance dari LGBMRegressor")
ax.set_xlabel("Importance")
ax.set_ylabel("Feature")
plt.show()
10. SHAP Values#
Selanjutnya saya menggunakan SHAP (SHapley Additive exPlanations) untuk menjelaskan kontribusi setiap fitur terhadap hasil prediksi model.
SHAP ini berbasis teori permainan dan bisa menunjukkan seberapa besar pengaruh masing-masing fitur, baik positif maupun negatif.
Karena model saya berbasis pohon keputusan (LightGBM), saya menggunakan TreeExplainer yang lebih cepat.
shap.initjs()
explainer = shap.TreeExplainer(forecaster.regressor)
shap_values_train = explainer.shap_values(X_train)
# Untuk menjaga kompatibilitas jika output SHAP berbentuk list
if isinstance(shap_values_train, list):
shap_values_train = shap_values_train[0]
print("Bentuk SHAP values:", shap_values_train.shape)
Bentuk SHAP values: (1080, 8)
SHAP Summary Plot dalam Bentuk Bar#
Plot bar ini menunjukkan rata-rata pengaruh setiap fitur terhadap prediksi.
Dari sini saya bisa melihat fitur mana yang secara umum paling berpengaruh terhadap model.
shap.summary_plot(shap_values_train, X_train, plot_type="bar")
SHAP Summary Plot Detail#
Berbeda dengan plot bar sebelumnya, plot ini menunjukkan arah pengaruh fitur.
Saya bisa melihat apakah nilai fitur yang tinggi mendorong prediksi naik atau turun.
Warna merah menunjukkan nilai fitur tinggi, sedangkan biru menunjukkan nilai rendah.
shap.summary_plot(shap_values_train, X_train)
11. Explain Individual Observation#
Di bagian ini saya mencoba menjelaskan satu data training secara individual.
Tujuannya agar saya bisa melihat fitur mana yang menaikkan atau menurunkan hasil prediksi pada satu baris data tertentu.
Ini yang disebut sebagai local explanation dalam konteks explainability.
shap.force_plot(
explainer.expected_value,
shap_values_train[0, :],
X_train.iloc[0, :]
)
Have you run `initjs()` in this notebook? If this notebook was from another user you must also trust this notebook (File -> Trust notebook). If you are viewing this notebook on github the Javascript has been stripped for security. If you are using JupyterLab this error is because a JupyterLab extension has not yet been written.
12. SHAP Dependence Plot#
Dependence plot ini saya gunakan untuk melihat hubungan antara satu fitur dengan nilai SHAP-nya.
Pada contoh ini saya memilih fitur Temperature karena saya ingin tahu bagaimana suhu memengaruhi prediksi permintaan listrik.
Hasilnya cukup menarik karena bisa terlihat pola non-linear.
fig, ax = plt.subplots(figsize=(8, 5))
shap.dependence_plot("Temperature", shap_values_train, X_train, ax=ax)
plt.show()
13. Prediksi 10 Hari ke Depan#
Sekarang saya menggunakan model yang sudah dilatih untuk memprediksi 10 hari pertama pada data testing.
Saya ingin melihat seberapa akurat model dalam memprediksi permintaan listrik di hari-hari yang belum pernah dilihat sebelumnya.
predictions = forecaster.predict(
steps = 10,
exog = data_test["Temperature"]
)
display(predictions)
2014-12-22 241514.532543
2014-12-23 226165.936559
2014-12-24 220506.468700
2014-12-25 209260.948991
2014-12-26 184885.145832
2014-12-27 195623.591810
2014-12-28 222766.340659
2014-12-29 223112.716406
2014-12-30 219103.891733
2014-12-31 217948.965404
Freq: D, Name: pred, dtype: float64
hasil_prediksi = pd.DataFrame({
"Actual_Demand": data_test["Demand"].iloc[:10],
"Predicted_Demand": predictions
})
hasil_prediksi["Error"] = hasil_prediksi["Actual_Demand"] - hasil_prediksi["Predicted_Demand"]
display(hasil_prediksi)
| Actual_Demand | Predicted_Demand | Error | |
|---|---|---|---|
| 2014-12-22 | 231957.371966 | 241514.532543 | -9557.160577 |
| 2014-12-23 | 210444.465956 | 226165.936559 | -15721.470603 |
| 2014-12-24 | 184197.155182 | 220506.468700 | -36309.313518 |
| 2014-12-25 | 165398.200578 | 209260.948991 | -43862.748413 |
| 2014-12-26 | 168797.125272 | 184885.145832 | -16088.020560 |
| 2014-12-27 | 173292.325672 | 195623.591810 | -22331.266138 |
| 2014-12-28 | 196116.228892 | 222766.340659 | -26650.111767 |
| 2014-12-29 | 188570.258296 | 223112.716406 | -34542.458110 |
| 2014-12-30 | 187212.226846 | 219103.891733 | -31891.664887 |
| 2014-12-31 | 104963.021342 | 217948.965404 | -112985.944062 |
mae = mean_absolute_error(hasil_prediksi["Actual_Demand"], hasil_prediksi["Predicted_Demand"])
rmse = np.sqrt(mean_squared_error(hasil_prediksi["Actual_Demand"], hasil_prediksi["Predicted_Demand"]))
mape = mean_absolute_percentage_error(hasil_prediksi["Actual_Demand"], hasil_prediksi["Predicted_Demand"]) * 100
print("Evaluasi prediksi 10 hari pertama data testing")
print(f"MAE : {mae:,.2f}")
print(f"RMSE : {rmse:,.2f}")
print(f"MAPE : {mape:.2f}%")
Evaluasi prediksi 10 hari pertama data testing
MAE : 34,994.02
RMSE : 44,748.89
MAPE : 23.68%
fig, ax = plt.subplots(figsize=(10, 5))
hasil_prediksi[["Actual_Demand", "Predicted_Demand"]].plot(ax=ax)
ax.set_title("Perbandingan Demand Aktual dan Prediksi")
ax.set_xlabel("Tanggal")
ax.set_ylabel("Demand")
plt.show()
14. Membuat Matriks Input untuk Prediksi#
Di sini saya membuat matriks X_predict yang berisi fitur-fitur yang dipakai model ketika melakukan prediksi.
Kolomnya sama seperti data training, yaitu lag_1 sampai lag_7 dan Temperature.
Ini berguna untuk saya analisis lebih lanjut menggunakan SHAP di langkah berikutnya.
X_predict = forecaster.create_predict_X(
steps = 10,
exog = data_test["Temperature"]
)
display(X_predict)
| lag_1 | lag_2 | lag_3 | lag_4 | lag_5 | lag_6 | lag_7 | Temperature | |
|---|---|---|---|---|---|---|---|---|
| 2014-12-22 | 216483.631690 | 186486.896670 | 197129.766534 | 214934.022460 | 215507.677076 | 226093.767670 | 231923.044018 | 22.950000 |
| 2014-12-23 | 241514.532543 | 216483.631690 | 186486.896670 | 197129.766534 | 214934.022460 | 215507.677076 | 226093.767670 | 18.829167 |
| 2014-12-24 | 226165.936559 | 241514.532543 | 216483.631690 | 186486.896670 | 197129.766534 | 214934.022460 | 215507.677076 | 18.312500 |
| 2014-12-25 | 220506.468700 | 226165.936559 | 241514.532543 | 216483.631690 | 186486.896670 | 197129.766534 | 214934.022460 | 16.933333 |
| 2014-12-26 | 209260.948991 | 220506.468700 | 226165.936559 | 241514.532543 | 216483.631690 | 186486.896670 | 197129.766534 | 16.429167 |
| 2014-12-27 | 184885.145832 | 209260.948991 | 220506.468700 | 226165.936559 | 241514.532543 | 216483.631690 | 186486.896670 | 18.189583 |
| 2014-12-28 | 195623.591810 | 184885.145832 | 209260.948991 | 220506.468700 | 226165.936559 | 241514.532543 | 216483.631690 | 24.539583 |
| 2014-12-29 | 222766.340659 | 195623.591810 | 184885.145832 | 209260.948991 | 220506.468700 | 226165.936559 | 241514.532543 | 17.677083 |
| 2014-12-30 | 223112.716406 | 222766.340659 | 195623.591810 | 184885.145832 | 209260.948991 | 220506.468700 | 226165.936559 | 17.391667 |
| 2014-12-31 | 219103.891733 | 223112.716406 | 222766.340659 | 195623.591810 | 184885.145832 | 209260.948991 | 220506.468700 | 21.034615 |
15. Menjelaskan Nilai Prediksi dengan SHAP#
Pada bagian ini saya menjelaskan prediksi pada tanggal tertentu, yaitu 2014-12-22, menggunakan SHAP.
Dengan cara ini saya bisa memahami mengapa model memberikan prediksi tertentu pada tanggal tersebut — fitur mana yang mendorong nilai naik dan mana yang menariknya turun.
predicted_date = "2014-12-22"
iloc_predicted_date = X_predict.index.get_loc(predicted_date)
shap_values_predict = explainer.shap_values(X_predict)
if isinstance(shap_values_predict, list):
shap_values_predict = shap_values_predict[0]
shap.force_plot(
explainer.expected_value,
shap_values_predict[iloc_predicted_date, :],
X_predict.iloc[iloc_predicted_date, :]
)
Have you run `initjs()` in this notebook? If this notebook was from another user you must also trust this notebook (File -> Trust notebook). If you are viewing this notebook on github the Javascript has been stripped for security. If you are using JupyterLab this error is because a JupyterLab extension has not yet been written.
16. Permutation Feature Importance#
Selain SHAP, saya juga menggunakan metode permutation importance.
Cara kerjanya adalah dengan mengacak nilai satu fitur, lalu melihat seberapa besar performa model menurun.
Kalau performa model turun banyak setelah fitur diacak, berarti fitur itu memang penting buat model.
Metode ini saya anggap lebih “jujur” karena model-agnostic, artinya bisa dipakai untuk model apa saja.
r = permutation_importance(
estimator = forecaster.regressor,
X = X_train,
y = y_train,
n_repeats = 3,
max_samples = 0.5,
random_state = 123
)
permutation_importances = pd.DataFrame({
"feature": X_train.columns,
"mean_importance": r.importances_mean,
"std_importance": r.importances_std
}).sort_values("mean_importance", ascending=False)
display(permutation_importances)
| feature | mean_importance | std_importance | |
|---|---|---|---|
| 0 | lag_1 | 0.617276 | 0.014583 |
| 7 | Temperature | 0.411240 | 0.014405 |
| 6 | lag_7 | 0.196190 | 0.001865 |
| 1 | lag_2 | 0.122398 | 0.007803 |
| 5 | lag_6 | 0.083912 | 0.003637 |
| 2 | lag_3 | 0.041294 | 0.002019 |
| 4 | lag_5 | 0.030787 | 0.001079 |
| 3 | lag_4 | 0.024816 | 0.001021 |
fig, ax = plt.subplots(figsize=(9, 5))
permutation_importances.sort_values("mean_importance").plot(
x="feature",
y="mean_importance",
kind="barh",
ax=ax,
legend=False
)
ax.set_title("Permutation Feature Importance")
ax.set_xlabel("Mean Importance")
ax.set_ylabel("Feature")
plt.show()
17. Partial Dependence Plot#
Terakhir, saya membuat Partial Dependence Plot (PDP) untuk melihat hubungan antara fitur tertentu dengan hasil prediksi model.
Saya memilih fitur Temperature dan lag_1 karena dari analisis sebelumnya kedua fitur ini termasuk yang paling berpengaruh.
PDP ini membantu saya memahami bagaimana perubahan nilai suatu fitur memengaruhi prediksi secara rata-rata.
fig, ax = plt.subplots(figsize=(10, 5))
PartialDependenceDisplay.from_estimator(
estimator = forecaster.regressor,
X = X_train,
features = ["Temperature", "lag_1"],
kind = "both",
ax = ax
)
ax.set_title("Partial Dependence Plot")
fig.tight_layout()
plt.show()
Jawaban Pertanyaan Tugas#
Berikut adalah jawaban saya terhadap pertanyaan-pertanyaan yang diberikan dalam tugas mata kuliah Penambangan Data Kelas A.
Pertanyaan 1: Analisa prediksi tentang apa?#
Menurut pemahaman saya, analisis prediksi pada kasus ini membahas tentang prediksi permintaan (demand) listrik harian di wilayah Victoria, Australia.
Secara lebih rinci:
Variabel yang diprediksi (target):
Demand, yaitu total kebutuhan atau permintaan listrik dalam satu hari.Tujuan prediksi: Memperkirakan berapa besar permintaan listrik di hari-hari mendatang berdasarkan pola permintaan di masa lalu dan kondisi suhu.
Metode yang digunakan: Model
ForecasterRecursivedari library Skforecast dengan algoritmaLGBMRegressor(LightGBM).Jenis analisis: Selain prediksi, kasus ini juga fokus pada explainability (kemampuan menjelaskan model), yaitu memahami mengapa model memberikan prediksi tertentu.
Dalam konteks mata kuliah Penambangan Data, kasus ini relevan karena menunjukkan bagaimana teknik data mining dapat diaplikasikan pada data time series untuk menghasilkan prediksi yang bukan hanya akurat, tetapi juga bisa dijelaskan. Ini penting karena dalam dunia nyata, kita tidak cukup hanya mengetahui “angka prediksinya berapa”, tetapi juga perlu tahu “kenapa model memberikan angka itu”.
Pertanyaan 2: Bagaimana bentuk data trainingnya, apa input dan outputnya?#
Data awal yang saya gunakan berbentuk time series (data runtun waktu), yaitu data yang tersusun berdasarkan urutan waktu.
Setelah saya ubah dari interval setengah jam menjadi data harian, library Skforecast secara otomatis mengubah data ini menjadi format supervised learning — yaitu format tabel yang terdiri dari kolom input (fitur) dan kolom output (target).
Input Model (Fitur)#
Fitur |
Keterangan |
Tipe |
|---|---|---|
|
Demand 1 hari sebelumnya |
Lag feature |
|
Demand 2 hari sebelumnya |
Lag feature |
|
Demand 3 hari sebelumnya |
Lag feature |
|
Demand 4 hari sebelumnya |
Lag feature |
|
Demand 5 hari sebelumnya |
Lag feature |
|
Demand 6 hari sebelumnya |
Lag feature |
|
Demand 7 hari sebelumnya |
Lag feature |
|
Suhu rata-rata harian di Melbourne |
Variabel eksogen |
Output Model (Target)#
Output |
Keterangan |
|---|---|
|
Nilai Demand aktual yang ingin diprediksi |
Ilustrasi#
Misalnya, untuk memprediksi permintaan listrik pada tanggal 8 Januari 2012, model akan menggunakan:
Permintaan listrik tanggal 7 Januari (
lag_1), 6 Januari (lag_2), …, hingga 1 Januari (lag_7)Suhu rata-rata pada tanggal 8 Januari (
Temperature)
Jadi, bentuk data training saya adalah tabel dengan 8 kolom input (lag_1 s.d. lag_7 + Temperature) dan 1 kolom output (y).
Proses transformasi dari time series ke tabel ini merupakan contoh nyata dari feature engineering dalam penambangan data.
Pertanyaan 3: Apa itu lag?#
Dari yang saya pelajari, lag (atau lagged variable) adalah nilai data pada periode sebelumnya yang digunakan sebagai input untuk memprediksi nilai saat ini atau masa depan.
Penjelasan Sederhana#
Bayangkan kita ingin memprediksi permintaan listrik hari ini. Salah satu informasi yang berguna adalah mengetahui permintaan listrik kemarin, 2 hari lalu, 3 hari lalu, dan seterusnya. Nah, nilai-nilai di masa lalu inilah yang disebut “lag”.
Dalam Kasus Ini#
Lag |
Arti |
|---|---|
|
Demand 1 hari sebelumnya |
|
Demand 2 hari sebelumnya |
|
Demand 3 hari sebelumnya |
|
Demand 4 hari sebelumnya |
|
Demand 5 hari sebelumnya |
|
Demand 6 hari sebelumnya |
|
Demand 7 hari sebelumnya |
Karena saya memakai lags = 7, artinya model saya menggunakan data permintaan listrik selama 7 hari terakhir sebagai “jendela” (window) untuk memprediksi permintaan listrik hari berikutnya.
Mengapa Lag Penting?#
Menangkap pola temporal: Lag membantu model mengenali pola berulang, misalnya permintaan listrik yang selalu tinggi di hari kerja dan rendah di akhir pekan.
Mengubah time series jadi tabel: Dengan lag, data time series bisa diubah menjadi format supervised learning yang bisa diolah oleh algoritma machine learning biasa.
Konsep fundamental: Dalam penambangan data dan forecasting, lag adalah salah satu teknik paling dasar dan paling sering digunakan untuk menangkap ketergantungan antar waktu (temporal dependency).
Pertanyaan 4: Jelaskan proses analysis yang dilakukan#
Berikut adalah proses analisis yang saya lakukan secara bertahap:
Tahap 1: Pengambilan Data#
Saya mengambil dataset vic_electricity dari library Skforecast. Dataset ini berisi data permintaan listrik, suhu, tanggal, dan informasi hari libur di Victoria, Australia. Data awalnya berjumlah sangat banyak karena dicatat setiap setengah jam.
Tahap 2: Preprocessing Data#
Saya melakukan preprocessing dengan mengagregasi data menjadi data harian:
Kolom
Demanddijumlahkan per hari (untuk mendapat total permintaan satu hari penuh)Kolom
Temperaturedihitung rata-ratanya per hari
Tahap ini penting karena data yang terlalu granular bisa menyulitkan model dan membuat proses training lebih lama.
Tahap 3: Eksplorasi & Visualisasi Data#
Saya membuat grafik time series untuk melihat pola dari data Demand dan Temperature. Dari visualisasi ini, saya bisa mengamati adanya pola musiman (seasonal pattern) di mana permintaan listrik naik di musim panas dan dingin.
Tahap 4: Split Data Training & Testing#
Data saya bagi menjadi:
Training: sampai 2014-12-21 (untuk melatih model)
Testing: mulai 2014-12-22 (untuk menguji prediksi model)
Pembagian ini sesuai dengan prinsip evaluasi objektif dalam penambangan data, di mana model diuji pada data yang belum pernah dilihat sebelumnya.
Tahap 5: Pembuatan & Training Model#
Saya membuat model ForecasterRecursive dengan algoritma LGBMRegressor, menggunakan 7 lag dan variabel eksogen Temperature. Model dilatih menggunakan data training.
Tahap 6: Transformasi Data ke Supervised Learning#
Skforecast secara otomatis mengubah time series menjadi tabel supervised learning dengan kolom lag_1 s.d. lag_7 + Temperature sebagai input dan Demand sebagai output.
Tahap 7: Analisis Explainability#
Ini adalah bagian inti dari kasus ini. Saya menggunakan beberapa metode untuk menjelaskan model:
Metode |
Penjelasan |
|---|---|
Feature Importance |
Menunjukkan fitur mana yang paling sering dipakai oleh model LightGBM dalam proses splitting pohon keputusan |
SHAP Values |
Menunjukkan kontribusi setiap fitur secara detail. SHAP Summary Plot (bar) untuk gambaran umum, SHAP Summary Plot (dot) untuk arah pengaruh, dan Force Plot untuk penjelasan per observasi |
SHAP Dependence Plot |
Menunjukkan hubungan non-linear antara satu fitur (misalnya |
Permutation Importance |
Mengukur pentingnya fitur dengan cara mengacak nilainya dan melihat seberapa besar performa model menurun. Metode ini model-agnostic |
Partial Dependence Plot (PDP) |
Menunjukkan bagaimana perubahan nilai satu fitur memengaruhi prediksi secara rata-rata, dengan mempertahankan fitur lain konstan |
Tahap 8: Prediksi & Evaluasi#
Model saya gunakan untuk memprediksi 10 hari pertama pada data testing. Hasilnya saya bandingkan dengan data aktual dan evaluasi menggunakan metrik:
MAE (Mean Absolute Error): rata-rata kesalahan absolut
RMSE (Root Mean Squared Error): akar dari rata-rata kuadrat kesalahan
MAPE (Mean Absolute Percentage Error): rata-rata kesalahan dalam persentase
Kesimpulan Proses#
Keseluruhan proses ini menunjukkan bahwa model machine learning tidak hanya bisa dipakai untuk forecasting, tetapi juga bisa dijelaskan hasilnya menggunakan teknik explainability. Ini sejalan dengan apa yang saya pelajari di mata kuliah Penambangan Data, bahwa memahami model sama pentingnya dengan membangun model itu sendiri.
Ringkasan Akhir#
Dari reproduksi yang saya lakukan dalam tugas Penambangan Data ini, saya dapat menyimpulkan bahwa:
Target prediksi dalam kasus ini adalah
Demand(permintaan listrik harian di Victoria, Australia).Input model terdiri dari
lag_1sampailag_7(nilai permintaan listrik 7 hari terakhir) danTemperature(suhu harian rata-rata). Total ada 8 fitur input.Output model adalah prediksi
Demanduntuk hari berikutnya.Lag adalah nilai masa lalu yang digunakan sebagai fitur input. Konsep ini sangat fundamental dalam analisis time series karena membantu model mengenali pola temporal.
Analisis explainability yang saya lakukan (feature importance, SHAP, permutation importance, dan PDP) menunjukkan bahwa
lag_1danTemperatureadalah fitur yang paling berpengaruh terhadap prediksi model.
Tugas ini memberikan saya pemahaman yang lebih mendalam tentang bagaimana teknik penambangan data dapat diterapkan pada permasalahan nyata, khususnya dalam hal forecasting dan model interpretability.
Notebook ini dibuat oleh Zakaria Mujur Prasetyo (240411100144) untuk tugas mata kuliah Penambangan Data Kelas A.