Regularisasi Model: Ridge, LASSO dan Elastic Net dengan Python


Apa itu Regularisasi?
Dalam dunia pembelajaran mesin (machine learning), regularisasi adalah teknik yang digunakan untuk mencegah overfitting, yaitu situasi di mana model mempelajari data pelatihan secara berlebihan, termasuk noise dan detail yang tidak relevan, sehingga model tidak dapat menangkap pola yang lebih umum dan menyebabkan kinerjanya pada data baru (data uji) menurun. Regularisasi umumnya berupa penambahan penalti terhadap kompleksitas model, sehingga memaksa model untuk menyederhanakan fungsi yang dipelajari.
Terdapat beberapa metode regularisasi populer yang umum digunakan khususnya pada model regresi yaitu Ridge (L2), Lasso (L1) dan Elastic Net (L1 + L2). Ketiga metode tersebut menambahkan penalti terhadap ukuran koefisien regresi. Tujuan utamanya adalah untuk mengecilkan besaran koefisien regresi, dalam rangka mengurangi varian model tanpa meningkatkan bias secara signifikan.
Regresi Ridge (L2)
Regresi Ridge atau disebut juga Regularisasi L2 bentuk regularisasi peubah pada model regresi. Koefisien model regresi ridge diperoleh dengan meminimumkan Residual Sum of Squares (RSS) seperti pada model regresi (OLS) biasa namun ditambah dengan penalti $\lambda \sum_{j=1}^p(\beta_j^2)$. Besaran penalti dikontrol melalui koefisien π di mana semakin besar nilai π, maka nilai koefisien regresi akan semakin mendekati 0.
Formula matematika untuk Regresi Ridge adalah sebagai berikut:
$\begin{aligned}J(\beta) = \sum_{i=1}^{n}(y_i – \hat{y_i})^2 + \lambda \sum_{j=1}^{p} \beta_j^2 \end{aligned}β$
di mana:
- $J(\beta)$ adalah loss function (fungsi yang akan diminimumkan)
- $y_i$β adalah nilai sebenarnya
- $\hat{y}_i$β adalah nilai prediksi
- $\lambda$ adalah parameter regularisasi
- $\beta_j$β adalah koefisien regresi
- $p$ adalah jumlah fitur
Penalti L2 dalam Regresi Ridge bekerja mengurangi besarnya koefisien regresi, dan “memaksa” model menjadi lebih sederhana. Hal ini akan mengurangi risiko overfitting, terutama ketika terdapat kondisi multikolinearitas di antara fitur-fitur dalam data. Regresi Ridge cenderung menghasilkan solusi yang stabil. Pada regresi ridge, koefisien regresi dapat menghasilkan nilai sekecil mungkin namun tidak akan pernah benar-benar menyentuh nilai 0. Oleh karena itu jumlah fitur yang digunakan dalam proses prediksi menggunakan regresi ridge akan tetap sama banyaknya dengan model OLS biasa.
Regresi LASSO (L1)
Regresi LASSO (Least Absolute Shrinkage and Selection Operator) bekerja dengan menambahkan penalti L1 pada model OLS biasa. Serupa dengan Ridge, Regresi LASSO bertujuan meminimumkan RSS namun dengan tambahan penalti L1 yaitu $\lambda \sum_{j=1}^p|\beta_j|$.
Formula matematika untuk Regresi LASSO adalah sebagai berikut:
$\begin{aligned}J(\beta) = \sum_{i=1}^{n}(y_i – \hat{y_i})^2 + \lambda \sum_{j=1}^{p}|\beta_j| β\end{aligned}$
Pada Regresi LASSO, penyusutan nilai koefisien regresi dapat mencapai nilai 0, sehingga Regresi LASSO juga berfungsi sebagai metode seleksi fitur. Hal ini sangat berguna ketika kita memiliki banyak fitur dan ingin menentukan fitur mana yang paling berpengaruh. Fitur-fitur dengan koefisien 0 berarti dapat diangggap tidak memiliki pengaruh dan tidak digunakan dalam pemodelan sehingga membuat model menjadi lebih sederhana. Namun, hal ini juga dapat menjadi kelemahan ketika terdapat ftur-fitur yang berkorelasi. Fitur yang sebenarnya penting bisa ikut terseleksi jika terdapat korelasi yang kuat dengan fitur lainnya.
Elastic Net (L1 + L2)
Elastic Net merupakan gabungan penalti L1 dan L2. Dengan kata lain, Elastic Net adalah bentuk “kompromi” antara Ridge dan LASSO, dengan harapan menggabungkan kelebihan dari kedua metode tersebut.
Formula matematika untuk Elastic Net adalah sebagai berikut:
$\begin{aligned}J(\beta) = \sum_{i=1}^{n}(y_i – \hat{y_i})^2 + \lambda_1 \sum_{j=1}^{p} \beta_j^2 + \lambda_2 \sum_{j=1}^{p}|\beta_j| β\end{aligned}$
di mana $\lambda_1$ dan $\lambda_2$ masing-masing merupakan parameter regularisasi bagi L1 dan L2.
Regularisasi dengan Python
Penyiapan Pustaka
Berikut adalah pustaka-pustaka yang digunakan pada tutorial ini. Jika belum tersedia, dapat diinstal menggunakan pip
dengan sintaks berikut:
pip install pandas numpy scikit-learn
Selanjutnya, import paket dan modul yang diperlukan:
pandas
: untuk membaca dataset (csv)numpy
: untuk membuat daftar nilai parameter dengan fungsilinspace
danlogspace
scikit-learn
: untuk pembagian data latih dan data uji, standardisasi data, pemodelan dan evaluasi model
Python
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import ( Lasso, Ridge, ElasticNet, LassoCV, RidgeCV, ElasticNetCV, ) from sklearn.metrics import root_mean_squared_error
Penyiapan Data
Dataset yang digunakan adalah data simulasi sebanyak 10.000 observasi dengan 10 fitur (X1, X2, ..., X10
) dan peubah respon bertipe numerik Y
. Data akan dibagi menjadi data latih dan data uji dengan proporsi masing-masing sebesar 70 persen dan 30 persen.
Selanjutnya, kita juga akan melakukan standardisasi fitur menggunakan StandardScaler
dari modul sklearn.preprocessing
. Standardisasi data akan membuat skala setiap fitur menjadi seragam. Hal ini dapat mempercepat proses konvergensi dalam pencarian koefisien regresi.
Pada model regresi, terdapat keuntungan lain menggunakan standardisasi fitur. Besaran koefisien regresi (absolut) yang dihasilkan, secara langsung menunjukkan tingkat kepentingan fitur tersebut dalam model. Semakin tinggi nilai koefisiennya, maka semakin tinggi juga pengaruh fitur tersebut terhadap hasil prediksi model. Hal ini tidak berlaku jika satuan antar fitur berbeda-beda.
Python
# membaca dataset import pandas as pd data = pd.read_csv("https://sainsdata.id/wp-content/uploads/2023/01/data_simulasi.csv") print(data.info()) # Memilih fitur dan target X = data.drop(columns="Y") y = data["Y"] # Membagi dataset menjadi set pelatihan dan pengujian X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=123 ) # standardisasi data scaler = StandardScaler() X_train = scaler.fit_transform(X_train) X_test = scaler.transform(X_test)
# OUTPUT <class 'pandas.core.frame.DataFrame'> RangeIndex: 10000 entries, 0 to 9999 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 X1 10000 non-null float64 1 X2 10000 non-null float64 2 X3 10000 non-null float64 3 X4 10000 non-null float64 4 X5 10000 non-null float64 5 X6 10000 non-null float64 6 X7 10000 non-null float64 7 X8 10000 non-null float64 8 X9 10000 non-null float64 9 X10 10000 non-null float64 10 Y 10000 non-null float64 dtypes: float64(11) memory usage: 859.5 KB
Model Regresi Linier (OLS)
Sebagai perbandingan, mari kita buat model Regresi Linier biasa (tanpa regularisasi) terlebih dahulu menggunakan fungsi LinearRegression
.
Python
# Model OLS model_ols = LinearRegression() # Fitting model ols model_ols.fit(X_train, y_train) # prediksi data uji y_pred_ols = model_ols.predict(X_test) # menghitung RMSE model ols pada data uji rmse_ols = root_mean_squared_error(y_test, y_pred_ols) print(f"RMSE (Testing): {rmse_ols}") # menampilkan nama dan keofisien setiap fitur features_name = data.drop(columns="Y").columns.to_list() coef_ols = pd.DataFrame({"Fitur": features_name, "Koefisien": model_ols.coef_}) print(f"\n{coef_ols}")
# OUTPUT RMSE (Testing): 10.14100506254817 Fitur Koefisien 0 X1 20.678204 1 X2 7.883093 2 X3 7.808659 3 X4 4.055257 4 X5 4.044879 5 X6 2.938155 6 X7 0.572541 7 X8 -0.493608 8 X9 0.109635 9 X10 -0.347439
Regresi Ridge
Model Regresi Ridge dapat dibuat menggunakan fungsi Ridge
dari modul sklearn.linear_model
. Parameter yang perlu ditentukan adalah alpha
yaitu besaran nilai konstanta regularisasi atau dalam persamaan sebelumnya adalah nilai bagi ($\lambda$). Nilai alpha
dapat berupa nilai positif apapun. Jika ditetapkan alpha=0
, hal ini berarti sama saja dengan model OLS biasa tanpa adapnya regularisasi.
catatan: agar tidak menjadi bingung perlu diingat bahwa terminologi yang umum digunakan dalam persamaan matematisnya adalah lambda ($\lambda$) namun implementasi menggunakan python scikit-learn adalah alpha
.
Hasil evaluasi nilai RMSE pada data uji dengan alpha=1
memberikan kinerja yang sedikit lebih baik dibandingkan OLS biasa yaitu 10,1407
.
Python
# Model Ridge dengan alpha=1 model_ridge = Ridge(alpha=1) # Fitting model Ridge model_ridge.fit(X_train, y_train) # prediksi data uji y_pred_ridge = model_ridge.predict(X_test) # menghitung RMSE model Ridge pada data uji rmse_ridge = root_mean_squared_error(y_test, y_pred_ridge) print(f"RMSE (Testing): {rmse_ridge}") # menampilkan nama dan keofisien setiap fitur features_name = data.drop(columns="Y").columns.to_list() coef_ridge = pd.DataFrame({"Fitur": features_name, "Koefisien": model_ridge.coef_}) print(f"\n{coef_ridge}")
# OUTPUT RMSE (Testing): 10.140752153776702 Fitur Koefisien 0 X1 20.584537 1 X2 7.881939 2 X3 7.807907 3 X4 4.054846 4 X5 4.044441 5 X6 2.917098 6 X7 0.572513 7 X8 -0.406173 8 X9 0.115693 9 X10 -0.326448
Regresi LASSO
Model Regresi Lasso dapat dibuat menggunakan fungsi Lasso
yang juga terdapat pada modul sklearn.linear_model
. Sama seperti Regresi Ridge, parameter yang perlu ditetapkan adalah alpha
.
Berdasarkan hasil di bawah ini, model Regresi Lasso dengan nilai alpha=1
menghasilkan nilai RMSE sebesar 10,3700
di mana lebih besar dibandingkan model OLS dan Ridge sebelumnya. Namun, perlu dilihat juga bahwa model menjadi jauh lebih sederhana karena terdapat 4 fitur dengan nilai keofisien 0
. Artinya, dengan menggunakan 6 fitur saja, kinerja model hanya sedikit lebih rendah dibandingkan model dengan 11 fitur.
Python
# Model LASSO dengan alpha=1 model_lasso = Lasso(alpha=1) # Fitting model LASSO model_lasso.fit(X_train, y_train) # prediksi data uji y_pred_lasso = model_lasso.predict(X_test) # menghitung RMSE dan R^2 model LASSO pada data uji rmse_lasso = root_mean_squared_error(y_test, y_pred_lasso) print(f"RMSE (Testing): {rmse_lasso}") # menampilkan nama dan keofisien setiap fitur features_name = data.drop(columns="Y").columns.to_list() coef_lasso = pd.DataFrame({"Fitur": features_name, "Koefisien": model_lasso.coef_}) print(f"\n{coef_lasso}")
# OUTPUT RMSE (Testing): 10.370011422334644 Fitur Koefisien 0 X1 19.273076 1 X2 6.865779 2 X3 6.793670 3 X4 3.042861 4 X5 3.057963 5 X6 1.872630 6 X7 0.000000 7 X8 0.000000 8 X9 0.000000 9 X10 0.000000
Regresi Elastic Net
Model Elastic Net dibuat menggunakan fungsi ElasticNet dari modul sklearn.linear_model
. Pada fungsi ini, terdapat 1 parameter lagi yang dapat diatur yaitu l1_ratio
. Nilai 11_ratio
adalah parameter yang menentukan bagaimana regulasi L1 dan L2 digabungkan. Jika l1_ratio
bernilai 1
, artinya sama dengan model Regresi Ridge. Sebaliknya jika bernilai 0
artinya sama dengan model regresi Lasso. Nilai di antara 0
dan 1
menunjukkan besaran rasio penalti L1 dan L2 yang diberikan pada model yaitu dengan proporsi l1_ratio
untuk L1 dan (1-l1_ratio
) untuk L2.
Contoh di bawah ini adalah model Regresi Elastic Net dengan rasio L1 sebesar 0.9 (L2=0.1) dan alpha=1. Hasil evaluasi RMSE pada data uji menunjukkan nilai yang tidak begitu baik serta tidak 1 fitur pun yang berhasil dieliminasi.
Hal ini wajar saja karena kita menetapkan nilai parameter secara acak saja. Pada bagian selanjutnya kita akan menggunakan teknik validasi silang untuk mencari kemungkinan nilai parmeter yang menghasilkan model lebih baik.
Python
# Model Elastic Net dengan rasio L1=0.9 dan alpha=1 model_elnet = ElasticNet(l1_ratio=0.9, alpha=1) # Fitting model LASSO model_elnet.fit(X_train, y_train) # prediksi data uji y_pred_elnet = model_elnet.predict(X_test) # menghitung RMSE model Elastic Net pada data uji rmse_elnet = root_mean_squared_error(y_test, y_pred_elnet) print(f"RMSE (Testing): {rmse_elnet}") # menampilkan nama dan keofisien setiap fitur features_name = data.drop(columns="Y").columns.to_list() coef_elnet = pd.DataFrame({"Fitur": features_name, "Koefisien": model_elnet.coef_}) print(f"\n{coef_elnet}")
# OUTPUT RMSE (Testing): 10.750265696411102 Fitur Koefisien 0 X1 10.203601 1 X2 6.329889 2 X3 6.295918 3 X4 2.858081 4 X5 2.881782 5 X6 1.150756 6 X7 0.000963 7 X8 7.192762 8 X9 1.363117 9 X10 0.721223
Pencarian Parameter Regularisasi
Penentuan nilai parameter yang tepat tentu dapat menghasilkan model dengan kinerja lebih optimal. Oleh karena itu, kita perlu mencoba melatih dan mengevaluasi model pada berbagai nilai alpha
(dan l1_ratio
untuk Elastic Net). Beruntung, modul sklearn.linear_model
sudah menyediakan fungsi RidgeCV
, LassoCV
dan ElasticNetCV
yang memudahkan kita untuk melakukan pencariann tersebut.
Secara umum, ketiga fungsi tersebut memiliki cara kerja yang sama. Pertama kita tentukan list nilai-nilai parameter yang akan dicobakan, misal alphas=[0.01, 0.1, ...., 1, 5, 10]
. Pembuatan list dapat juga dilakukan dengan bantuan pustaka numerik seperti numpy untuk membuat daftar yang lebih kompleks misalkan dengan fungsi linspace
dan logspace
.
Selanjutnya dengan menggunakan teknik validasi silang k-fold, akan dilakukan pemodelan untuk setiap nilai parameter yang diberikan. Evaluasi model dilakukan dengan menghitung nilai rata-rata kinerja model berdasarkan validasi silang tersebut.
Ridge CV
Pada contoh berikut, kita menggunakan fungsi logspace
dari numpy
untuk membuat daftar 50 nilai alpha pada rentang nilai 0.001 ($10^{-3}$) sampai 10. Fungsi logspace
membagi data secara logaritmik dan sangat cocok digunakan untuk membuat daftar nilai pada selang yang sangat luas. Namun seperti yang disampaikan sebelumnya, kita dapat saja menggunakan list sederhana dengan beberapa nilai alpha.
Hasil validasi silang menunjukkan nilai alpha=1.2648...
memberikan kinerja model terbaik. Selanjutnya, molde dengan nilai alpha
tersebut dapat diterapkan untuk memprediksi data uji. Nilai RMSE yang diperoleh pada data uji adalah sebesar 10,1407
dan sedikit lebih baik dibandingkan nilai RMSE model Ridge sebelumnya.
Python
# membuat daftar nilai alpha (10^-3 - 10) alphas = np.logspace(-3, 1, 50) print(alphas) model_ridge_cv = RidgeCV(alphas=alphas, cv=5) # Fitting model Lasso CV model_ridge_cv.fit(X_train, y_train) # Prediksi data uji y_pred_ridge_cv = model_ridge_cv.predict(X_test) # Menghitung RMSE pada data uji rmse_ridge_cv = root_mean_squared_error(y_test, y_pred_ridge_cv) # Nilai alpha pada model terbaik print("\nbest alpha:", model_ridge_cv.alpha_) print("RMSE (Testing):", rmse_ridge_cv) coef_ridge_cv = pd.DataFrame( {"Fitur": features_name, "Koefisien": model_ridge_cv.coef_} ) print(f"\n{coef_ridge_cv}")
# OUTPUT [1.00000000e-03 1.20679264e-03 1.45634848e-03 1.75751062e-03 2.12095089e-03 2.55954792e-03 3.08884360e-03 3.72759372e-03 4.49843267e-03 5.42867544e-03 6.55128557e-03 7.90604321e-03 ... ... ... ... 1.84206997e+00 2.22299648e+00 2.68269580e+00 3.23745754e+00 3.90693994e+00 4.71486636e+00 5.68986603e+00 6.86648845e+00 8.28642773e+00 1.00000000e+01] best alpha: 1.2648552168552958 RMSE (Testing): 10.14069041193013 Fitur Koefisien 0 X1 20.559989 1 X2 7.881634 2 X3 7.807707 3 X4 4.054736 4 X5 4.044325 5 X6 2.911612 6 X7 0.572505 7 X8 -0.383268 8 X9 0.117288 9 X10 -0.320980
LASSO CV
Dengan nilai-nilai alpha
yang sama, sekarang kita lakukan pencarian untuk Regresi Lasso. Nilai alpha
terbaik berdasarkan validasi silang adalah 0,0167...
. Selanjutnya, evaluasi model pada data uji menunjukkan nilai RMSE 10,1385...
dan sejauh menjadi nilai terbaik yang diperoleh.
Hasil pemodelan juga menunjukkan fitur X8
dan X10
memiliki koefisien bernilai 0
. Artinya model menjadi lebih sederhana karena hanya menggunakan 8 fitur saja namun memiliki kinerja lebih baik dibandingkan model yang lebih kompleks.
Python
# membuat daftar nilai alpha (10^-3 - 10) alphas = np.logspace(-3, 1, 50) # membuat model Lasso CV model_lasso_cv = LassoCV(alphas=alphas, cv=5) # Fitting model Lasso CV model_lasso_cv.fit(X_train, y_train) # Prediksi data uji y_pred_lasso_cv = model_lasso_cv.predict(X_test) # Menghitung RMSE pada data uji rmse_lasso_cv = root_mean_squared_error(y_test, y_pred_lasso_cv) # Nilai alpha pada model terbaik print("alpha:", model_lasso_cv.alpha_) print("RMSE (Testing):", rmse_lasso_cv) coef_lasso_cv = pd.DataFrame( {"Fitur": features_name, "Koefisien": model_lasso_cv.coef_} ) print(f"\n{coef_lasso_cv}")
# OUTPUT alpha: 0.016768329368110076 RMSE (Testing): 10.13854981651355 Fitur Koefisien 0 X1 20.184598 1 X2 7.866311 2 X3 7.794182 3 X4 4.039152 4 X5 4.029202 5 X6 2.584033 6 X7 0.560475 7 X8 -0.000000 8 X9 0.099201 9 X10 0.000000
Elastic Net CV
Model Elastic Net memiliki dua parameter yang dapat dicari yaitu alpha
dan l1_ratio
. Daftar nilai alpha
yang akan kita gunakan sama seperti sebelumnya. Sementara untuk l1_ratio
dengan rentang 0.01
sampai 0.99
sebanyak 20 nilai menggunakan fungsi linspace
.
Hasil pencarian menunjukkan model terbaik adalah dengan pengaturan nilai alpha=0.0167...
dan l1_ratio=0.99
. Artinya 99 persen regularisasi menggunakan L1 dan hanya 1 persen saja untuk L2. Hasil kombinasi ini memberikan kinerja yang baik pada data uji. Nilai RMSE sebesar 10.1384...
dan menjadi model dengan kinerja terbaik dibandingkan model lainnya.
Meskipun komposisi untuk Lasso sangat kecil (1 persen) namun masih mampu membuat model yang lebih sederhana dan tetap berkinerja baik dengan menghilangkan fitur X8
dan X10
.
Hasil-hasil ini tentu saja dapat berbeda, tergantung dataset yang digunakan, pembagian data latih dan data uji serta penentuan nilai-nilai parameter model. Sehingga sangat mungkin model Ridge atau model Lasso memiliki kinerja lebih baik dibandingkan Elastic Net pada data lainnya.
Python
# membuat daftar nilai alpha (10^-3 - 10) alphas = np.logspace(-3, 1, 50) # membuat daftar nilai l1_ratio (0.11 - 0.99) l1_ratios = np.linspace(0.01, 0.99, 20) # membuat model ElasticNet CV model_elnet_cv = ElasticNetCV(l1_ratio=l1_ratios, alphas=alphas, cv=5) # Fitting model Elastic Net CV model_elnet_cv.fit(X_train, y_train) # Prediksi data uji y_pred_elnet_cv = model_elnet_cv.predict(X_test) # Menghitung RMSE pada data uji rmse_elnet_cv = root_mean_squared_error(y_test, y_pred_elnet_cv) # Nilai alpha pada model terbaik print("alpha:", model_elnet_cv.alpha_) print("RMSE (Testing):", rmse_elnet_cv) coef_elnet_cv = pd.DataFrame( {"Fitur": features_name, "Koefisien": model_elnet_cv.coef_} ) print(f"\n{coef_elnet_cv}")
# OUTPUT alpha: 0.016768329368110076 l1_ratio: 0.99 RMSE (Testing): 10.138452101708406 Fitur Koefisien 0 X1 20.175734 1 X2 7.865180 2 X3 7.793050 3 X4 4.038551 4 X5 4.028712 5 X6 2.583667 6 X7 0.560751 7 X8 0.000000 8 X9 0.106351 9 X10 0.000000
Selamat mencoba!!!