Model Support Vector Regression (SVR) dengan Scikit-Learn

Support Vector Regression (SVR) Python Scikit-learn

Support Vector Regression (SVR)

SVR adalah varian dari Support Vector Machine (SVM) yang digunakan untuk permasalahan regresi, yaitu memprediksi nilai kontinu. Tujuan utama SVR adalah menemukan fungsi regresi yang dapat memprediksi nilai kontinu dengan optimal, dengan menjaga agar kesalahan prediksi berada dalam batas toleransi tertentu yang disebut epsilon (ε). Secara spesifik SVR bertujuan untuk:

  • Minimalkan Kesalahan Prediksi: SVR mencoba meminimalkan kesalahan prediksi dengan memfokuskan hanya pada kesalahan yang melebihi margin epsilon, sehingga model lebih tahan terhadap noise kecil dalam data.
  • Generalisasi hasil: Dengan menggunakan konsep margin dan support vectors, SVR bertujuan untuk menghasilkan model yang tidak hanya sesuai dengan data pelatihan, tetapi juga dapat melakukan prediksi yang baik pada data baru yang belum pernah dilihat sebelumnya.
  • Penanganan Data Non-Linear: Melalui penggunaan kernel trick, SVR dapat menangani hubungan yang kompleks dan non-linear antara fitur-fitur dalam data, memungkinkan model untuk bekerja dengan baik pada berbagai jenis data.

Konsep Utama dalam SVR:

  • Epsilon-Insensitive Tube (ε): Sebuah margin epsilon di sekitar fungsi regresi di mana titik-titik data di dalam margin tersebut dianggap sebagai prediksi yang benar.
  • Support Vectors: Titik-titik data yang berada di luar margin epsilon yang menentukan fungsi regresi.
  • Kernel: Fungsi yang memetakan data ke dalam ruang fitur berdimensi tinggi sehingga memungkinkan memisahkan atau mendekati data dengan lebih baik.

Tutorial ini akan membahas implementasi SVR dengan Python menggunakan pustaka scikit-learn. Pembahasan akan mencakup langkah-langkah mulai dari penyiapan dataset, transformasi data, pembagian dataset, pemodelan SVR, serta evaluasi performa model. Selain itu, pembahasan juga mencakup cara melakukan tuning hyperparameter menggunakan Grid Search untuk mencari model SVR terbaik. Keseluruhan proses pemodelan juga akan dilakukan dengan menerapkan pipelining, sehingga model nantinya dapat digunakan untuk memprediksi data baru tanpa harus melakukan tahapan-tahapan preprocessing secara manual.

Penyiapan Data

Dalam tutorial ini, kita akan menggunakan dataset prediksi umur kepiting yang tersedia di Kaggle (Crab Age Prediction). Dataset ini berisi berbagai fitur karakter morfologis dari kepiting yang digunakan untuk memprediksi perkiraan umurnya. Total observasi pada dataset adalah sebanyak 3.893 yang terdiri dari 8 buah fitur dengan 1 peubah respon yaitu Age (dalam bulan).

Python

import pandas as pd

data = pd.read_csv("https://raw.githubusercontent.com/sainsdataid/dataset/main/crab_age_dataset.csv")

data.info()
# OUTPUT

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3893 entries, 0 to 3892
Data columns (total 9 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   Sex             3893 non-null   object 
 1   Length          3893 non-null   float64
 2   Diameter        3893 non-null   float64
 3   Height          3893 non-null   float64
 4   Weight          3893 non-null   float64
 5   Shucked Weight  3893 non-null   float64
 6   Viscera Weight  3893 non-null   float64
 7   Shell Weight    3893 non-null   float64
 8   Age             3893 non-null   int64  
dtypes: float64(7), int64(1), object(1)
memory usage: 273.9+ KB

Transformasi dan Pembagian Data

Dataset yang kita gunakan memiliki 1 fitur dengan tipe kategorik yaitu Sex dengan 3 kategori nilai yaitu M untuk Male, F untuk Female dan I untuk Indetermine. Oleh karena itu kolom Sex perlu ditransformasi terlebih dahulu. Transformasi yang akan kita gunakan adalah One-hot Encoding.

Model SVR merupakan model berbasis jarak, sehingga sensitif terhadap skala fitur yang berbeda-beda. Oleh karena itu, kita juga perlu melakukan transformasi fitur numerik agar memiliki skala yang sama misalkan dengan standardisasi. Standardisasi mengubah skala fitur sehingga memiliki mean 0 dan standar deviasi 1, yang membantu mempercepat konvergensi algoritma optimasi serta meningkatkan kinerja model. Dengan memastikan semua fitur berada pada skala yang sama, model dapat mempelajari pola yang lebih konsisten dan akurat untuk setiap fiturnya.

Transformasi data akan dilakukan menggunakan fungsi ColumnTransformer dari modul sklearn.compose, dengan peubah kategorik menggunakan fungsi OneHotEncoder dan standardisasi peubah numerik dengan fungsi StandardScaler.

Transformasi menyebabkan struktur data berubah. Proses ini tentunya juga harus terus dilakukan seandainya kita memiliki data baru dikemudian hari. Oleh karena itu, untuk memastikan setiap data baru nantinya akan melewati tahapan preprocessing yang sama (encoding fitur kategorik dan standardisasi fitur numerik) maka seluruh tahapan pemodelan akan kita kerjakan dalam bentuk pipelining. Proses ini dilakukan menggunakan fungsi Pipeline dari model sklearn.pipeline.

Pada tahap ini, kita juga membagi dataset menjadi data latih dan data uji. Data latih akan digunakan untuk pelatihan model serta tuning hyperparameter. Sedangkan data uji digunakan untuk mengevaluasi kinerja model. Pembagian dataset dilakukan menggunakan fungsi train_test_split dari modul sklearn.model_selection dengan proprosi 80 persen data latih dan 20 persen data uji.

Python

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split

# Memilih fitur dan target
X = data.drop(columns="Age")
y = data["Age"]

# Membagi dataset menjadi set pelatihan dan pengujian
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Membuat ColumnTransformer
num_features = [
    "Length",
    "Diameter",
    "Height",
    "Shucked Weight",
    "Viscera Weight",
    "Shell Weight",
]
cat_feature = ["Sex"]

# Pipeline untuk preprocessing numerik
numeric_transformer = Pipeline(steps=[("scaler", StandardScaler())])

# Pipeline untuk preprocessing kategorik
categorical_transformer = Pipeline(steps=[("onehot", OneHotEncoder())])

# Menggabungkan langkah preprocessing dengan ColumnTransformer
preprocessor = ColumnTransformer(
    transformers=[
        ("num", numeric_transformer, num_features),
        ("cat", categorical_transformer, cat_feature),
    ]
)

Model SVR

Sebelum kita melatih model, penting untuk memahami parameter dalam proses pembangunan model SVR dan bagaimana nilai-nilai tersebut mempengaruhi kinerja model. Pembuatan model SVR dilakukan menggunakan fungsi SVR dari modul sklearn.SVM. Fungsi SVR memiliki beberapa parameter yang dapat diatur meliputi:

  • C: Parameter regularisasi. Tingkat regularisasi yang diterapkan adalah berbanding terbalik dengan C. parameter ini harus bernilai positif. Penalti yang digunakan pada proses regularisasi adalah L2 kuadrat.
  • kernel: Fungsi kernel yang digunakan untuk memproyeksikan data ke dalam ruang fitur yang lebih tinggi. Kernel yang umum digunakan meliputi 'linear' (kernel linear), 'poly' (kernel polinomial), 'rbf' (Radial Basis Function kernel atau Gaussian kernel), dan 'sigmoid' (kernel sigmoid). Dapat juga menggunakan fungsi yang kita definisikan sendiri. Default: 'rbf'
  • degree: derajat polinomial jika menggunakan kernel polinomial (kernel='poly'). Default: 3
  • gamma: Koefisien kernel untuk fungsi kernel rbfpoly, dan sigmoid. Nilai gamma mengontrol seberapa jauh pengaruh dari satu data training tunggal. Nilai yang kecil berarti pengaruh yang lebih besar dari setiap data poin. Default: 'scale' (yaitu 1 / (n_features * X.var()))
  • coef0: Parameter untuk bias (intercept) dalam kernel polinomial dan sigmoid. Default: 0.0
  • tol: Toleransi untuk menghentikan kriteria yang mengontrol presisi dari solusi akhir. Default: 1e-3
  • max_iter: Batas maksimal iterasi untuk algoritma pelatihan. Default: -1 (tanpa batas iterasi, penghentian algoritma berdasarkan nilai tol)

Pemodelan

Model SVR pertama yang kita buat adalah SVR dengan kernel polinomial derajat 2 serta nilai C=100 dan gamma=0.1. Nilai-nilai lainnya tetap menggunakan nilai defaultnya masing-masing.

Seperti penjelasan sebelumnya, pemodelan akan kita lakukan menggunakan pipeline, sehingga kita perlu membuat objek Pipeline untuk mendefinisikan tahapan-tahapan pemodelan. Dalam hal ini, hanya terdapat dua tahap saja yang diberi nama preprocessor dan regressor. Tahapan preprocessor yaitu proses transformasi data dan regressor adalah tahapan pemodelan dengan SVR.

Python

from sklearn.svm import SVR

model_svr = SVR(C=100, degree=2, gamma=0.1, kernel="poly")

# Pipeline lengkap dengan model SVR
svr_pipeline = Pipeline(
    steps=[("preprocessor", preprocessor), ("regressor", model_svr)]
)

# Melatih model SVR dengan pipeline
svr_pipeline.fit(X_train, y_train)
# OUTPUT

SVR(C=100, degree=2, gamma=0.1, kernel='poly')

Prediksi dan Evaluasi Model

Model yang telah dilatih selanjutnya dievaluasi dengan data uji. Evaluasi model dilakukan dengan membuat prediksi nilai Age untuk setiap observasi pada data uji. Hasil prediksi kemudian dibandingkan dengan nilai sebenarnya. Pada contoh ini, kita akan menggunakan metrik Mean Absolute Percentage Error (MAPE).

Hasil di bawah ini menunjukkan nilai MAPE sebesar 14,12%. Artinya, berdasarkan data uji secara rata-rata tingkat kesalahan prediksi model adalah sebesar 14,12% dari nilai sebenarnya.

Python

from sklearn.metrics import mean_absolute_percentage_error

# Prediksi
y_pred = svr_pipeline.predict(X_test)

# Evaluasi
mape = mean_absolute_percentage_error(y_test, y_pred) * 100

print(f"MAPE: {round(mape, 2)}%")
# OUTPUT

MAPE: 14.12%

Untuk mencari kemungkinan model SVR dengan kinerja yang lebih baik, penting untuk melakukan proses tuning hyperparameter. Tuning hyperparameter membantu menemukan kombinasi parameter yang optimal untuk model tersebut. Di sini, kita akan menggunakan teknik yang paling sederhana yaitu Grid Search.

Penentuan Nilai Hyperparameter

Pertama, kita tentukan terlebih dahulu daftar nilai-nilai yang akan menjadi dasar pencarian. Pada contoh ini, pencarian akan menggunakan kombinasi dari 5 hyperparameter yaitu C, gamma, epsilon, kernel dan degree dengan nilai seperti yang ditampilkan pada kode di bawah ini. Nantinya, proses pencarian akan dilakukan pada setiap kombinasi yang terbentuk dari keseluruhan hyperparameter tersebut.

Terlihat pada kode di bawah ini, terdapat penambahan teks "regressor__" di bagian awal nama-nama hyperparameter. Penambahan ini diperlukan sebagai identifikasi dalam proses pipeline bahwa nilai-nilai yang diberikan merupakan bagian dari step "regressor".

Perlu menjadi catatan juga, semakin banyak hyperaparameter dan nilai yang diberikan maka proses pencarian Grid Search akan semakin lama. Jadi, untuk proses pembelajaran silahkan jika ingin menyesuaikan ukurannya menjadi lebih sedikit agar tidak menghabiskan waktu.

Python

# Daftar nilai hyperaprameter
param_grid = {
    "regressor__C": [1, 10, 20, 100],
    "regressor__gamma": [0.01, 0.1, 0.2],
    "regressor__epsilon": [0.01, 0.1, 0.5, 1],
    "regressor__kernel": ["linear", "poly", "rbf"],
    "regressor__degree": [2, 3],  # Hanya untuk kernel 'poly'
}

Pencarian Model

Proses Grid Search dilakukan dengan fungsi GridSearchCV dari modul sklearn.model_selection. Pengukuran kinerja model akan dilakukan menggunakan validasi silang K-Fold dengan 5 fold dengan metrik MAPE. (catatan: fungsi GridSearchCV selalu menggunakan nilai terbesar sebagai nilai yang lebih baik, oleh karena itu untuk nilai MAPE, scoring yang digunakan adalah "neg_mean_absolute_percentage_error").

Hasil pencarian menunjukkan kinerja model terbaik saat pelatihan memiliki nilai MAPE sebesar 14,28% (rata-rata berdasarkan validasi silang K-Fold). Nilai ini diperoleh pada model dengan kernel="rbf"; C=10; epsilon=0.5 dan gamma=0.1. (nilai degree dapat diabaikan karena kernel yang digunakan adalah rbf)

Python

from sklearn.model_selection import GridSearchCV

# Inisiasi Model Awal
base_model = SVR()

# Inisiasi Model Pipeline
svr_pipeline_cv = Pipeline(
    steps=[("preprocessor", preprocessor), ("regressor", base_model)]
)

# Inisiasi Grid Search
grid_search = GridSearchCV(
    svr_pipeline_cv,
    param_grid,
    cv=5,
    refit=True,
    scoring="neg_mean_absolute_percentage_error",
    n_jobs=-1,          # gunakan seluruh CPU core yang tersedia
)

# Fit model
grid_search.fit(X_train, y_train)

# Mendapatkan parameter terbaik
best_par = grid_search.best_params_
print("Parameter terbaik:\n", best_par)

# Mendapatkan skor terbaik
mape_cv = -100 * grid_search.best_score_
print("Skor MAPE terbaik:\n", mape_cv)
# OUTPUT

Parameter terbaik:
 {'C': 10, 'degree': 2, 'epsilon': 0.5, 'gamma': 0.1, 'kernel': 'rbf'}

Skor MAPE terbaik:
 14.24

Prediksi dan Evaluasi

Berdasarkan hasil temuan hyperparameter terbaik tersebut, kita dapat mengevaluasi kinerja model dengan data uji seperti sebelumnya. Hasil evaluasi menunjukkan nilai MAPE model sebesar 13,93%. Nilai ini sedikit lebih baik dibandingkan model awal tanpa tuning hyperparameter.

Python

# Memilih model terbaik
best_model = grid_search.best_estimator_

# prediksi data uji
pred_cv = best_model.predict(X_test)

# Evaluasi
mape = mean_absolute_percentage_error(y_test, pred_cv) * 100

print(f"MAPE: {round(mape, 2)}%")
# OUTPUT

MAPE: 13.93%

Persistensi Model

Persistensi model adalah proses menyimpan model yang telah dilatih ke dalam sebuah file sehingga model tersebut dapat digunakan kembali di masa depan tanpa perlu melatih ulang. Ini sangat berguna ketika kita ingin menggunakan model yang sama untuk melakukan prediksi di waktu mendatang atau untuk diterapkan pada aplikasi produksi.

Menyimpan Model

Setelah model terbaik ditemukan melalui proses pelatihan dan tuning hyperparameter, kita dapat menyimpannya menggunakan fungsi dump dari pustaka joblib. File yang dihasilkan akan berisi seluruh informasi yang diperlukan untuk merekonstruksi model, termasuk struktur model dan bobot yang telah dilatih. Misalnya, joblib.dump(best_model, 'model_svr.pkl') akan menyimpan model terbaik ke dalam file model_svr.pkl.

Python

import joblib

joblib.dump(best_model, "model_svr.pkl")
print("Model saved to model_svr.pkl")
# OUTPUT

Model saved to model_svr.pkl

Memuat Model

Model yang telah disimpan dapat dimuat kembali dari file menggunakan fungsi load dari pustaka joblib. Misalnya, loaded_model = joblib.load('model_svr.pkl') akan memuat model dari file model_svr.pkl dan menyimpannya dalam variabel loaded_model.

Python

loaded_model = joblib.load("model_svr.pkl")
print("Model loaded from model_svr.pkl")
# OUTPUT

Model loaded from catboost_model.pkl

Prediksi Data Baru

Setelah model dimuat, kita dapat menggunakannya untuk membuat prediksi pada data baru. Misalkan, terdapat data baru dari 2 data kepiting baru. Berdasarkan data tersebut, maka kita dapat memprediksi perkiraan umur kepiting tersebut menggunkaan model ada.

Salah satu keunggulan penggunaan pipeline dalam pelatihan model adalah kita tidak perlu memikirkan tahapan-tahapan preprocessing seperti encoding data, standardisasi data maupun proses lainnya ketika berhadapan dengan data baru. Keseluruhan proses tersebut akan dikerjakan secara otomatis saat kita melakukan prediksi menggunakan model tersebut.

Kode berikut ini menampilkan ilustrasi yaitu terdapat dua data baru yang akan diprediksi. Karena kita menggunakan pipeline maka data tersebut dapat langsung diprediksi tanpa harus melakukan proses one-hot encoding pada peubah Sex maupun standardisasi nilai peubah numeriknya. Dapat dilihat hasil prediksi untuk kepiting pertama diperkirakan berumur sekitar 6,9 bulan dan kepiting kedua berumur sekitar 10 bulan.

Python

# contoh data baru
data_baru = [
    {
        "Sex": "I",
        "Length": 1.05,
        "Diameter": 0.8,
        "Height": 0.25,
        "Weight": 9.63,
        "Shucked Weight": 4.94,
        "Viscera Weight": 1.41,
        "Shell Weight": 2.67,
    },
    {
        "Sex": "M",
        "Length": 1.45,
        "Diameter": 1.15,
        "Height": 0.375,
        "Weight": 29.73,
        "Shucked Weight": 14.75,
        "Viscera Weight": 5.48,
        "Shell Weight": 8.64,
    },
]

# Reformat data menjadi dataframe
data_baru_df = pd.DataFrame(data_baru)

# Prediksi Umur Kepiting
pred_baru = loaded_model.predict(data_baru_df)

print(pred_baru)
# OUTPUT

[6.89733796 9.99640727]

Selamat mencoba!

API

Tulisan Lainnya

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Daftar Isi