📅  最后修改于: 2020-09-27 09:12:32             🧑  作者: Mango
支持向量机(SVM)是最流行的监督学习算法之一,可用于分类以及回归问题。但是,首先,它用于机器学习中的分类问题。
SVM算法的目标是创建可以将n维空间划分为类的最佳直线或决策边界,以便我们将来可以轻松地将新数据点放在正确的类别中。最佳决策边界称为超平面。
SVM选择有助于创建超平面的极限点/向量。这些极端情况称为支持向量,因此算法称为支持向量机。考虑下图,其中使用决策边界或超平面将两个不同的类别分类:
示例:可以通过我们在KNN分类器中使用的示例来理解SVM。假设我们看到一只奇怪的猫,它也具有狗的某些特征,因此如果我们想要一个可以准确识别它是猫还是狗的模型,那么可以使用SVM算法来创建这样的模型。我们将首先用大量的猫和狗的图像训练模型,以便它可以了解猫和狗的不同特征,然后我们用这个奇怪的生物对其进行测试。因此,当支持向量在这两个数据(猫和狗)之间创建决策边界并选择极端情况(支持向量)时,它将看到猫和狗的极端情况。根据支持向量,它将分类为猫。考虑下图:
SVM算法可用于人脸检测,图像分类,文本分类等。
SVM可以有两种类型:
超平面:可以有多条线/决策边界来分离n维空间中的类,但是我们需要找出有助于对数据点进行分类的最佳决策边界。最佳边界称为SVM的超平面。
超平面的尺寸取决于数据集中存在的特征,这意味着如果有2个特征(如图所示),则超平面将是一条直线。并且如果有3个要素,则超平面将是2维平面。
我们总是创建一个具有最大余量的超平面,这意味着数据点之间的最大距离。
支持向量:
最接近超平面并影响超平面位置的数据点或向量称为支持向量。由于这些向量支持超平面,因此称为支持向量。
线性SVM:
通过示例可以了解SVM算法的工作原理。假设我们有一个具有两个标签(绿色和蓝色)的数据集,并且该数据集具有两个特征x1和x2。我们想要一个可以将坐标对(x1,x2)分类为绿色或蓝色的分类器。考虑下图:
由于它是二维空间,因此只需使用一条直线,我们就可以轻松地将这两个类分开。但是可以有多行可以将这些类分开。考虑下图:
因此,SVM算法有助于找到最佳的直线或决策边界。最好的边界或区域称为超平面。 SVM算法从两个类中找到线的最接近点。这些点称为支持向量。向量与超平面之间的距离称为余量。 SVM的目标是最大化此余量。具有最大余量的超平面称为最佳超平面。
非线性SVM:
如果数据是线性排列的,那么我们可以使用一条直线将其分开,但是对于非线性数据,我们无法绘制一条直线。考虑下图:
因此,要分离这些数据点,我们需要再增加一个维度。对于线性数据,我们使用了两个维度x和y,因此对于非线性数据,我们将添加第三个维度z。可以计算为:
通过添加第三维,样本空间将变为下图所示:
因此,现在,SVM将以以下方式将数据集划分为类。考虑下图:
由于我们处于3维空间,因此它看起来像是一个平行于x轴的平面。如果我们在z = 1的二维空间中对其进行转换,则它将变为:
因此,在非线性数据的情况下,我们得到半径为1的圆周。
支持向量机的Python实现
现在,我们将使用Python实现SVM算法。在这里,我们将使用在Logistic回归和KNN分类中使用的相同数据集user_data。
在数据预处理步骤之前,代码将保持不变。下面是代码:
#Data Pre-processing Step
# importing libraries
import numpy as nm
import matplotlib.pyplot as mtp
import pandas as pd
#importing datasets
data_set= pd.read_csv('user_data.csv')
#Extracting Independent and dependent Variable
x= data_set.iloc[:, [2,3]].values
y= data_set.iloc[:, 4].values
# Splitting the dataset into training and test set.
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test= train_test_split(x, y, test_size= 0.25, random_state=0)
#feature Scaling
from sklearn.preprocessing import StandardScaler
st_x= StandardScaler()
x_train= st_x.fit_transform(x_train)
x_test= st_x.transform(x_test)
执行完上述代码后,我们将对数据进行预处理。该代码将给数据集如下:
测试集的缩放输出将是:
使SVM分类器适合训练集:
现在,训练集将适合SVM分类器。要创建SVM分类器,我们将从Sklearn.svm库中导入SVC类。下面是它的代码:
from sklearn.svm import SVC# "Support vector classifier"
classifier = SVC(kernel='linear', random_state=0)
classifier.fit(x_train, y_train)
在上面的代码中,我们使用了kernel =’linear’,因为在这里我们正在为线性可分离的数据创建SVM。但是,我们可以将其更改为非线性数据。然后我们将分类器拟合到训练数据集(x_train,y_train)
输出:
Out[8]:
SVC(C=1.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=0,
shrinking=True, tol=0.001, verbose=False)
可以通过更改C(正则化因子),γ和内核的值来更改模型性能。
#Predicting the test set result
y_pred= classifier.predict(x_test)
得到y_pred向量后,我们可以比较y_pred和y_test的结果,以检查实际值和预测值之间的差异。
输出:以下是测试集预测的输出:
#Creating the Confusion matrix
from sklearn.metrics import confusion_matrix
cm= confusion_matrix(y_test, y_pred)
输出:
从上面的输出图像中可以看到,有66 + 24 = 90个正确的预测,而8 + 2 = 10个正确的预测。因此,可以说,与Logistic回归模型相比,我们的SVM模型得到了改进。
from matplotlib.colors import ListedColormap
x_set, y_set = x_train, y_train
x1, x2 = nm.meshgrid(nm.arange(start = x_set[:, 0].min() - 1, stop = x_set[:, 0].max() + 1, step =0.01),
nm.arange(start = x_set[:, 1].min() - 1, stop = x_set[:, 1].max() + 1, step = 0.01))
mtp.contourf(x1, x2, classifier.predict(nm.array([x1.ravel(), x2.ravel()]).T).reshape(x1.shape),
alpha = 0.75, cmap = ListedColormap(('red', 'green')))
mtp.xlim(x1.min(), x1.max())
mtp.ylim(x2.min(), x2.max())
for i, j in enumerate(nm.unique(y_set)):
mtp.scatter(x_set[y_set == j, 0], x_set[y_set == j, 1],
c = ListedColormap(('red', 'green'))(i), label = j)
mtp.title('SVM classifier (Training set)')
mtp.xlabel('Age')
mtp.ylabel('Estimated Salary')
mtp.legend()
mtp.show()
输出:
通过执行以上代码,我们将获得以下输出:
如我们所见,以上输出看起来与Logistic回归输出类似。在输出中,由于在分类器中使用了线性核,因此我们将直线作为超平面。上面我们还讨论了,对于2d空间,SVM中的超平面是一条直线。
#Visulaizing the test set result
from matplotlib.colors import ListedColormap
x_set, y_set = x_test, y_test
x1, x2 = nm.meshgrid(nm.arange(start = x_set[:, 0].min() - 1, stop = x_set[:, 0].max() + 1, step =0.01),
nm.arange(start = x_set[:, 1].min() - 1, stop = x_set[:, 1].max() + 1, step = 0.01))
mtp.contourf(x1, x2, classifier.predict(nm.array([x1.ravel(), x2.ravel()]).T).reshape(x1.shape),
alpha = 0.75, cmap = ListedColormap(('red','green' )))
mtp.xlim(x1.min(), x1.max())
mtp.ylim(x2.min(), x2.max())
for i, j in enumerate(nm.unique(y_set)):
mtp.scatter(x_set[y_set == j, 0], x_set[y_set == j, 1],
c = ListedColormap(('red', 'green'))(i), label = j)
mtp.title('SVM classifier (Test set)')
mtp.xlabel('Age')
mtp.ylabel('Estimated Salary')
mtp.legend()
mtp.show()
输出:
通过执行以上代码,我们将获得以下输出:
如上图所示,SVM分类器已将用户分为两个区域(已购买或未购买)。购买SUV的用户位于带有红色散点的红色区域。未购买SUV的用户位于绿色分散点的绿色区域。超平面将这两个类别分为“已购买”和“未购买”变量。