Máy vectơ hỗ trợ (SVM)
Giới thiệu về SVM
Máy vectơ hỗ trợ (SVM) là các thuật toán học máy được giám sát mạnh mẽ nhưng linh hoạt được sử dụng cho cả phân loại và hồi quy. Nhưng nhìn chung, chúng được sử dụng trong các bài toán phân loại. Năm 1960, SVM lần đầu tiên được giới thiệu nhưng sau đó chúng được cải tiến vào năm 1990. SVM có cách triển khai độc đáo so với các thuật toán học máy khác. Gần đây, chúng cực kỳ phổ biến vì khả năng xử lý nhiều biến liên tục và phân loại.
Hoạt động của SVM
Mô hình SVM về cơ bản là sự biểu diễn của các lớp khác nhau trong một siêu phẳng trong không gian đa chiều. Siêu phẳng sẽ được SVM tạo theo cách lặp đi lặp lại để có thể giảm thiểu lỗi. Mục tiêu của SVM là chia bộ dữ liệu thành các lớp để tìm siêu phẳng biên tối đa (MMH).
Sau đây là các khái niệm quan trọng trong SVM:
Support Vectors- Các điểm dữ liệu gần siêu phẳng nhất được gọi là vectơ hỗ trợ. Đường phân cách sẽ được xác định với sự trợ giúp của các điểm dữ liệu này.
Hyperplane - Như chúng ta thấy trong sơ đồ trên, nó là một mặt phẳng quyết định hoặc không gian được phân chia giữa một tập các đối tượng có các lớp khác nhau.
Margin- Nó có thể được định nghĩa là khoảng cách giữa hai dòng trên các điểm dữ liệu tủ quần áo của các lớp khác nhau. Nó có thể được tính bằng khoảng cách vuông góc từ đường thẳng đến các vectơ hỗ trợ. Ký quỹ lớn được coi là ký quỹ tốt và ký quỹ nhỏ được coi là ký quỹ xấu.
Mục tiêu chính của SVM là chia bộ dữ liệu thành các lớp để tìm siêu phẳng biên tối đa (MMH) và nó có thể được thực hiện theo hai bước sau:
Đầu tiên, SVM sẽ tạo lặp đi lặp lại các siêu máy bay để phân tách các lớp theo cách tốt nhất.
Sau đó, nó sẽ chọn siêu phẳng phân tách các lớp một cách chính xác.
Triển khai SVM bằng Python
Để triển khai SVM bằng Python, chúng ta sẽ bắt đầu với việc nhập các thư viện tiêu chuẩn như sau:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns; sns.set()
Tiếp theo, chúng tôi đang tạo một tập dữ liệu mẫu, có dữ liệu có thể phân tách tuyến tính, từ sklearn.dataset.sample_generator để phân loại bằng 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');
Sau đây là kết quả đầu ra sau khi tạo tập dữ liệu mẫu có 100 mẫu và 2 cụm -
Chúng tôi biết rằng SVM hỗ trợ phân loại phân biệt. nó phân chia các lớp với nhau bằng cách đơn giản tìm một đoạn thẳng trong trường hợp hai chiều hoặc đa tạp trong trường hợp nhiều chiều. Nó được thực hiện trên tập dữ liệu trên như sau:
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);
Kết quả như sau:
Chúng ta có thể thấy từ kết quả trên rằng có ba dải phân cách khác nhau phân biệt hoàn hảo các mẫu trên.
Như đã thảo luận, mục tiêu chính của SVM là chia bộ dữ liệu thành các lớp để tìm ra siêu phẳng biên tối đa (MMH), do đó thay vì vẽ một đường 0 giữa các lớp, chúng ta có thể vẽ xung quanh mỗi dòng một lề có độ rộng cho đến điểm gần nhất. Nó có thể được thực hiện như sau:
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);
Từ hình ảnh trên trong đầu ra, chúng ta có thể dễ dàng quan sát “lề” trong các bộ phân loại phân biệt. SVM sẽ chọn dòng tối đa hóa lợi nhuận.
Tiếp theo, chúng tôi sẽ sử dụng bộ phân loại vector hỗ trợ của Scikit-Learn để đào tạo mô hình SVM trên dữ liệu này. Ở đây, chúng tôi đang sử dụng hạt nhân tuyến tính để phù hợp với SVM như sau:
from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)
Kết quả như sau:
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)
Bây giờ, để hiểu rõ hơn, phần sau sẽ vẽ sơ đồ các hàm quyết định cho 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()
Để đánh giá mô hình, chúng ta cần tạo lưới như sau:
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)
Tiếp theo, chúng ta cần vẽ các ranh giới và biên quyết định như sau:
ax.contour(X, Y, P, colors='k',
levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
Bây giờ, vẽ biểu đồ tương tự các vectơ hỗ trợ như sau:
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)
Bây giờ, sử dụng chức năng này để phù hợp với các mô hình của chúng tôi như sau:
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
decision_function(model);
Chúng ta có thể quan sát từ kết quả đầu ra ở trên rằng bộ phân loại SVM phù hợp với dữ liệu có lề tức là các đường đứt nét và các vectơ hỗ trợ, các phần tử quan trọng của sự phù hợp này, chạm vào đường đứt nét. Các điểm vectơ hỗ trợ này được lưu trữ trong thuộc tính support_vectors_ của trình phân loại như sau:
model.support_vectors_
Kết quả như sau:
array([[0.5323772 , 3.31338909],
[2.11114739, 3.57660449],
[1.46870582, 1.86947425]])
Nhân SVM
Trong thực tế, thuật toán SVM được thực hiện với hạt nhân để biến đổi không gian dữ liệu đầu vào thành dạng yêu cầu. SVM sử dụng một kỹ thuật gọi là kernel trick, trong đó kernel lấy một không gian đầu vào có chiều thấp và biến nó thành một không gian có chiều cao hơn. Nói một cách đơn giản, kernel chuyển đổi các vấn đề không thể phân tách thành các vấn đề có thể tách biệt bằng cách thêm nhiều chiều vào nó. Nó làm cho SVM mạnh mẽ, linh hoạt và chính xác hơn. Sau đây là một số loại hạt nhân được SVM sử dụng:
Kernel tuyến tính
Nó có thể được sử dụng như một sản phẩm chấm giữa hai lần quan sát bất kỳ. Công thức của hạt nhân tuyến tính như sau:
k (x, x i ) = sum (x * x i )
Từ công thức trên, chúng ta có thể thấy rằng tích giữa hai vectơ nói & là tổng của phép nhân của mỗi cặp giá trị đầu vào.
Nhân đa thức
Nó là dạng tổng quát hơn của nhân tuyến tính và phân biệt không gian đầu vào cong hoặc phi tuyến. Sau đây là công thức cho nhân đa thức:
K (x, xi) = 1 + sum (x * xi) ^ d
Ở đây d là bậc của đa thức mà chúng ta cần chỉ định thủ công trong thuật toán học.
Hạt nhân hàm cơ sở hướng tâm (RBF)
Nhân RBF, chủ yếu được sử dụng trong phân loại SVM, ánh xạ không gian đầu vào trong không gian chiều không xác định. Công thức sau giải thích nó về mặt toán học:
K (x, xi) = exp (-gamma * sum ((x - xi ^ 2))
Ở đây, gamma nằm trong khoảng từ 0 đến 1. Chúng ta cần chỉ định thủ công nó trong thuật toán học tập. Giá trị mặc định tốt của gamma là 0,1.
Khi chúng tôi triển khai SVM cho dữ liệu có thể phân tách tuyến tính, chúng tôi có thể triển khai nó bằng Python cho dữ liệu không thể phân tách tuyến tính. Nó có thể được thực hiện bằng cách sử dụng hạt nhân.
Thí dụ
Sau đây là một ví dụ để tạo bộ phân loại SVM bằng cách sử dụng hạt nhân. Chúng tôi sẽ sử dụng tập dữ liệu mống mắt từ scikit-learning -
Chúng tôi sẽ bắt đầu bằng cách nhập các gói sau:
import pandas as pd
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt
Bây giờ, chúng ta cần tải dữ liệu đầu vào -
iris = datasets.load_iris()
Từ tập dữ liệu này, chúng tôi sẽ sử dụng hai tính năng đầu tiên như sau:
X = iris.data[:, :2]
y = iris.target
Tiếp theo, chúng tôi sẽ vẽ ranh giới SVM với dữ liệu gốc như sau:
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()]
Bây giờ, chúng ta cần cung cấp giá trị của tham số chính quy như sau:
C = 1.0
Tiếp theo, đối tượng phân loại SVM có thể được tạo như sau:
Svc_classifier = svm.SVC (kernel = 'linear', 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')
Đầu ra
Text(0.5, 1.0, 'Support Vector Classifier with linear kernel')
Để tạo bộ phân loại SVM với rbf kernel, chúng ta có thể thay đổi kernel thành rbf như sau -
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')
Đầu ra
Text(0.5, 1.0, 'Support Vector Classifier with rbf kernel')
Chúng tôi đặt giá trị của gamma thành 'auto' nhưng bạn cũng có thể cung cấp giá trị của nó từ 0 đến 1.
Ưu và nhược điểm của Bộ phân loại SVM
Ưu điểm của bộ phân loại SVM
Bộ phân loại SVM cung cấp độ chính xác cao và hoạt động tốt với không gian chiều cao. Các bộ phân loại SVM về cơ bản sử dụng một tập hợp con các điểm đào tạo do đó sử dụng rất ít bộ nhớ.
Nhược điểm của bộ phân loại SVM
Chúng có thời gian đào tạo cao do đó trong thực tế không phù hợp với các bộ dữ liệu lớn. Một nhược điểm khác là bộ phân loại SVM không hoạt động tốt với các lớp chồng chéo.