Regularisasi Model: Ridge, LASSO dan Elastic Net dengan Python

Regularisasi Ridge Lasso Elastic Net 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 fungsi linspace dan logspace
  • 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!!!

API

Tulisan Lainnya

You may also like...

Leave a Reply

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

Daftar Isi