Imbalance data adalah kasus di mana kelas dataset klasifikasi memiliki proporsi yang tidak seimbang. Sebagai contoh, saya akan menggunakan dataset churn dari Kaggle untuk artikel ini.
Kita dapat melihat adanya ketidakseimbangan di kelas 1 dibandingkan dengan kelas 0. Jika kita menghitung proporsinya, proporsi kelas 1 sekitar 20,4% dari seluruh dataset. Namun, bagaimana cara mengklasifikasikan suatu data tergolong data imbalance? Tabel di bawah mungkin dapat membantu Anda.
Ada tiga kasus Imbalance — Mild, Moderate, and Extreme; tergantung pada proporsi kelas minoritas terhadap seluruh dataset. Pada contoh data churn di atas, tergolong kasus Mild Imbalance.
Lalu, mengapa kita perlu memperhatikan data yang imbalance saat membuat model machine learning? Kelas imbalance menghasilkan bias di mana model machine learning cenderung memprediksi kelas mayoritas. Anda tidak ingin model mengabaikan kelas minoritas bukan?
Itulah mengapa ada teknik untuk mengatasi masalah Imbalance, yaitu: Undersampling dan Oversampling. Apa perbedaan antara kedua teknik ini?
Undersampling akan mengurangi proporsi kelas mayoritas hingga jumlahnya mirip dengan kelas minoritas. Sedangkan, Oversampling akan mengulang sampel proporsi kelas minoritas sesuai dengan proporsi kelas mayoritas.
Dalam artikel ini, saya hanya akan menulis tentang teknik Oversampling yang disebut SMOTE dan berbagai variasinya.
Sebagai catatan, saya adalah seorang Data Scientist yang lebih suka untuk membiarkan proporsi data apa adanya, karena itu merepresentasikan data. Lebih baik mencoba feature engineering sebelum beralih ke teknik-teknik ini.
SMOTE
Apa itu SMOTE? SMOTE atau Synthetic Minority Oversampling Technique adalah teknik oversampling, tetapi SMOTE bekerja secara berbeda dari oversampling pada umumnya.
Pada teknik oversampling klasik, data minoritas diduplikasi dari populasi data minoritas. Teknik ini meningkatkan jumlah data, tetapi tidak memberikan informasi atau variasi baru pada model machine learning.
Oleh karena itu, Nitesh Chawla, dkk. (2002) memperkenalkan teknik baru untuk membuat data sintetis untuk tujuan oversampling dalam paper SMOTE mereka.
SMOTE bekerja dengan memanfaatkan algoritma k-nearest neighbor untuk membuat data sintetis. Pertama-tama SMOTE memilih data acak dari kelas minoritas, kemudian menetapkan k-nearest neighbors dari data tersebut. Data sintetis kemudian dibuat di antara data acak dan tetangga terdekat yang dipilih secara acak. Perhatikan contohnya di bawah ini.
Prosedur ini diulang beberapa kali hingga kelas minoritas memiliki proporsi yang sama dengan kelas mayoritas.
Saya tidak memberikan penjelasan yang lebih mendalam karena bagian di atas sudah merangkum bagaimana SMOTE bekerja. Dalam artikel ini, saya ingin fokus pada SMOTE dan variasinya, serta kapan menggunakannya tanpa terlalu banyak membahas teori. Jika Anda ingin tahu lebih banyak, saya akan melampirkan tautan ke paper untuk setiap variasi yang saya sebutkan di sini.
Sebagai persiapan, saya akan menggunakan imblearn package, yang mencakup SMOTE dan variasinya dalam paket tersebut.
#Installing imblearn
pip install -U imbalanced-learn
1. SMOTE
Kita akan mulai dengan menggunakan SMOTE dalam bentuk default-nya. Kita akan menggunakan dataset churn yang sama seperti sebelumnya. Mari siapkan data terlebih dahulu untuk mencoba SMOTE.
Jika Anda menyadari penjelasan saya sebelumnya, SMOTE digunakan untuk mensintesis data di mana fitur-fiturnya bersifat kontinu dan permasalahnya bersifat klasifikasi. Karena itu, pada bagian ini kita hanya akan mencoba menggunakan dua fitur kontinu dengan target klasifikasi.
import pandas as pd
import seaborns as sns
#I read the csv churn data into variable called df. Here I would only use #two continuous features CreditScore and Age with the target Exited
df_example = df[['CreditScore', 'Age', 'Exited']]
sns.scatterplot(data = df, x ='CreditScore', y = 'Age', hue = 'Exited')
Seperti yang bisa kita lihat pada scatter plot di atas, terjadi percampuran kelas 0 dan 1 diantara fitur ‘CreditScore’ dan ‘Age’.
Mari mencoba untuk membuat data oversampled menggunakan teknik SMOTE.
#Importing SMOTE
from imblearn.over_sampling import SMOTE
#Oversampling the data
smote = SMOTE(random_state = 101)
X, y = smote.fit_resample(df[['CreditScore', 'Age']], df['Exited'])
#Creating a new Oversampling Data Frame
df_oversampler = pd.DataFrame(X, columns = ['CreditScore', 'Age'])
df_oversampler['Exited']
sns.countplot(df_oversampler['Exited'])
Seperti yang terlihat pada grafik di atas, kelas 0 dan 1 sekarang memiliki proporsi yang serupa. Mari lihat bagaimana hasilnya jika kita membuat scatter plot yang sama seperti sebelumnya.
sns.scatterplot(data = df_oversampler, x ='CreditScore', y = 'Age', hue = 'Exited')
Saat ini, kita memiliki data oversampled untuk mengisi area yang sebelumnya kosong dengan data sintetis.
Tujuan oversampling adalah untuk memiliki model prediksi yang lebih baik. Teknik ini tidak dibuat untuk tujuan analisis apa pun karena setiap data yang dibuat bersifat sintetis, jadikan ini sebagai pengingat.
Oleh karena itu, kita perlu mengevaluasi apakah oversampling data mengarah pada model yang lebih baik atau tidak. Mari mulai dengan membagi data untuk membuat model prediksi.
# Importing the splitter, classification model, and the metric
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
#Splitting the data with stratification
X_train, X_test, y_train, y_test = train_test_split(df_example[['CreditScore', 'Age']], df['Exited'], test_size = 0.2, stratify = df['Exited'], random_state = 101)
Sebagai tambahan, Anda hanya melakukan oversampling pada data training dan bukan seluruh data kecuali jika Anda akan menggunakan seluruh data sebagai data training. Jika Anda ingin membagi data, Anda harus membagi data terlebih dahulu sebelum melakukan oversampling data training.
#Create an oversampled training data
smote = SMOTE(random_state = 101)
X_oversample, y_oversample = smote.fit_resample(X_train, y_train)
Sekarang kita memiliki kedua data, yaitu data yang imbalance dan data yang telah di-oversample, mari coba membuat model klasifikasi menggunakan kedua data ini. Pertama, mari lihat performa model Logistic Regression yang dilatih dengan data yang imbalance.
#Training with imbalance data
classifier = LogisticRegression()
classifier.fit(X_train, y_train)
print(classification_report(y_test, classifier.predict(X_test)))
Seperti yang bisa kita lihat dari metrik-metrik di atas, model Logistic Regression yang dilatih dengan data yang imbalance cenderung memprediksi kelas 0 daripada kelas 1. Ada bias pada model kita.
Mari lihat bagaimana hasilnya dari model yang dilatih dengan data yang telah di-oversample.
#Training with oversampled data
classifier_o = LogisticRegression()
classifier_o.fit(X_oversample, y_oversample)
print(classification_report(y_test, classifier_o.predict(X_test)))
Pada kasus ini, model lebih baik dalam memprediksi kelas 1. Dalam hal ini, kita bisa mengatakan bahwa data yang telah di-oversample membantu model Logistic Regression untuk memprediksi kelas 1 dengan lebih baik.
Saya bisa mengatakan bahwa data yang telah di-oversample meningkatkan model Logistic Regression untuk tujuan prediksi, meskipun konteks ‘meningkatkan’ kembali ke penggunanya.
2. SMOTE-NC
Saya telah menyebutkan bahwa SMOTE hanya berfungsi untuk fitur kontinu. Jadi, bagaimana jika Anda memiliki fitur yang beragam (kategorikal dan kontinu)? Dalam hal ini, kita memiliki variasi SMOTE lain yang disebut SMOTE-NC (Nominal dan Continuous).
Mungkin Anda berpikir, cukup ubah data kategorikal menjadi numerik karena kita telah memiliki SMOTE untuk fitur numerik. Masalahnya adalah ketika kita melakukannya, kita akan mendapatkan data yang tidak masuk akal.
Sebagai contoh, pada data churn di atas, kita memiliki fitur kategorikal ‘IsActiveMember’ dengan data 0 atau 1. Jika kita mengoversample data ini dengan SMOTE, kita bisa berakhir dengan data oversampled seperti 0.67 atau 0.5, yang sama sekali tidak masuk akal.
Inilah mengapa kita perlu menggunakan SMOTE-NC ketika kita memiliki kasus data yang beragam. Premisnya sederhana, kita menunjukkan (menandai) fitur mana yang bersifat kategorikal, dan SMOTE akan men-sampling ulang data kategorikal daripada membuat data sintetis.
Mari mencoba menerapkan SMOTE-NC. Kali ini saya akan memilih fitur lain sebagai contoh (satu kategorikal, satu kontinu).
df_example = df[['CreditScore', 'IsActiveMember', 'Exited']]
Pada contoh diatas, ‘CreditScore’ adalah fitur kontinu, dan ‘IsActiveMember’ adalah fitur kategorikal. Lalu, mari membagi data seperti sebelumnya.
X_train, X_test, y_train, y_test = train_test_split(df_example[['CreditScore', 'IsActiveMember']],df['Exited'], test_size = 0.2,stratify = df['Exited'], random_state = 101)
Kemudian, mari membuat dua model klasifikasi yang berbeda lagi; satu dilatih dengan data yang imbalance dan satu dengan data yang di-oversample. Pertama, mari mencoba SMOTE-NC untuk meng-oversample data.
#Import the SMOTE-NC
from imblearn.over_sampling import SMOTENC
#Create the oversampler. For SMOTE-NC we need to pinpoint the column #position where is the categorical features are. In this case, #'IsActiveMember' is positioned in the second column we input [1] as the #parameter. If you have more than one categorical columns, just input all #the columns position
smotenc = SMOTENC([1],random_state = 101)
Data sudah siap, mari mencoba membuat classifiers.
#Classifier with imbalance data
classifier = LogisticRegression()
classifier.fit(X_train, y_train)
print(classification_report(y_test, classifier.predict(X_test)))
Dengan data yang imbalance, kita dapat melihat bahwa classifier lebih memihak kelas 0 dan mengabaikan kelas 1 sepenuhnya. Lalu, bagaimana jika kita melatihnya dengan data yang di-oversample oleh SMOTE-NC.
#Classifier with SMOTE-NC
classifier_o = LogisticRegression()
classifier_o.fit(X_oversample, y_oversample)
print(classification_report(y_test, classifier_o.predict(X_test)))
Seperti halnya dengan SMOTE, classifier dengan data yang di-oversample oleh SMOTE-NC memberikan perspektif baru pada model machine learning untuk memprediksi data yang imbalance. Ini mungkin bukan yang terbaik, tetapi lebih baik daripada data yang imbalance.
3. Borderline-SMOTE
Borderline-SMOTE adalah variasi dari SMOTE. Sesuai dengan namanya, ada sesuatu yang berhubungan dengan batas (border).
Jadi, tidak seperti SMOTE, di mana data sintetis dibuat secara acak antara dua data, Borderline-SMOTE hanya membuat data sintetis sepanjang batas keputusan (decision boundary) antara dua kelas.
Selain itu, ada dua jenis Borderline-SMOTE; Borderline-SMOTE1 dan Borderline-SMOTE2. Perbedaannya sederhana; Borderline-SMOTE1 juga meng-oversample kelas mayoritas di mana data mayoritas menyebabkan kesalahan klasifikasi di decision boundary, sementara Borderline-SMOTE2 hanya meng-oversample kelas minoritas.
Mari mencoba Borderline-SMOTE dengan data sebelumnya. Sekali lagi saya hanya menggunakan fitur-fitur numerik.
df_example = df[['CreditScore', 'Age', 'Exited']]
Gambar di atas menunjukkan perbedaan antara meng-oversample data dengan SMOTE dan Borderline-SMOTE1. Mungkin terlihat sedikit mirip, tetapi kita bisa melihat ada perbedaan di mana data sintetis dibuat.
Bagaimana dengan performa model machine learning? Mari kita coba. Pertama, seperti biasa, kita membagi data.
X_train, X_test, y_train, y_test = train_test_split(df_example[['CreditScore', 'Age']], df['Exited'], test_size = 0.2, stratify = df['Exited'], random_state = 101)
Lalu, kita membuat data yang di-oversample dengan menggunakan Borderline-SMOTE.
#By default, the BorderlineSMOTE would use the Borderline-SMOTE1
from imblearn.over_sampling import BorderlineSMOTE
bsmote = BorderlineSMOTE(random_state = 101, kind = 'borderline-1')
X_oversample_borderline, y_oversample_borderline = bsmote.fit_resample(X_train, y_train)
Terakhir, mari periksa performa machine learning dengan data yang di-oversample oleh Borderline-SMOTE.
classifier_border = LogisticRegression()
classifier_border.fit(X_oversample_borderline, y_oversample_borderline)
print(classification_report(y_test, classifier_border.predict(X_test)))
Performanya tidak terlalu berbeda dari model yang dilatih dengan data yang di-oversample oleh SMOTE. Ini berarti bahwa kita seharusnya fokus pada fitur daripada meng-oversample data.
Borderline-SMOTE baik digunakan ketika kita tahu bahwa kesalahan klasifikasi sering terjadi di dekat boundary decision. Jika tidak, kita bisa tetap menggunakan SMOTE biasa. Jika Anda ingin membaca lebih lanjut tentang Borderline-SMOTE, Anda bisa cek paper-nya di sini.
4. Borderline-SMOTE SVM
Variasi lain dari Borderline-SMOTE adalah Borderline-SMOTE SVM, atau kita bisa menyebutnya SVM-SMOTE.
Perbedaan utama antara SVM-SMOTE dan SMOTE lainnya adalah alih-alih menggunakan K-nearest neighbors untuk mengidentifikasi kesalahan klasifikasi di Borderline-SMOTE, teknik ini akan menggabungkan algoritma SVM.
Pada SVM-SMOTE, batas area diestimasi oleh support vectors setelah melatih klasifikasi SVM pada set data training yang asli. Data sintetis akan dibuat secara acak di sepanjang garis yang menghubungkan setiap support vectors kelas minoritas dengan sejumlah tetangga terdekatnya.
Apa yang istimewa dari Borderline-SMOTE SVM dibandingkan dengan Borderline-SMOTE adalah lebih banyak data yang disintesis di luar daerah tumpang tindih (overlap) kelas. Fokusnya lebih pada di mana data terpisah.
Sama seperti sebelumnya, mari mencoba menggunakan teknik ini dalam pembuatan model. Saya masih akan menggunakan data training yang sama dalam contoh Borderline-SMOTE.
from imblearn.over_sampling import SVMSMOTE
svmsmote = SVMSMOTE(random_state = 101)
X_oversample_svm, y_oversample_svm = svmsmote.fit_resample(X_train, y_train)
classifier_svm = LogisticRegression()
classifier_svm.fit(X_oversample_svm, y_oversample_svm)
print(classification_report(y_test, classifier_svm.predict(X_test)))
Performanya sekali lagi tidak terlalu berbeda, meskipun bisa saya katakan bahwa model kali ini sedikit lebih memihak kelas 0 daripada ketika kita menggunakan teknik lain tetapi tidak terlalu berbeda.
Sekali lagi, tergantung pada Anda, apa target model prediksi Anda dan bisnis yang terpengaruh olehnya. Jika Anda ingin membaca lebih lanjut tentang Borderline-SMOTE SVM, Anda bisa cek paper-nya di sini.
5. Adaptive Synthetic Sampling (ADASYN)
ADASYN adalah variasi lain dari SMOTE. ADASYN mengambil pendekatan yang lebih berbeda dibandingkan dengan Borderline-SMOTE. Sementara Borderline-SMOTE mencoba untuk mensintesis data dekat decision boundary data, ADASYN membuat data sintetis sesuai dengan kepadatan data (data density).
Pembuatan data sintetik akan berbanding terbalik dengan kepadatan kelas minoritas. Artinya, lebih banyak data sintetik yang dibuat di wilayah ruang fitur yang kepadatan minoritasnya rendah, serta lebih sedikit atau tidak ada sama sekali di wilayah yang kepadatannya tinggi.
Sederhananya, di area di mana kelas minoritas kurang padat, data sintetis dibuat lebih banyak. Sebaliknya, data sintetis tidak dibuat begitu banyak di area yang padat.
Mari kita lihat bagaimana performa model dengan menggunakan ADASYN. Saya masih akan menggunakan data pelatihan yang sama dalam contoh Borderline-SMOTE.
from imblearn.over_sampling import ADASYN
adasyn = ADASYN(random_state = 101)
X_oversample_ada, y_oversample_ada = adasyn.fit_resample(X_train, y_train)
classifier_ada = LogisticRegression()
classifier_ada.fit(X_oversample_ada, y_oversample_ada)
print(classification_report(y_test, classifier_ada.predict(X_test)))
Seperti yang dapat kita lihat dari performa model di atas, performanya sedikit lebih buruk daripada ketika kita menggunakan metode SMOTE lainnya.
Masalahnya mungkin terletak pada outlier. Seperti yang saya sebutkan sebelumnya, ADASYN akan fokus pada data yang kepadatannya rendah. Seringkali, data kepadatan rendah adalah outlier. Pendekatan ADASYN kemudian akan memberikan terlalu banyak perhatian pada area ini dari ruang fitur yang dapat menghasilkan kinerja model yang lebih buruk. Mungkin lebih baik untuk menghapus outlier sebelum menggunakan ADASYN.
Jika Anda ingin membaca lebih lanjut tentang ADASYN, Anda bisa cek paper-nya di sini.
Kesimpulan
Data imbalance menjadi masalah saat membuat model machine learning. Salah satu cara untuk mengatasi masalah ini adalah dengan meng-oversample data minoritas.
Daripada meng-oversample dengan menduplikasi data, kita dapat meng-oversample data dengan membuat data sintetis menggunakan teknik SMOTE. Ada beberapa variasi SMOTE, diantaranya:
SMOTE
SMOTE-NC
Borderline-SMOTE
SVM-SMOTE
ADASYN
Semoga Bermanfaat!
Comments