Semua Tentang Belajar Teknologi Digital Dalam Kehidupan Sehari - Hari

Jumat, 21 Maret 2025

Mengulik Statistik Transportasi KAI - Regresi Linear Vs ARIMA

 



Pembahasan kali ini akan mengambil data yang telah disediakan oleh Biro Pusat Statistik yang memang diperintahkan oleh negara untuk menyediakan data-data statistik semua kegiatan penduduk Indonesia, salah satunya yang saya ambil adalah data perjalanan kereta api yang tersedia sejak 2006. Jadi jika pembaca ingin belajar lewat contoh-contoh seperti yang saya gunakan, bisa mendaftar API key secara gratis di websitenya BPS. Memang sih tiap data bisa diambil dalam excel atau csv, namun ketersediaanya dalam bentuk tahunan, sehingga gak terlalu keren untuk unjuk gigi kemampuan koding saya (padahal saya juga banyak dibantu QWENAI).

Contoh untuk memanggi API dan mendapatkan JSON nya bisa menggunakan script python seperti ini :


koding:

#Jangan lupa daftar akses API key di BPS
import requests
r = requests.get('https://webapi.bps.go.id/v1/api/list/model/data/lang/ind/domain/0000/var/72/key/Ubah key punya akun anda')

with open('data_KAI.json','w') as fd:
    fd.write(r.text)


Namun ...bukan Indonesia namanya kalau menyediakan data gratisan apapun dengan prinsip "Kalau bisa dipersulit ngapain dipermudah ?" Jadi JSON nya sepertinya hanya dipahami yang bikin database dari BPS, dimana tiap key json saling terhubung dengan kode-kode yang saling terkait. Jadi jika menggunakan layanan Json to Table di internet, maka akan zonk hasilnya. Jadi saya bertanya aja ke QWEN AI dan mendapatkan pencerahan mengenai Json dari API BPS, dan berhasil membuat CSV yang lebih gampang di extract time-series nya.


File JSON ini berisi kumpulan data komprehensif terkait transportasi, khususnya yang berfokus pada jumlah penumpang kereta api di Indonesia. Data tersebut terstruktur dan saling terhubung melalui berbagai kunci dan nilai. Berikut ini adalah analisis struktur dan koneksi dalam JSON:

Struktur Umum

Metadata:
  • status: Menunjukkan status data (misalnya, "OK").
  • data-availability: Menunjukkan apakah data tersedia.
  • last_update: Stempel waktu pembaruan terakhir.
Subjek:
  • subject: Berisi informasi tentang subjek data, dalam hal ini, "Transportasi".
Variabel:
  • var: Menjelaskan variabel yang sedang diukur. Di sini, "Jumlah Penumpang Kereta Api" dengan satuan "Ribu Orang". Ini juga mencakup catatan dan sumber.
Variabel Versi:
  • turvar: Atribut tambahan untuk pembuatan versi (dalam hal ini, menunjukkan 'Tidak'). 
  • labelvervar: Label untuk jenis transportasi ("Kereta Api").
  • vervar: Mencantumkan berbagai jenis layanan kereta api seperti Jabodetabek, Non Jabodetabek, Sumatera, dll.
Tahun:
  • tahun: Mencantumkan tahun dari 2006 hingga 2025.
Periode Waktu:
  • turtahun: Mencantumkan bulan dan entri tahunan.
Konten Data:
  • datacontent: Berisi titik data aktual. Setiap kunci mewakili kombinasi variabel dan periode waktu tertentu, dan nilainya mewakili jumlah penumpang.
Data Terkait:
  • related: Bagian ini kosong di berkas Anda, tetapi dapat digunakan untuk menautkan ke kumpulan data terkait lainnya.

Koneksi dan Hubungan Kunci:

Keterkaitan Subjek dan Variabel:
  • Array subjek terhubung ke array var melalui kolom subj. Misalnya, "Transportasi" terhubung ke "Jumlah Penumpang Kereta Api".
Variabel dan Variabel Versi:
  • Array var dirinci lebih lanjut oleh array vervar yang mengkategorikan data ke dalam berbagai jenis layanan kereta api.
Data Temporal:
  • Array tahun dan turtahun menyediakan konteks temporal. Setiap titik data dalam datacontent sesuai dengan tahun dan bulan tertentu (atau tahunan).
Titik Data:

Kunci dalam datacontent mengikuti pola yang mengodekan jenis layanan, tahun, dan bulan. Misalnya, 17201061 dapat dipecah menjadi:
  • 1: Mengacu pada "Jabodetabek" dari vervar.
  • 72: Mengacu pada "Jumlah Penumpang Kereta Api".
  • 01: Mengacu pada tahun 2006 dari tahun.
  • 06: Mengacu pada Juni dari turtahun.
Contoh Analisis:
Mari kita ambil contoh kunci dari datacontent untuk mengilustrasikan bagaimana data saling terhubung:

Kunci: 17201061
Rincian:
  • 1: "Jabodetabek" (vervar)
  • 72: "Jumlah Penumpang Kereta Api" (var)
  • 01: Tahun 2006 (tahun)
  • 06: Bulan Juni (turtahun)
  • Nilai: 8681 (yang berarti 8.681.000 penumpang)
Ringkasan:

File JSON sangat terstruktur dan saling terhubung, memungkinkan analisis terperinci jumlah penumpang kereta api di berbagai layanan, tahun, dan bulan. Kunci dalam objek datacontent mengodekan dimensi ini, sehingga memungkinkan untuk mengekstrak wawasan yang berarti tentang tren dan pola dalam transportasi kereta api dari waktu ke waktu.

Nah...mumet bukan ? Mari kita lanjutkan ke script python yang sudah saya sesuaikan agar bisa merubah json BPS menjadi CSV data series:

# Import required libraries
import pandas as pd
import json

with open('data_KAI.json', 'r') as file:
    data = json.load(file)


# Extract relevant mappings
vervar_map = {str(v['val']): v['label'] for v in data['vervar']}  # Train services
tahun_map = {str(t['val']): t['label'] for t in data['tahun']}  # Years
turtahun_map = {str(t['val']): t['label'] for t in data['turtahun']}  # Months + Annual

# Prepare a dictionary to store the decoded data
time_series_data = {}

# Decode the datacontent keys
for key, value in data['datacontent'].items():
    # Split the key into components
    service_code = key[0]  # First digit: service type
    year_code = key[4:7]   # Next three digits: year
    month_code = key[7:]   # Remaining digits: month or annual
    #print(year_code)
    # Map codes to labels
    service_label = vervar_map.get(service_code, "Unknown Service")
    year_label = tahun_map.get(year_code, "Unknown Year")  # Use full year_code for lookup
    month_label = turtahun_map.get(month_code, "Unknown Month")

    # Create a unique identifier for the column (YYYY-MM format)
    if month_label != "Tahunan":  # Exclude annual data
        date_key = f"{year_label}-{int(month_code):02d}"  # Format: YYYY-MM
    else:
        date_key = f"{year_label}-Annual"  # For annual totals

    # Add to the time_series_data dictionary
    if service_label not in time_series_data:
        time_series_data[service_label] = {}
    time_series_data[service_label][date_key] = value

# Convert to a DataFrame
all_dates = sorted({date for dates in time_series_data.values() for date in dates})
df = pd.DataFrame(index=time_series_data.keys(), columns=all_dates)

# Populate the DataFrame
for service, values in time_series_data.items():
    for date, count in values.items():
        df.at[service, date] = count

# Reset index to make the services a column
df.reset_index(inplace=True)
df.rename(columns={"index": "Service"}, inplace=True)

# Save the DataFrame to a CSV file
csv_file = "railway_passenger_time_series.csv"
df.to_csv(csv_file, index=False)

print(f"CSV file '{csv_file}' has been created successfully!")

Hasilnya berupa file bernama "railway_passenger_time_series.csv" dan untuk menampilkan data nya dalam visualisasi grafik, kita manfaatkan matplotlib. Seperti contoh dibawah ini mengambarkan data history perjalanan kereta api di daerah jabodetabek periode 2006-2025 (grafik ada di gambar paling atas):

# Import required libraries
import pandas as pd
import matplotlib.pyplot as plt

# Load the previously created CSV file
csv_file = "railway_passenger_time_series.csv"
df = pd.read_csv(csv_file)

# Filter data for "Jabodetabek" service
jabodetabek_data = df[df['Service'] == 'Jabodetabek'].drop(columns=['Service']).T
jabodetabek_data.columns = ['PassengerCount']

# Remove rows corresponding to "Year-Annual" (filter out annual totals)
jabodetabek_data = jabodetabek_data[~jabodetabek_data.index.str.contains('Annual')]

jabodetabek_data.index = pd.to_datetime(jabodetabek_data.index, format='%Y-%m')  # Convert index to datetime
jabodetabek_data = jabodetabek_data.sort_index()  # Ensure chronological order

# Plot the time series data
plt.figure(figsize=(14, 7))
plt.plot(jabodetabek_data.index, jabodetabek_data['PassengerCount'], label='Jabodetabek Passenger Count', color='blue')

# Add title and labels
plt.title('Monthly Passenger Count for Jabodetabek (2006-2025)', fontsize=16)
plt.xlabel('Year', fontsize=12)
plt.ylabel('Passenger Count (in thousands)', fontsize=12)

# Rotate x-axis labels for better readability
plt.xticks(rotation=45)

# Add grid and legend
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()

# Show the plot
plt.tight_layout()
plt.show()

Ayo jangan lama-lama saya tampilkan regesi linearnya :


# Import required libraries
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt

# Load the previously created CSV file
csv_file = "railway_passenger_time_series.csv"
df = pd.read_csv(csv_file)

# Filter data for "Jabodetabek" service
jabodetabek_data = df[df['Service'] == 'Jabodetabek'].drop(columns=['Service']).T
jabodetabek_data.columns = ['PassengerCount']

# Remove rows corresponding to "Year-Annual" (filter out annual totals)
jabodetabek_data = jabodetabek_data[~jabodetabek_data.index.str.contains('Annual')]

# Convert index to datetime format
jabodetabek_data.index = pd.to_datetime(jabodetabek_data.index, format='%Y-%m')
jabodetabek_data = jabodetabek_data.sort_index()  # Ensure chronological order

# Filter data for the years 2020 to 2024
start_date = '2006-01'
end_date = '2024-12'
filtered_data = jabodetabek_data.loc[start_date:end_date]

# Prepare the data for training
def prepare_data(series):
    """
    Prepare data for supervised learning.
    :param series: Time series data (passenger counts).
    :return: X (features) and y (target).
    """
    X, y = [], []
    for i in range(len(series) - 1):  # Use one-step-ahead prediction
        X.append([i])  # Use time step as the feature
        y.append(series[i + 1])  # Predict the next month
    return np.array(X), np.array(y)

# Extract the passenger count series
series = filtered_data['PassengerCount'].values

# Prepare training datasets
X_train, y_train = prepare_data(series)

# Train the Linear Regression model
model = LinearRegression()
model.fit(X_train, y_train)

# Predict future values for the next 60 months (2029)
future_months = 60
last_time_step = len(series) - 1
future_predictions = []
for i in range(future_months):
    next_month_prediction = model.predict([[last_time_step + i]])[0]
    future_predictions.append(next_month_prediction)

# Create a DataFrame for the predictions
future_dates = pd.date_range(start=filtered_data.index[-1] + pd.offsets.MonthBegin(),
                             periods=future_months, freq='MS')
predictions_df = pd.DataFrame({
    'Date': future_dates,
    'Predicted_PassengerCount': future_predictions
})

# Combine historical data and predictions
combined_data = pd.concat([
    filtered_data.reset_index().rename(columns={'index': 'Date'}),
    predictions_df
])

# Plot the results
plt.figure(figsize=(14, 7))

# Historical data
plt.plot(combined_data['Date'][:-future_months], combined_data['PassengerCount'][:-future_months],
         label='Historical Data (2006-2024)', color='blue')

# Predictions
plt.plot(combined_data['Date'][-future_months:], combined_data['Predicted_PassengerCount'][-future_months:],
         label='Predicted Data (2025)', color='orange', linestyle='--')

# Add title and labels
plt.title('Monthly Passenger Count for Jabodetabek (2006-2029)', fontsize=16)
plt.xlabel('Year', fontsize=12)
plt.ylabel('Passenger Count (in thousands)', fontsize=12)

# Rotate x-axis labels for better readability
plt.xticks(rotation=45)

# Add grid and legend
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()

# Show the plot
plt.tight_layout()
plt.show()

Hasilnya seperti ini grafiknya :



Bagaimana dengan ARIMA ?


# Create a DataFrame for the predictions
future_dates = pd.date_range(start=filtered_data.index[-1] + pd.offsets.MonthBegin(),
                             periods=future_months, freq='MS')
predictions_df = pd.DataFrame({
    'Date': future_dates,
    'Predicted_PassengerCount': predictions
})

# Combine historical data and predictions
combined_data = pd.concat([
    filtered_data.reset_index().rename(columns={'index': 'Date'}),
    predictions_df
])

# Plot the results
plt.figure(figsize=(14, 7))

# Historical data
plt.plot(combined_data['Date'][:-future_months], combined_data['PassengerCount'][:-future_months],
         label=f'Historical Data ({start_date[0:4]}-{end_date[0:4]})', color='blue')

# Predictions
plt.plot(combined_data['Date'][-future_months:], combined_data['Predicted_PassengerCount'][-future_months:],
         label='Predicted Data (2025)', color='orange', linestyle='--')

# Add title and labels
plt.title(f'Monthly Passenger Count for Jabodetabek ({start_date[0:4]}-{end_date[0:4]})', fontsize=16)
plt.xlabel('Year', fontsize=12)
plt.ylabel('Passenger Count (in thousands)', fontsize=12)

# Rotate x-axis labels for better readability
plt.xticks(rotation=45)

# Add grid and legend
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()

# Show the plot
plt.tight_layout()
plt.show()

Grafiknya lebih bergejolak dibandingkan regresi linear :



Pada grafik diatas bisa pembaca utak-atik range tahun yang digunakan karena ada pola yang kurang "statisioner" ketika jaman pandemi 2020-2021.

Jika prediksi dari model Anda (misalnya, ARIMA, LSTM, atau model peramalan lainnya) menghasilkan garis 'cenderung' datar, biasanya hal ini menunjukkan bahwa model tersebut gagal menangkap pola, tren, atau kemusiman yang mendasarinya dalam data. Prediksi garis datar menunjukkan bahwa model tersebut memprediksi nilai konstan dari waktu ke waktu, yang sering kali merupakan tanda adanya satu atau beberapa masalah dalam proses pemodelan. Berikut adalah alasan paling umum untuk perilaku ini dan cara mengatasinya:

1. Kurangnya Tren atau Kemusiman dalam Data

Mengapa hal ini terjadi: Jika data historis tidak menunjukkan tren atau kemusiman yang kuat, model tersebut mungkin secara default memprediksi nilai konstan (misalnya, rata-rata data).

Cara memperbaikinya:
  • Visualisasikan data untuk memeriksa tren, kemusiman, atau pola siklus.
  • Gunakan teknik dekomposisi (misalnya, seasonal_decompose dalam Python) untuk menganalisis komponen deret waktu. Jika tren atau kemusiman ada tetapi lemah, pertimbangkan untuk memodelkannya secara eksplisit menggunakan alat seperti:
  • Menambahkan komponen musiman dalam ARIMA (SARIMA).
  • Menggunakan fitur eksternal (misalnya, hari dalam seminggu, hari libur) dalam model pembelajaran mesin.

2. Konfigurasi Model yang Buruk

Mengapa hal ini terjadi: Parameter model mungkin tidak disetel dengan benar, yang menyebabkan underfitting. Misalnya:
  • Dalam ARIMA, parameter (p, d, q) mungkin tidak optimal.
  • Dalam LSTM, arsitektur (misalnya, jumlah lapisan, neuron) atau hiperparameter (misalnya, laju pembelajaran, ukuran batch) mungkin tidak sesuai dengan data.
Cara memperbaikinya:
  • Untuk ARIMA, gunakan alat seperti auto_arima untuk menemukan parameter terbaik secara otomatis.
  • Untuk LSTM, bereksperimenlah dengan arsitektur, laju pembelajaran, dan durasi pelatihan yang berbeda.
  • Validasi model secara teratur menggunakan metrik seperti RMSE atau MAE pada set validasi.


3. Data Tidak Cukup

Mengapa hal ini terjadi: Jika kumpulan data terlalu kecil atau tidak memiliki variabilitas, model mungkin kesulitan mempelajari pola yang bermakna.

Cara memperbaikinya:
  • Pastikan Anda memiliki cukup data historis untuk melatih model secara efektif.
  • Jika datanya jarang, pertimbangkan untuk menggabungkannya (misalnya, harian → mingguan) untuk mengurangi gangguan dan menyorot pola.

4. Pemulusan Berlebihan Selama Prapemrosesan

Mengapa hal ini terjadi: Langkah-langkah prapemrosesan seperti pemulusan berlebihan, pembedaan, atau normalisasi dapat menghilangkan pola penting dari data.

Cara memperbaikinya:
  • Hindari pembedaan berlebihan pada data dalam ARIMA (gunakan d minimum yang diperlukan untuk mencapai stasioneritas).
  • Berhati-hatilah dengan normalisasi. Misalnya, jika rentang nilai terlalu padat, model mungkin memprediksi mendekati rata-rata.
  • Pertahankan skala asli data saat mengevaluasi prediksi. 


5. Model Memprediksi Rata-rata

Mengapa hal ini terjadi: Banyak model, terutama yang lebih sederhana seperti ARIMA, cenderung memprediksi rata-rata data ketika tidak dapat mengidentifikasi pola yang jelas.

Cara memperbaikinya:
  • Tambahkan regresor eksternal (misalnya, cuaca, hari libur) untuk memberikan konteks tambahan.
  • Gunakan model yang lebih kompleks seperti LSTM atau peningkatan gradien yang dapat mempelajari hubungan non-linier.
  • Periksa residual model untuk memastikannya acak. Jika residual menunjukkan pola, model tersebut kurang sesuai.

6. Fitur Input yang Salah

Mengapa hal ini terjadi: Jika fitur input tidak cukup mewakili dependensi temporal, model mungkin gagal untuk belajar.
Cara memperbaikinya:
  • Sertakan fitur yang tertinggal (misalnya, pengamatan sebelumnya) untuk model pembelajaran mesin.
  • Gunakan pengetahuan domain untuk merekayasa fitur yang bermakna (misalnya, rata-rata bergulir, indikator hari dalam seminggu). 


7. Evaluasi pada Pola yang Tak Terlihat

Mengapa hal ini terjadi: Jika data pengujian berisi pola yang tidak terlihat dalam data pelatihan, model mungkin akan menggunakan prediksi datar secara default.

Cara memperbaikinya:
  • Pastikan set data pelatihan dan pengujian berasal dari distribusi yang sama.
  • Gunakan teknik validasi silang seperti pemisahan deret waktu untuk mengevaluasi kinerja model pada data yang tak terlihat.


8. Regresor Eksternal yang Konstan

Mengapa hal ini terjadi: Jika fitur eksternal (misalnya, cuaca, peristiwa) konstan atau tidak memiliki variabilitas, model mungkin tidak mempelajari hubungan yang bermakna.

Cara memperbaikinya:
  • Pastikan fitur eksternal memiliki variabilitas dan relevansi yang cukup terhadap variabel target.
  • Hapus fitur yang tidak relevan atau konstan dari set data.


9. Pelatihan pada Cakrawala yang Terlalu Pendek

Mengapa hal ini terjadi: Jika model dilatih pada urutan yang sangat pendek atau cakrawala prakiraan yang terbatas, model mungkin gagal untuk digeneralisasi ke cakrawala yang lebih panjang.

Cara memperbaikinya:
  • Latih model pada urutan yang lebih panjang atau perluas cakrawala prakiraan selama pelatihan.
  • Gunakan teknik peramalan multi-langkah (misalnya, peramalan rekursif atau langsung) untuk prediksi jangka panjang.

10. Kebocoran Data

Mengapa hal ini terjadi: Jika informasi masa depan bocor ke dalam data pelatihan, model mungkin gagal untuk digeneralisasi dan menghasilkan prediksi yang tidak realistis.

Cara memperbaikinya:
  • Pastikan set pelatihan dan pengujian dipisahkan secara ketat dalam waktu.
  • Hindari penggunaan data masa depan (misalnya, nilai target) sebagai fitur selama pelatihan.


- Powered by Qwen AI -
Share:

0 komentar:

Posting Komentar

Kontak Penulis



12179018.png (60×60)
+628155737755

Mail : ahocool@gmail.com

Site View

Categories

555 (8) 7 segmen (3) adc (4) amplifier (2) analog (19) android (14) antares (11) arduino (28) artikel (11) attiny (3) attiny2313 (19) audio (5) baterai (5) blog (1) bluetooth (1) chatgpt (2) cmos (2) crypto (2) dasar (46) digital (11) dimmer (5) display (3) esp8266 (26) euro2020 (13) gcc (1) gis (3) gsm (1) iklan (1) infrared (2) Input Output (3) iot (78) jam (7) jualan (12) kereta api (1) keyboard (1) keypad (3) kios pulsa (2) kit (6) komponen (17) komputer (3) komunikasi (1) kontrol (8) lain-lain (8) lcd (2) led (14) led matrix (6) line tracer (1) lm35 (1) lora (11) lorawan (2) MATV (1) memory (1) metal detector (4) microcontroller (70) micropython (6) mikrokontroler (2) mikrokontroller (14) mikrotik (5) modbus (9) mqtt (3) ninmedia (5) ntp (1) paket belajar (19) palang pintu otomatis (1) parabola (88) pcb (2) power (1) praktek (2) project (33) proyek (1) python (9) radio (28) raspberry pi (9) remote (1) revisi (1) rfid (1) robot (1) rpm (2) rs232 (1) script break down (3) sdcard (3) sensor (2) sharing (3) signage (1) sinyal (1) sms (6) software (18) solar (1) solusi (1) statistik (5) tachometer (2) technology (1) teknologi (2) telegram (2) telepon (9) televisi (167) television (28) telkomiot (5) transistor (2) troubleshoot (3) tulisan (94) tutorial (108) tv digital (6) tvri (2) unesa (8) vu meter (2) vumeter (2) wav player (3) wayang (1) wifi (3) yolo (9)

Arsip Blog

Diskusi


kaskus
Forum Hobby Elektronika