Destek Vektör Makineleri (Support Vector Machine | SVM) Çalışma Mantığı ve Python Uygulaması

Yiğit Şener
7 min readJan 16, 2021

--

Destek vektör makineleri (support vector machine | SVM) makine öğrenmesinin haylaz algoritmalarından birisidir. Neden haylaz derseniz veriler arasındaki boşlulardan yararlanarak onları sınıflandırır ya da regresyonu yapabilir. Ancak genellikle sınıflandırma için kullanılır. Kümeleme (clustering) ya da sıra dışı verilerin tespiti (outlier detection) içinde uygulanabilir. En temelde SVM vektörler yardımı ile verileri birbirinden ayırt etmemizi sağlar. Hemen basit bir örnekle başlayalım.

# girdi veri seti
# 8 satır ve 2 sutündan oluşmakta
x = np.array([
[3, 2],
[2, 3],
[3, 3],
[4, 2],
[4, 5],
[5, 4],
[4, 4],
[5, 3]
])

# çıktı değişkeninin 8 değeri bulunmakta
y = np.array([-1, -1, -1, -1, 1, 1, 1, 1])

# göz ile bir plot çizelim
# çıktı değişkenleri girdi üzerinde gösteren plot
# eğer -1'e eşitse girdinin gösterimi "-" ile
# eğer 1'e eşitse girdinin gösterimi "+" olarak gösterilir.
for index, deger in enumerate(x):
if y[index] == -1:
plt.scatter(deger[0], deger[1]
,s=100, marker='_'
,linewidths=5)
else:
plt.scatter(deger[0], deger[1]
,s=100, marker='+'
,linewidths=5)

# varsayımsal SVM plot
plt.plot([1, 6],
[6, 1])

plt.show()

Yukarıdaki iki boyutlu basit gösterimde scatter ve line plot bir aradadır. Scatter gösterimde “-” ve “+” ile gösterilen değerler x girdi değişkenlerine ait. Çıktı değişken ile işaretlenmiş olan y veri setindeki -1'e karşılık “-”, 1'e karşılık ise “+” değerleri yer almaktadır. Burada -1 ve 1'i en doğru şekilde sınıflandırmak için SVM iki değişken kümesini ayıran bir vektör çizimi uygulamaktadır. Yukarıdaki line yani vektörü şimdilik kendi verdiğimiz değerlere göre atayarak algoritmanın çalışma mantığı göstermiş oluyoruz. Öyle bir noktadan bu vektör oluşturulmalı ki algoritmanın sınıfları ayırma gücü kuvvetli olabilsin. Bu vektörün SVM’deki karşılığı ise hiper düzlem (hyperplane) olarak geçmektedir.

SVM Terimleri ve Çalışma Mantığı

Yukarıdaki grafiğin daha şirin bir halini aşağıda gösterin terimleri ve işleyişi anlatalım.

İki ya da daha fazla etiketlenmiş sınıflı veri setlerinde (A ve B sınıfı) ayrımcı (discriminative) sınıflandırma SVM ile yaratılabilir. Ayrım için belirlenmesi gereken karar sınırı (decision boundary) sınıflar arasındaki en iyi boşluğu (margin) bularak çizgiyi (hyperplane | hiper düzlem) çeker. Karar sınırına en yakın noktalara veya değerlere destek (support) denir. Bunun “DESTEK” olarak adlandırılmasının sebebi ise en iyi yerden geçebilecek çizginin yaratılmasına destek olmalarından dolayıdır. Eğer bu noktaların konumu değişirse en iyi (maksimum) durum değişeceği için karar sınırları da değişecektir. Boşluğu en iyilemek (maksimize etmek) ve sınıflar arasına bir hiper düzlem yerleştirmek, yeni gelen değerlerin (noktaların) doğru sınıf kategorisine girme şansını büyük ölçüde artırabilir.

Uygulamamızı biraz daha genişleterek sentetik veri seti üzerinden SVM ile bir sınıflandırma yaparak grafikleştirelim. Öncelikle sentetik veri setini oluşturalım.

# sentetik veri seti
from sklearn.datasets import make_blobs

# iki merkesli 50 örnekli veri seti
x, y = make_blobs(n_samples=50, centers=2,
random_state=0, cluster_std=0.60)

Oluşturduğumuz sınıfları scatter plot üzerinden inceleyelim.

# veri setinin gösterimi
plt.scatter(x[:, 0], x[:, 1], c=y, s=50, cmap='Dark2')
plt.show()

Noktalar arasındaki ayrım gözle bile fark edilebilir bir durumda. Sklearn üzerinde SVM sınıflandırma algoritmasını veri seti üzerine uygulayalım. Doğrusal (linear) bir metodoloji kullanacağımızı SVC modeli içindeki kernel seçeneğine belitiyoruz.

# model oluşturma
model = SVC(kernel='linear', C=1E10)
model.fit(x, y)

# katsayılar
print(model.coef_)
# ÇIKTI
# array([[ 0.23525694, -1.41250783]])

Modelimizi oluşturduğumuza göre grafik üzerinde nasıl göründüğünü bir inceleyelim.

def svm_grafik_karar_fonksiyonu(model, ax=None, plot_support=True):
"""
:param model: çalışılan model değişkeni
:param ax: plot düzlemi
:param plot_support: destek vektör olacak mı?
:return: plot gösterimi
"""
if ax is None:
ax = plt.gca()

xlim = ax.get_xlim()
ylim = ax.get_ylim()


x = np.linspace(xlim[0], xlim[1], 30)
y = np.linspace(ylim[0], ylim[1], 30)
Y, X = np.meshgrid(y, x)
xy = np.vstack([X.ravel(), Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)

# karar sınırları ve boşluğun görseli
ax.contour(X, Y, P, colors='k',
levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])

# destek vektörlerinin plotu
if plot_support:
ax.scatter(model.support_vectors_[:, 0],
model.support_vectors_[:, 1],
s=300, linewidth=1, facecolors='none');
ax.set_xlim(xlim)
ax.set_ylim(ylim)
plt.show()

# girdi değişkenlerin scatter plot gösterimi
plt.scatter(x[:, 0], x[:, 1], c=y, s=50, cmap='autumn')

# grafiğin çalıştırılması
svm_grafik_karar_fonksiyonu(model)

Grafikte görüldüğü üzere model ile çizilen hiper düzlem olabildiğince karar sınırlarındaki en iyi noktaları bularak sınıfları birbirinden ayırmaya çalışmış.

Doğrusal Olmayan ve Ayrılmaz Düzlemlerde SVM

Bazı problemler doğrusal alt düzlem kullanılarak çözülemez.

Böyle bir durumda SVM, girdi uzayını daha yüksek boyutlu bir alana dönüştürmek için bir çekirdek numarası (kernel trick) kullanır. Veri noktaları, x ekseni ve z ekseni üzerinde çizilir (Z, hem x hem de y’nin karelerinin toplamıdır: z = x ^ 2 = y ^ 2). Böyle bir problem için örnek bir veri seti oluşturarak inceleyelim.

# İçe içe geçen daire şeklinde sentetik veri
from sklearn.datasets import make_circles

# 100 adet satır ve 2 merkezli veri
X, y = make_circles(100, factor=.1, noise=.1)

# scatter plot
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='Dark2')
plt.show()

Yukarıdaki grafikte görüldüğü üzere içe içe geçmiş dairesel bir veri seti ile karşı karşıyayız.

Peki böyle bir veri setine yukarıdaki yöntemi uygularsak ne ile karşılaşacağız? Yukarıda yazdığımız fonksiyonu kullanacağız fakat bazı parametreleri aşağıdaki şekilde değiştiriyoruz.

# modeli oluşturuyoruz
model_2 = SVC(kernel='linear').fit(x, y)

# girdi değişkenlerin scatter plot gösterimi
plt.scatter(x[:, 0], x[:, 1], c=y, s=50, cmap='Dark2')

# grafiğin çalıştırılması
# bu sefer destek plotu göstermiyoruz
svm_grafik_karar_fonksiyonu(model=model_2, plot_support=False)

Grafikte görüldüğü üzere algoritma hiper düzlemi istenildiği bir şekilde çizemedi.

Şimdi değişkenleri farklı bir boyuta döndürerek bir inceleyelim.

def plot_3D(x=x, y=y):
r = np.exp(-(x ** 2).sum(1))
ax = plt.subplot(projection='3d')
ax.scatter3D(x[:, 0], x[:, 1], r, c=y, s=50, cmap='Dark2')
ax.view_init(elev=30, azim=30)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('r')
plt.show()

plot_3D()

Grafikte görüldüğü üzere Z boyutunu işin içine dahil ettiğimizde girdi değişkenlerinin ayrıştığını görebiliyoruz. Böyle bir döndürme yöntemi sayesinde ayrıştırma işlemi SVM tarafından uygulanabilir olacaktır.

Scikit-Learn’de, çekirdek modeli hiper parametresini kullanarak, doğrusal çekirdeğimizi bir RBF (radyal temel fonksiyonu) çekirdeğine dönüştürerek, çekirdekleştirilmiş SVM uygulayabiliriz:

model_rbf = SVC(kernel='rbf', C=1E6)
model_rbf.fit(x, y)

Çekirdek yöntemini RBF olarak belirleyip modelimizi oluşturduk. Şimdide grafiksel açıdan bakalım. Aşağıdaki kodda yukarıda görselleştirmek için kullandığımız fonksiyon ve uyguladığımız model yer almaktadır.

plt.scatter(x[:, 0], x[:, 1], c=y, s=50, cmap='Dark2')
plt.scatter(model_rbf.support_vectors_[:, 0], model_rbf.support_vectors_[:, 1],
s=300, lw=1, facecolors='none')
svm_grafik_karar_fonksiyonu(model_rbf)

Görüldüğü üzere RBF yöntemi ile sınıflar birbirlerinden ayrışmış vaziyettedir. Tabi gerçek hayatta bu kadar güzel ayrışan bir veri seti ile karşılaşmak mümkün olmayabilir.

SVM Algoritmasında Kullanılan Önemli Parametreler

Sklearn içinde SVM kullanımında yer alan bazı önemli parametreleri açıklayalım. Öncelikle bunların hepsine aşağıdaki şekilde bakabiliriz. Daha fazla detay için buraya bakılabilir.

from sklearn.svm import SVC

# PARAMETRELER
print(SVC().get_params())
# ÇIKTI
# {'C': 1.0, 'break_ties': False, 'cache_size': 200
# ,'class_weight': None, 'coef0': 0.0
# ,'decision_function_shape': 'ovr', 'degree': 3
# ,'gamma': 'scale', 'kernel': 'rbf', 'max_iter': -1
# ,'probability': False, 'random_state': None
# ,'shrinking': True, 'tol': 0.001, 'verbose': False}
  • C: Düzenlileştirme (Regularization) parametresi. Düzenlemenin gücü C ile ters orantılıdır. Kesinlikle pozitif bir sayı olmalıdır. L2 (ridge regresyon) ile cezalandırma yöntemini uygulanır.
  • Kernel: Bu parametrenin aldığı değerler {‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’} olup yukarıda linear ve RBF yöntemlerini incelemiştir.
  • Degree: Eğer kernel yöntem olarak polinom (“poly”) kullanımı varsa bu parametre polinom derecesinin belirlenmesi içindir.
  • Gamma: Daha düşük bir Gamma değeri, eğitim veri kümesine seyrek olacak şekilde uyarken, daha yüksek bir gamma değeri ise eğitim veri kümesine tam olarak uymakta ve bu durum aşırı öğrenmeye (overfitting) neden olabilmektedir. Başka bir deyişle, düşük bir gamma değeri ayırma çizgisini hesaplarken yalnızca yakın noktaları dikkate alır. Diğer yandan yüksek bir gama değeri ayırma çizgisinin hesaplanmasında tüm veri noktalarını dikkate alır diyebilirsiniz.

SVM Avantajları ve Dezavantajları

SVM Sınıflandırıcıları, Naïve Bayes algoritmasına kıyasla iyi doğruluk sunar ve daha hızlı tahmin gerçekleştirir. Ayrıca, karar aşamasında bir alt eğitim noktası kümesi kullandıkları için daha az bellek kullanırlar. SVM, net bir ayırma marjı ve yüksek boyutsal boşlukla iyi çalışır.

Dezavantajı ise SVM, yüksek eğitim süresi nedeniyle büyük veri kümeleri için uygun değildir ve aynı zamanda Naïve Bayes’e kıyasla model eğitimi sırasında eğitimde daha fazla zaman harcar. Çakışan sınıflarla kötü çalışır ve ayrıca kullanılan çekirdek türüne duyarlıdır.

Sonuç

SVM algoritmaları özellikle ayırım gerektiren veri setleri için kullanılması tavsiye edilir. Sektörde yapılan bazı çalışmalarda fraud detection gibi konular üzerinde SVM uygulanabilmektedir. Dengesiz dağılan çıktı değişkenler üzerinde başarılı olduğu uygulamalar bulunmaktadır.

--

--