Imbalanced Dataset (dataset yang tidak seimbang) adalah suatu masalah dalam data science. Masalah ini terjadi karena ketidakseimbangan sering kali menyebabkan masalah pada performa model. Untuk mengurangi masalah ketidakseimbangan, kita dapat menggunakan metode oversampling. Oversampling adalah metode resampling data minoritas untuk menyeimbangkan data.
Ada banyak cara untuk melakukan oversampling, dan salah satunya adalah dengan menggunakan SMOTE. Mari kita jelajahi berbagai implementasi SMOTE untuk mempelajari lebih lanjut tentang teknik oversampling.
Variasi SMOTE
Sebelum kita melanjutkan lebih jauh, kita akan menggunakan dataset churn dari Kaggle untuk mewakili dataset yang tidak seimbang. Target dataset adalah variabel Exited dan kita akan melihat bagaimana SMOTE akan melakukan oversampling data berdasarkan target minoritas.
import pandas as pd
df = pd.read_csv('churn.csv')
df['Exited'].value_counts().plot(kind = 'bar', color = ['blue', 'red'])
Kita bisa melihat bahwa dataset churn kita menghadapi masalah ketidakseimbangan. Mari coba SMOTE untuk melakukan oversampling data.
1. SMOTE
SMOTE biasanya digunakan untuk oversampling data kontinu pada masalah ML dengan membuat data buatan atau data sintetis. Kita menggunakan data kontinu karena model untuk mengembangkan sampel hanya menerima data kontinu.
Pada contoh kita, kita akan menggunakan dua variabel kontinu dari contoh dataset; EstimatedSalary dan Age. Mari kita lihat bagaimana kedua variabel ini tersebar dibandingkan dengan target data.
import seaborn as sns
sns.scatterplot(data =df, x ='EstimatedSalary', y = 'Age', hue = 'Exited')
Kita bisa melihat kelas minoritas kebanyakan tersebar di bagian tengah plot. Mari coba oversample data dengan SMOTE dan lihat perbedaannya. Untuk memfasilitasi oversampling SMOTE, kita akan menggunakan paket Python imblearn.
pip install imblearn
Dengan imblearn, kita akan melakukan oversample data churn.
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state = 42)
X, y = smote.fit_resample(df[['EstimatedSalary', 'Age']], df['Exited'])
df_smote = pd.DataFrame(X, columns = ['EstimatedSalary', 'Age'])
df_smote['Exited'] = y
Paket imblearn berbasis pada API scikit-learn, yang mudah digunakan. Pada contoh di atas, kita telah melakukan oversample dataset dengan SMOTE. Mari kita lihat distribusi variabel Exited.
df_smote['Exited'].value_counts().plot(kind = 'bar', color = ['blue', 'red'])
Seperti yang kita lihat pada output di atas, variabel target sekarang memiliki proporsi yang serupa. Mari kita lihat bagaimana variabel kontinu tersebar dengan data oversample SMOTE baru.
import matplotlib.pyplot as plt
sns.scatterplot(data = df_smote, x ='EstimatedSalary', y = 'Age', hue = 'Exited')
plt.title('SMOTE')
Gambar di atas menunjukkan saat ini data minoritas tersebar lebih banyak daripada sebelum kita melakukan oversample data. Jika kita melihat output lebih detail, kita bisa melihat bahwa persebaran data minoritas masih dekat dengan inti dan telah menyebar lebih luas dari sebelumnya.
Hal ini terjadi karena sampel didasarkan pada model tetangga, yang memperkirakan sampel berdasarkan tetangga terdekat.
2. SMOTE-NC
SMOTE-NC adalah SMOTE untuk data kategorikal. Seperti yang saya sebutkan di atas, SMOTE hanya bekerja untuk data kontinu.
Mengapa kita tidak langsung melakukan mengkodekan variabel kategorikal menjadi variabel kontinu?
Masalahnya adalah SMOTE membuat sampel berdasarkan tetangga terdekat. Jika Anda mengkodekan data kategorikal, misalnya variabel HasCrCard yang berisi kelas 0 dan 1, hasil sampelnya bisa menjadi 0.8 atau 0.34, dan sebagainya.
Dari sudut pandang data, ini tidak masuk akal. Itulah mengapa kita bisa menggunakan SMOTE-NC untuk memastikan bahwa oversampling data kategorikal masuk akal.
Mari kita coba dengan contoh data. Pada sampel khusus ini, kita akan menggunakan variabel HasCrCard dan Age. Pertama, saya ingin menunjukkan persebaran awal variabel HasCrCard.
pd.crosstab(df['HasCrCard'], df['Exited'])
Kemudian mari kita lihat perbedaannya setelah proses oversampling dengan SMOTE-NC.
from imblearn.over_sampling import SMOTENC
smotenc = SMOTENC([1],random_state = 42)
X_os_nc, y_os_nc = smotenc.fit_resample(df[['Age', 'HasCrCard']], df['Exited'])
Perhatikan kode di atas, posisi variabel kategorikal didasarkan pada posisi variabel dalam DataFrame.
Mari kita lihat bagaimana persebaran HasCrCard setelah oversampling.
pd.crosstab(X_os_nc['HasCrCard'], y_os_nc)
Lihat bahwa data oversampling hampir memiliki proporsi yang sama. Anda bisa mencoba dengan variabel kategorikal lain untuk melihat bagaimana SMOTE-NC bekerja.
3. Borderline-SMOTE
Borderline-SMOTE adalah SMOTE yang didasarkan pada garis batas (borderline) classifier. Borderline-SMOTE akan melakukan oversample data yang dekat dengan garis batas classifier. Hal ini karena semakin dekat sampel dari garis batas, semakin rentan terhadap kesalahan klasifikasi dan oleh karena itu lebih penting untuk dioversample.
Ada dua jenis Borderline-SMOTE; Borderline-SMOTE1 dan Borderline-SMOTE2. Perbedaannya adalah Borderline-SMOTE1 akan melakukan oversample kedua kelas yang dekat dengan garis batas. Sedangkan Borderline-SMOTE2 hanya akan melakukan oversample kelas minoritas.
Mari kita coba Borderline-SMOTE dengan contoh dataset.
from imblearn.over_sampling import BorderlineSMOTE
bsmote = BorderlineSMOTE(random_state = 42, kind = 'borderline-1')
X_bd, y_bd = bsmote.fit_resample(df[['EstimatedSalary', 'Age']], df['Exited'])
df_bd = pd.DataFrame(X_bd, columns = ['EstimatedSalary', 'Age'])
df_bd['Exited'] = y_bd
Mari kita lihat bagaimana persebarannya setelah kita melakukan Borderline-SMOTE.
sns.scatterplot(data = df_bd, x ='EstimatedSalary', y = 'Age', hue = 'Exited')
plt.title('Borderline-SMOTE')
Jika kita melihat hasil di atas, outputnya mirip dengan output SMOTE, tetapi hasil oversampling Borderline-SMOTE sedikit lebih dekat dengan garis batas.
4. SMOTE-Tomek
SMOTE-Tomek menggunakan kombinasi SMOTE dan undersampling link Tomek. Link Tomek adalah cara membersihkan data dengan menghapus kelas mayoritas yang tumpang tindih dengan kelas minoritas.
Mari kita coba SMOTE-Tomek dengan contoh dataset.
from imblearn.combine import SMOTETomek
s_tomek = SMOTETomek(random_state = 42)
X_st, y_st = s_tomek.fit_resample(df[['EstimatedSalary', 'Age']], df['Exited'])
df_st = pd.DataFrame(X_st, columns = ['EstimatedSalary', 'Age'])
df_st['Exited'] = y_st
Mari kita lihat hasil variabel target setelah kita menggunakan SMOTE-Tomek.
df_st['Exited'].value_counts().plot(kind = 'bar', color = ['blue', 'red'])
Jumlah kelas 0 dari variabel Exited sekarang sekitar 6000 dibandingkan dengan dataset asli yang mendekati 8000. Hal ini terjadi karena SMOTE-Tomek melakukan undersample pada kelas 0 sambil melakukan oversample pada kelas minoritas.
Mari kita lihat bagaimana persebaran data setelah kita melakukan oversample data dengan SMOTE-Tomek.
sns.scatterplot(data = df_st, x ='EstimatedSalary', y = 'Age', hue = 'Exited')
plt.title('SMOTE-Tomek')
Hasil persebarannya masih mirip dengan sebelumnya. Namun jika kita melihat lebih detail, semakin jauh data yang dihasilkan, semakin sedikit minoritas oversampled yang dihasilkan.
5. SMOTE-ENN
Mirip dengan SMOTE-Tomek, SMOTE-ENN (Edited Nearest Neighbour) menggabungkan oversampling dan undersampling. SMOTE melakukan oversampling, sedangkan ENN melakukan undersampling.
Edited Nearest Neighbour adalah cara untuk menghapus sampel kelas mayoritas dalam dataset asli dan hasil sampel di mana kelas minoritas terdekat salah mengklasifikasikannya. Ini akan menghapus kelas mayoritas yang dekat dengan perbatasan di mana ia salah diklasifikasikan.
Mari kita coba SMOTE-ENN dengan contoh dataset.
from imblearn.combine import SMOTEENN
s_enn = SMOTEENN(random_state=42)
X_se, y_se = s_enn.fit_resample(df[['EstimatedSalary', 'Age']], df['Exited'])
df_se = pd.DataFrame(X_se, columns = ['EstimatedSalary', 'Age'])
df_se['Exited'] = y_se
Mari kita lihat hasil SMOTE-ENN. Pertama, kita akan melihat variabel target.
df_se['Exited'].value_counts().plot(kind = 'bar', color = ['blue', 'red'])
Proses undersampling SMOTE-ENN jauh lebih ketat dibandingkan dengan SMOTE-Tomek. Dari hasil di atas, lebih dari setengah kelas 0 dari variabel Exited asli telah diundersample, dan hanya sedikit peningkatan pada kelas minoritas.
Mari kita lihat persebaran data setelah SMOTE-ENN diterapkan.
Persebaran datanya jauh lebih besar di antara kelas daripada sebelumnya. Namun, kita perlu ingat bahwa data hasilnya lebih kecil.
6. SMOTE-CUT
SMOTE-CUT atau SMOTE-Clustered Undersampling Technique menggabungkan oversampling, clustering, dan undersampling.
SMOTE-CUT mengimplementasikan oversampling dengan SMOTE, mengelompokkan data asli maupun data hasil dan menghapus sampel kelas mayoritas dari cluster.
Clustering SMOTE-CUT didasarkan pada algoritma EM atau Expectation Maximization, yang akan menetapkan setiap data dengan probabilitas menjadi milik cluster. Hasil clustering akan membimbing algoritma untuk melakukan oversample atau undersample, sehingga distribusi dataset menjadi seimbang.
Mari kita coba menggunakan contoh dataset. Pada contoh ini, kita akan menggunakan paket Python crucio.
pip install crucio
Dengan paket crucio, kita melakukan oversample dataset menggunakan kode berikut.
from crucio import SCUT
df_sample = df[['EstimatedSalary', 'Age', 'Exited']].copy()
scut = SCUT()
df_scut= scut.balance(df_sample, 'Exited')
Mari kita lihat distribusi data target.
df_scut['Exited'].value_counts().plot(kind = 'bar', color = ['blue', 'red'])
Kelas Exited menjadi seimbang, meskipun proses undersampling cukup ketat. Banyak dari kelas 0 dari variabel Exited dihapus karena undersampling.
Mari kita lihat persebaran data setelah SMOTE-CUT diterapkan.
sns.scatterplot(data = df_scut, x ='EstimatedSalary', y = 'Age', hue = 'Exited')
plt.title('SMOTE-CUT')
Persebaran datanya lebih tersebar tetapi kurang dari SMOTE-ENN.
7. ADASYN
ADASYN atau Adaptive Synthetic Sampling adalah SMOTE yang mencoba melakukan oversample data minoritas berdasarkan kepadatan data. ADASYN akan menetapkan distribusi berbobot untuk setiap sampel minoritas dan memprioritaskan oversample pada sampel minoritas yang lebih sulit dipelajari.
Mari kita coba ADASYN dengan contoh dataset.
from crucio import ADASYN
df_sample = df[['EstimatedSalary', 'Age', 'Exited']].copy()
ada = ADASYN()
df_ada= ada.balance(df_sample, 'Exited')
Mari kita lihat hasil distribusi target.
df_ada['Exited'].value_counts().plot(kind = 'bar', color = ['blue', 'red'])
Karena ADASYN akan fokus pada data yang lebih sulit dipelajari atau kurang padat, hasil oversampling lebih sedikit dibandingkan yang lain.
Mari kita lihat bagaimana persebaran datanya.
sns.scatterplot(data = df_ada, x ='EstimatedSalary', y = 'Age', hue = 'Exited')
plt.title('ADASYN')
Seperti yang kita lihat pada gambar di atas, persebarannya lebih dekat dengan inti tetapi lebih dekat ke data minoritas dengan kepadatan rendah.
Kesimpulan
Imbalanced Data atau ketidakseimbangan data adalah suatu masalah dalam bidang data. Salah satu cara untuk mengatasi masalah ketidakseimbangan adalah dengan melakukan oversample dataset dengan SMOTE. Seiring dengan perkembangan penelitian, banyak metode SMOTE telah dibuat yang bisa kita gunakan.
Dalam artikel ini, kita membahas 7 teknik SMOTE yang berbeda, termasuk:
SMOTE
SMOTE-NC
Borderline-SMOTE
SMOTE-Tomek
SMOTE-ENN
SMOTE-CUT
ADASYN
Comments