Kesadaran SVM

Kernel dan situasi ketika SVM cocok dipakai.

Daftar isi

Support Vector Machine, yang lazim disingkat SVM, adalah classifier yang mencari pemisah antarkelas dengan margin terlebar, yaitu jarak sejauh mungkin dari pemisah ke sampel terdekat setiap kelas. Model ini kuat pada dataset menengah dengan dimensi tinggi, tetapi biaya pelatihannya tumbuh cepat seiring bertambahnya jumlah sampel, sehingga kesadaran akan batas kemampuannya menjadi bagian dari materi ini. Topik membahas konsep margin dan support vector, peran kernel dalam pemisahan nonlinier, parameter gamma dan C, serta kewajiban standardisasi fitur. Seluruh contoh dijalankan pada dataset iris dan make_moons bawaan scikit-learn.

Margin maksimal dan support vector#

SVC, kelas SVM untuk klasifikasi pada scikit-learn, mencari hyperplane, yaitu bidang datar pemisah dua kelas, dengan margin terlebar. Hyperplane dinyatakan oleh persamaan w⊤x+b=0 w^\top x + b = 0 , sedangkan marginnya adalah jarak ke sampel terdekat dari masing-masing kelas, yang besarnya sebanding dengan 1/∥w∥ 1 / \|w\| . Memaksimalkan margin berarti memperkecil ∥w∥ \|w\| , dan pemisah yang lebih lebar dianggap lebih tahan terhadap variasi data baru. Untuk masalah dengan lebih dari dua kelas, scikit-learn memecahnya menjadi beberapa masalah dua kelas secara bawaan, dengan strategi satu lawan satu.

Sampel yang letaknya tepat di tepi margin inilah yang disebut support vector, yaitu vektor penyangga yang menentukan posisi pemisah. Sampel yang berada jauh di dalam wilayah kelasnya tidak mengubah solusi sama sekali, karena gesernya tidak menyentuh margin. Konsekuensinya, prediksi model hanya bergantung pada subset kecil dari data latih, dan menghapus sampel yang jauh dari batas tidak menghasilkan model yang berbeda. Sifat ini berbeda dengan regresi logistik yang seluruh sampelnya ikut menarik garis keputusan.

Kernel memperluas ke pemisahan nonlinier#

Garis lurus tidak selalu mampu memisahkan kelas, dan dataset make_moons yang berbentuk dua bulan sabit menjadi contoh klasiknya. SVM mengatasi keadaan ini melalui kernel, yaitu fungsi yang menghitung kemiripan dua sampel seolah keduanya berada di ruang berdimensi lebih tinggi tanpa benar-benar membangun ruang tersebut. Kernel linear menghasilkan pemisah lurus, sedangkan kernel rbf (radial basis function) menghasilkan pemisah melengkung yang mengikuti bentuk kelas. Perbedaannya terukur langsung pada data berikut.

python Contoh: kernel linear dan rbf pada data make_moons
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

X, y = make_moons(n_samples=400, noise=0.25, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, stratify=y, random_state=42
)

for kernel in ["linear", "rbf"]:
    model = make_pipeline(StandardScaler(), SVC(kernel=kernel))
    model.fit(X_train, y_train)
    print(f"kernel={kernel:>6}: test={model.score(X_test, y_test):.3f}")
text Keluaran
kernel=linear: test=0.920
kernel=   rbf: test=0.950

Kernel rbf mencapai 0.950, lebih tinggi daripada linear yang berhenti di 0.920, karena dua bulan sabit memang tidak dapat dipisahkan oleh satu garis lurus. Ketika bentuk kelasnya memang sederhana, misalnya pada data yang hampir terpisah oleh garis, kernel linear justru sering unggul dan lebih cepat dilatih. Pemilihan kernel adalah keputusan tentang bentuk batas keputusan, dan rbf menjadi pilihan bawaan yang aman untuk data tabular karena kemampuannya menyesuaikan lengkung secara otomatis. Kernel lain seperti poly juga tersedia, sedangkan dua pilihan di atas mencakup kebutuhan yang paling umum.

gamma dan C sebagai dua kendala kompleksitas#

Dua parameter mengendalikan seberapa jauh model boleh menyesuaikan data. Parameter gamma menentukan jangkauan pengaruh satu sampel pada kernel rbf, yaitu gamma besar membuat pengaruhnya pendek sehingga batas keputusan berkelok mengikuti sampel, sedangkan gamma kecil membuatnya panjang dan batas keputusan menjadi halus. Parameter C menentukan toleransi terhadap pelanggaran margin, yaitu C besar menuntut pemisahan yang ketat, sedangkan C kecil membiarkan sebagian sampel melanggar demi margin yang lebih lebar. Keduanya sama-sama menaikkan kompleksitas ketika diperbesar.

python Contoh: pengaruh gamma terhadap akurasi train dan test
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

X, y = make_moons(n_samples=400, noise=0.25, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, stratify=y, random_state=42
)

for gamma in [0.1, 1.0, 10.0, 100.0]:
    model = make_pipeline(StandardScaler(), SVC(kernel="rbf", gamma=gamma))
    model.fit(X_train, y_train)
    print(f"gamma={gamma:>5}: train={model.score(X_train, y_train):.3f}, "
          f"test={model.score(X_test, y_test):.3f}")
text Keluaran
gamma=  0.1: train=0.820, test=0.950
gamma=  1.0: train=0.937, test=0.930
gamma= 10.0: train=0.960, test=0.900
gamma=100.0: train=0.990, test=0.900
python Contoh: pengaruh C terhadap akurasi train dan test
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.25, stratify=iris.target, random_state=42
)

for c in [0.1, 1.0, 10.0, 100.0]:
    model = make_pipeline(StandardScaler(), SVC(kernel="rbf", C=c))
    model.fit(X_train, y_train)
    print(f"C={c:>6}: train={model.score(X_train, y_train):.3f}, "
          f"test={model.score(X_test, y_test):.3f}")
text Keluaran
C=   0.1: train=0.902, test=0.868
C=   1.0: train=0.964, test=0.947
C=  10.0: train=0.973, test=0.974
C= 100.0: train=0.991, test=0.947

Kedua pengukuran memperlihatkan pola yang sama, yaitu akurasi train naik saat parameter diperbesar, sedangkan akurasi test naik dahulu kemudian turun. Pada pengukuran gamma, nilai 0.1 yang paling halus mencapai test 0.950, sedangkan nilai 10 dan 100 yang berkelok mengikuti data latih hanya mencapai 0.900. Pada pengukuran C, nilai 0.1 terlalu longgar sehingga train dan test sama-sama rendah, sedangkan nilai 10 memberikan test tertinggi di 0.974 sebelum turun kembali pada 100. Nilai bawaan gamma="scale" dan C=1.0 merupakan titik awal yang layak, dan penyetelan keduanya dilakukan melalui pencarian grid yang diulas pada modul cross-validation.

Standardisasi sebelum SVC#

SVM mengukur jarak dan kedekatan antarsampel, sehingga fitur berskala besar mendominasi perhitungannya. Standardisasi bukan sekadar anjuran pada SVC, melainkan syarat kerja yang benar, dan StandardScaler dipasang di dalam pipeline agar statistiknya dipelajari hanya dari data latih. Dengan cara ini, tidak ada informasi dari data uji yang ikut menentukan transformasinya. Program berikut mengukur selisihnya pada dataset iris.

python svm-scaling.py
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.25, stratify=iris.target, random_state=42
)

# kondisi pertama: SVC pada fitur mentah tanpa scaling
svm_tanpa = SVC(kernel="rbf")
svm_tanpa.fit(X_train, y_train)
akurasi_tanpa = svm_tanpa.score(X_test, y_test)

# kondisi kedua: StandardScaler di dalam pipeline, fit hanya pada data latih
svm_dengan = make_pipeline(StandardScaler(), SVC(kernel="rbf"))
svm_dengan.fit(X_train, y_train)
akurasi_dengan = svm_dengan.score(X_test, y_test)

print(f"SVC rbf tanpa StandardScaler : {akurasi_tanpa:.3f}")
print(f"SVC rbf dengan StandardScaler: {akurasi_dengan:.3f}")
print(f"Selisih                      : {akurasi_dengan - akurasi_tanpa:.3f}")
text Keluaran
SVC rbf tanpa StandardScaler : 0.921
SVC rbf dengan StandardScaler: 0.947
Selisih                      : 0.026

Standardisasi menaikkan akurasi dari 0.921 menjadi 0.947 tanpa perubahan pada kernel, parameter, atau pemecahan data. Nilai bawaan gamma="scale" dihitung dari varians setiap fitur, sehingga fitur berskala besar seperti panjang kelopak menenggelamkan fitur yang lain sebelum penyetaraan dilakukan. Selisih 0.026 pada data yang hanya berukuran 38 sampel uji berarti sekitar satu prediksi yang berpindah menjadi benar, dan pada data nyata yang lebih besar selisih semacam ini berdampak lebih jauh. Pola ini konsisten dengan temuan topik Mengapa Scaling Diperlukan, yang memuat pengukuran serupa pada KNN.

Kapan SVM cocok dan kapan tidak#

SVC bekerja baik pada dataset berukuran menengah dengan jumlah fitur yang besar, misalnya data teks yang setiap sampelnya diwakili ribuan dimensi. Margin maksimalnya membuat model ini stabil pada kondisi fitur banyak dan sampel tidak terlalu banyak, dan kernelnya menyediakan nonlinearitas tanpa rekayasa fitur manual. Kondisi tersebut menjadikan SVM pilihan yang wajar ketika decision tree dan ensemble belum dicoba, atau ketika jumlah sampelnya berada pada ribuan. Data breast_cancer dengan 569 sampel dan 30 fitur berada tepat pada wilayah yang nyaman bagi model ini.

Sebaliknya, waktu pelatihan SVC tumbuh setidaknya kuadratik terhadap jumlah sampel, sehingga praktisnya melampaui batas yang masuk akal pada data puluhan ribu baris ke atas. Model ini juga menolak masukan yang memuat nilai NaN, memerlukan waktu lebih lama untuk menghitung probabilitas karena evaluasi silang internal, dan tetap menuntut standardisasi pada setiap penggunaannya. Apabila data sudah memasuki ratusan ribu baris, HistGradientBoostingClassifier pada modul Gradient Boosting menjadi alternatif yang lebih cepat dengan hasil yang sebanding.

Kesalahan umum#

Kesalahan pertama adalah menjalankan SVC pada fitur mentah. Skornya turun secara diam-diam karena jarak dan gamma dihitung dari skala yang timpang, sebagaimana terukur selisih 0.921 berbanding 0.947 pada iris di atas. StandardScaler di dalam pipeline menjadi aturan bawaan yang tidak pernah dilepaskan.

Kesalahan kedua adalah menaikkan gamma dan C bersamaan tanpa pengukuran. Keduanya menaikkan kompleksitas pada jalur yang berbeda, sehingga efek keduanya saling menutupi dan penyebab overfitting menjadi sulit dilacak. Pemisahan pengukuran satu parameter pada satu waktu menjaga diagnosis tetap jelas.

Kesalahan ketiga adalah menganggap SVC cocok untuk semua ukuran data. Kompleksitas pelatihannya yang kuadratik ke atas membuat waktu pelatihan naik tajam pada data besar, dan kegagalannya bukan berupa error yang jelas, melainkan waktu tunggu yang memanjang tanpa kepastian selesai. Estimasi waktu pada sampel kecil sebelum pelatihan penuh mencegah keadaan itu terjadi di tengah pekerjaan.

Ringkasan#

  • SVC mencari hyperplane dengan margin terlebar, dan posisinya ditentukan oleh support vector, yaitu sampel yang letaknya di tepi margin.
  • Kernel rbf memungkinkan pemisahan nonlinier dan mengungguli kernel linear sebesar 0.950 berbanding 0.920 pada make_moons.
  • Parameter gamma dan C mengendalikan kompleksitas, dan nilai yang terlalu besar menurunkan akurasi data uji meskipun akurasi train naik terus.
  • Standardisasi fitur adalah syarat kerja SVC, dan SVM paling cocok untuk dataset menengah dengan dimensi tinggi, bukan untuk data puluhan ribu baris ke atas.

Referensi#