รองรับ Vector Machine (SVM)

ข้อมูลเบื้องต้นเกี่ยวกับ SVM

Support vector Machines (SVM) เป็นอัลกอริธึมการเรียนรู้ของเครื่องที่มีประสิทธิภาพ แต่มีความยืดหยุ่นซึ่งใช้สำหรับการจำแนกประเภทและการถดถอย แต่โดยทั่วไปมักใช้ในปัญหาการจำแนกประเภท ในปี 1960 SVM ถูกนำมาใช้ครั้งแรก แต่ต่อมาได้รับการปรับปรุงในปี 1990 SVM มีวิธีการนำไปใช้งานที่ไม่เหมือนใครเมื่อเทียบกับอัลกอริทึมการเรียนรู้ของเครื่องอื่น ๆ เมื่อเร็ว ๆ นี้พวกเขาได้รับความนิยมอย่างมากเนื่องจากความสามารถในการจัดการกับตัวแปรต่อเนื่องและหมวดหมู่หลายตัว

การทำงานของ SVM

โมเดล SVM นั้นเป็นตัวแทนของคลาสต่างๆในไฮเปอร์เพลนในพื้นที่หลายมิติ ไฮเปอร์เพลนจะถูกสร้างขึ้นในลักษณะซ้ำ ๆ โดย SVM เพื่อให้ข้อผิดพลาดลดลง เป้าหมายของ SVM คือการแบ่งชุดข้อมูลออกเป็นคลาสเพื่อค้นหาไฮเปอร์เพลนระยะขอบสูงสุด (MMH)

ต่อไปนี้เป็นแนวคิดที่สำคัญใน SVM -

  • Support Vectors- ดาต้าพอยต์ที่อยู่ใกล้กับไฮเปอร์เพลนมากที่สุดเรียกว่าเวกเตอร์สนับสนุน เส้นคั่นจะถูกกำหนดด้วยความช่วยเหลือของจุดข้อมูลเหล่านี้

  • Hyperplane - ดังที่เราเห็นในแผนภาพด้านบนมันคือระนาบการตัดสินใจหรือช่องว่างซึ่งแบ่งระหว่างชุดของวัตถุที่มีคลาสต่างกัน

  • Margin- อาจกำหนดให้เป็นช่องว่างระหว่างสองบรรทัดบนจุดข้อมูลตู้เสื้อผ้าของคลาสต่างๆ สามารถคำนวณเป็นระยะตั้งฉากจากเส้นถึงเวกเตอร์แนวรับ มาร์จิ้นขนาดใหญ่ถือเป็นมาร์จินที่ดีและมาร์จิ้นขนาดเล็กถือเป็นมาร์จินที่ไม่ดี

เป้าหมายหลักของ SVM คือการแบ่งชุดข้อมูลออกเป็นคลาสเพื่อค้นหาไฮเปอร์เพลนระยะขอบสูงสุด (MMH) และสามารถทำได้ในสองขั้นตอนต่อไปนี้ -

  • ขั้นแรก SVM จะสร้างไฮเปอร์เพลนซ้ำ ๆ ซึ่งจะแยกคลาสออกจากกันด้วยวิธีที่ดีที่สุด

  • จากนั้นจะเลือกไฮเปอร์เพลนที่แยกชั้นเรียนอย่างถูกต้อง

การนำ SVM ไปใช้ใน Python

สำหรับการนำ SVM ไปใช้ใน Python เราจะเริ่มต้นด้วยการนำเข้าไลบรารีมาตรฐานดังนี้ -

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns; sns.set()

ต่อไปเรากำลังสร้างชุดข้อมูลตัวอย่างโดยมีข้อมูลที่แยกออกได้เชิงเส้นจาก sklearn.dataset.sample_generator สำหรับการจำแนกโดยใช้ SVM -

from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=100, centers=2, random_state=0, cluster_std=0.50)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer');

ต่อไปนี้จะเป็นผลลัพธ์หลังจากสร้างชุดข้อมูลตัวอย่างที่มี 100 ตัวอย่างและ 2 คลัสเตอร์ -

เราทราบดีว่า SVM สนับสนุนการจำแนกแบบพินิจพิเคราะห์ มันแบ่งชั้นเรียนออกจากกันโดยเพียงแค่ค้นหาเส้นในกรณีที่มีสองมิติหรือหลายมิติในกรณีที่มีหลายมิติ มีการนำไปใช้กับชุดข้อมูลข้างต้นดังนี้ -

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
plt.plot([0.6], [2.1], 'x', color='black', markeredgewidth=4, markersize=12)
for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
   plt.plot(xfit, m * xfit + b, '-k')
plt.xlim(-1, 3.5);

ผลลัพธ์มีดังนี้ -

เราสามารถเห็นได้จากผลลัพธ์ด้านบนว่ามีตัวคั่นสามแบบที่แยกตัวอย่างข้างต้นได้อย่างสมบูรณ์แบบ

ดังที่ได้กล่าวไปแล้วเป้าหมายหลักของ SVM คือการแบ่งชุดข้อมูลออกเป็นคลาสเพื่อค้นหาไฮเปอร์เพลนระยะขอบสูงสุด (MMH) ดังนั้นแทนที่จะลากเส้นศูนย์ระหว่างคลาสเราสามารถลากเส้นรอบ ๆ แต่ละบรรทัดโดยเว้นระยะความกว้างไปยังจุดที่ใกล้ที่สุด สามารถทำได้ดังนี้ -

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
   for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
   yfit = m * xfit + b
   plt.plot(xfit, yfit, '-k')
   plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none',
         color='#AAAAAA', alpha=0.4)
plt.xlim(-1, 3.5);

จากภาพด้านบนในเอาต์พุตเราสามารถสังเกต "ระยะขอบ" ภายในตัวจำแนกแบบแยกแยะได้ SVM จะเลือกบรรทัดที่เพิ่มระยะขอบสูงสุด

ต่อไปเราจะใช้ตัวจำแนกเวกเตอร์สนับสนุนของ Scikit-Learn เพื่อฝึกโมเดล SVM กับข้อมูลนี้ ที่นี่เรากำลังใช้เคอร์เนลเชิงเส้นเพื่อให้พอดีกับ SVM ดังนี้ -

from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)

ผลลัพธ์มีดังนี้ -

SVC(C=10000000000.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
kernel='linear', max_iter=-1, probability=False, random_state=None,
shrinking=True, tol=0.001, verbose=False)

ตอนนี้เพื่อความเข้าใจที่ดีขึ้นต่อไปนี้จะพล็อตฟังก์ชันการตัดสินใจสำหรับ 2D SVC -

def decision_function(model, ax=None, plot_support=True):
   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)

ต่อไปเราต้องวางแผนขอบเขตการตัดสินใจและระยะขอบดังนี้ -

ax.contour(X, Y, P, colors='k',
   levels=[-1, 0, 1], alpha=0.5,
   linestyles=['--', '-', '--'])

ตอนนี้พล็อตเวกเตอร์สนับสนุนในทำนองเดียวกันดังนี้ -

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.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
decision_function(model);

เราสามารถสังเกตได้จากเอาต์พุตด้านบนว่าตัวจำแนก SVM พอดีกับข้อมูลที่มีระยะขอบเช่นเส้นประและเวกเตอร์รองรับองค์ประกอบสำคัญของความพอดีนี้สัมผัสกับเส้นประ จุดเวกเตอร์สนับสนุนเหล่านี้ถูกเก็บไว้ในแอตทริบิวต์ support_vectors_ ของลักษณนามดังนี้ -

model.support_vectors_

ผลลัพธ์มีดังนี้ -

array([[0.5323772 , 3.31338909],
   [2.11114739, 3.57660449],
   [1.46870582, 1.86947425]])

เมล็ด SVM

ในทางปฏิบัติอัลกอริทึม SVM ถูกนำไปใช้กับเคอร์เนลที่เปลี่ยนพื้นที่ข้อมูลอินพุตให้อยู่ในรูปแบบที่ต้องการ SVM ใช้เทคนิคที่เรียกว่าเคล็ดลับเคอร์เนลซึ่งเคอร์เนลใช้พื้นที่อินพุตมิติต่ำและแปลงเป็นพื้นที่มิติที่สูงขึ้น กล่าวง่ายๆว่าเคอร์เนลจะแปลงปัญหาที่ไม่สามารถแยกออกเป็นปัญหาที่แยกออกจากกันได้โดยการเพิ่มมิติข้อมูลเข้าไป ทำให้ SVM มีประสิทธิภาพยืดหยุ่นและแม่นยำยิ่งขึ้น ต่อไปนี้เป็นประเภทของเมล็ดพืชที่ SVM ใช้ -

เคอร์เนลเชิงเส้น

สามารถใช้เป็นผลิตภัณฑ์จุดระหว่างข้อสังเกตสองข้อใด ๆ สูตรของเคอร์เนลเชิงเส้นมีดังนี้ -

k (x, x i ) = ผลรวม (x * x i )

จากสูตรข้างต้นเราจะเห็นว่าผลคูณระหว่างเวกเตอร์สองตัวบอกว่า & คือผลรวมของการคูณของค่าอินพุตแต่ละคู่

เคอร์เนลพหุนาม

เป็นรูปแบบทั่วไปของเคอร์เนลเชิงเส้นและแยกความแตกต่างของพื้นที่อินพุตแบบโค้งหรือไม่เชิงเส้น ต่อไปนี้เป็นสูตรสำหรับเคอร์เนลพหุนาม -

K (x, xi) = 1 + ผลรวม (x * xi) ^ d

นี่ d คือระดับของพหุนามซึ่งเราจำเป็นต้องระบุด้วยตนเองในอัลกอริทึมการเรียนรู้

ฟังก์ชัน Radial Basis (RBF)

เคอร์เนล RBF ส่วนใหญ่ใช้ในการจำแนก SVM แม็พพื้นที่ป้อนข้อมูลในพื้นที่มิติไม่ จำกัด สูตรต่อไปนี้อธิบายทางคณิตศาสตร์ -

K (x, xi) = exp (-gamma * sum ((x - xi ^ 2))

ที่นี่แกมมามีค่าตั้งแต่ 0 ถึง 1 เราจำเป็นต้องระบุด้วยตนเองในอัลกอริทึมการเรียนรู้ ค่าเริ่มต้นที่ดีของแกมมาคือ 0.1

ในขณะที่เราใช้ SVM สำหรับข้อมูลที่แยกกันได้เชิงเส้นเราสามารถนำไปใช้ใน Python สำหรับข้อมูลที่ไม่สามารถแยกออกจากกันเชิงเส้นได้ สามารถทำได้โดยใช้เมล็ด

ตัวอย่าง

ต่อไปนี้เป็นตัวอย่างสำหรับการสร้างตัวแยกประเภท SVM โดยใช้เคอร์เนล เราจะใช้ชุดข้อมูลไอริสจาก scikit-learn -

เราจะเริ่มต้นด้วยการนำเข้าแพ็คเกจต่อไปนี้ -

import pandas as pd
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt

ตอนนี้เราต้องโหลดข้อมูลอินพุต -

iris = datasets.load_iris()

จากชุดข้อมูลนี้เราใช้คุณสมบัติสองประการแรกดังนี้ -

X = iris.data[:, :2]
y = iris.target

ต่อไปเราจะพล็อตขอบเขต SVM ด้วยข้อมูลดั้งเดิมดังนี้ -

x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
   np.arange(y_min, y_max, h))
X_plot = np.c_[xx.ravel(), yy.ravel()]

ตอนนี้เราจำเป็นต้องระบุค่าของพารามิเตอร์การทำให้เป็นมาตรฐานดังนี้ -

C = 1.0

ถัดไปสามารถสร้างวัตถุลักษณนาม SVM ได้ดังนี้ -

Svc_classifier = svm.SVC (เคอร์เนล = 'เชิงเส้น', C = C) .fit (X, y)

Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with linear kernel')

เอาต์พุต

Text(0.5, 1.0, 'Support Vector Classifier with linear kernel')

สำหรับการสร้างลักษณนาม SVM ด้วย rbf เคอร์เนลเราสามารถเปลี่ยนเคอร์เนลเป็น rbf ดังต่อไปนี้ -

Svc_classifier = svm.SVC(kernel='rbf', gamma =‘auto’,C=C).fit(X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with rbf kernel')

เอาต์พุต

Text(0.5, 1.0, 'Support Vector Classifier with rbf kernel')

เราใส่ค่าของแกมมาเป็น 'อัตโนมัติ' แต่คุณสามารถระบุค่าระหว่าง 0 ถึง 1 ได้เช่นกัน

ข้อดีข้อเสียของ SVM Classifiers

ข้อดีของตัวแยกประเภท SVM

ตัวแยกประเภท SVM มีความแม่นยำสูงและทำงานได้ดีกับพื้นที่มิติสูง ตัวแยกประเภท SVM โดยทั่วไปจะใช้จุดฝึกอบรมย่อยดังนั้นจึงใช้หน่วยความจำน้อยลงมาก

จุดด้อยของตัวแยกประเภท SVM

พวกเขามีเวลาฝึกอบรมสูงดังนั้นในทางปฏิบัติจึงไม่เหมาะกับชุดข้อมูลขนาดใหญ่ ข้อเสียอีกประการหนึ่งคือตัวแยกประเภท SVM ทำงานได้ไม่ดีกับคลาสที่ทับซ้อนกัน