Machine Learning 简明教程

Machine Learning - Support Vector Machine

支持向量机 (SVM) 是功能强大但灵活的监督式机器学习算法,用于分类和回归。但通常它们用于分类问题。SVMs 最早于 20 世纪 60 年代推出,但后来在 1990 年得到改进。与其他机器学习算法相比,SVM 有其独特的实现方式。如今,它们因能够处理多个连续和分类变量而非常流行。

Working of SVM

SVM 的目标是找到一个将数据点分成不同类的超平面。超平面是二维空间中的线,三维空间中的平面或 n 维空间中的高维曲面。选择超平面的方式是使其最大化间隔,即超平面与每个类中最近数据点之间的距离。最近的数据点称为支持向量。

超平面和数据点“x”之间的距离可以使用以下公式计算:

distance = (w . x + b) / ||w||

其中“w”是权重向量,“b”是偏置项,“||w||”是权重向量的欧几里得范数。权重向量“w”垂直于超平面并决定了它的方向,而偏置项“b”决定了它的位置。

通过解决一个优化问题可以找到最佳超平面,即在所有数据点都正确分类的约束下最大化间隔。换句话说,我们想要找到一个在确保没有数据点被错误分类的情况下,使两类之间的间隔最大化的超平面。这是一个使用二次规划求解的凸优化问题。

如果数据点不可线性分离,我们可以使用称为核技巧的技术将数据点映射到它们变得可分离的高维空间中。核函数计算映射的数据点之间的内积,而无需计算映射本身。这让我们无需承担映射的计算成本,就可以使用高维空间中的数据点。

让我们借助以下图表详细了解它 −

working of svm

以下是 SVM 中重要概念 −

  1. Support Vectors - 最接近超平面的数据点称为支持向量。将利用这些数据点定义分隔线。

  2. Hyperplane - 如下图所示,这是一个决策平面或空间,界于一组具有不同类的对象之间。

  3. Margin - 它可以定义为不同类最近数据点上的两条线之间的间隙。它可以计算为从该线到支持向量的垂直距离。大间隔被认为是好间隔,小间隔被认为是坏间隔。

Implementation in Python

我们将使用 scikit-learn 库在 Python 中实现 SVM。Scikit-learn 是一个流行的机器学习库,它提供了广泛的用于分类、回归、聚类和降维任务的算法。

我们将使用著名的 Iris 数据集,其中包含三种鸢尾花:山鸢尾、杂色鸢尾和弗吉尼亚鸢尾的花萼长度、花萼宽度、花瓣长度和花瓣宽度。目标是根据这四个特征将这些花分类到各自的种类中。

Example

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# load the iris dataset
iris = load_iris()

# split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(iris.data,
iris.target, test_size=0.2, random_state=42)

# create an SVM classifier with a linear kernel
svm = SVC(kernel='linear')

# train the SVM classifier on the training set
svm.fit(X_train, y_train)

# make predictions on the testing set
y_pred = svm.predict(X_test)

# calculate the accuracy of the classifier
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

我们通过从 scikit-learn 导入必要的模块 load_iris 来加载鸢尾花数据集, train_test_split 将数据分割为训练集和测试集,SVC 使用线性核创建 SVM 分类器,以及 accuracy_score 计算分类器的准确率。

我们使用 load_iris 加载鸢尾花数据集,并使用 train_test_split 将数据分割为训练集和测试集。我们采用 0.2 的测试集大小,这意味着 20% 的数据将用于测试,80% 用于训练。我们将随机状态设置为 42,确保结果的可重复性。

我们使用 SVC(kernel='linear') 创建一个线性核的 SVM 分类器。然后使用 svm.fit(X_train, y_train) 在训练集上训练 SVM 分类器。

分类器训练好后,我们使用 svm.predict(X_test) 对测试集进行预测。然后,我们使用 accuracy_score(y_test, y_pred) 计算分类器的准确率并将其打印到控制台。

代码的输出应类似于以下内容 −

Accuracy: 1.0

Tuning SVM Parameters

实际上,SVM 通常需要对其参数进行微调才能实现最佳性能。最重要的微调参数是核函数、正则化参数 C 以及特定核函数的参数。

核函数参数决定要使用的核函数的类型。最常见的核函数类型包括线性、多项式、径向基函数 (RBF) 和 sigmoid。线性核函数用于线性可分数据,而其他核函数用于非线性可分数据。

正则化参数 C 控制最大化边界和最小化分类误差之间的折衷。较高的 C 值意味着分类器将以牺牲更小的边界为代价最小化分类误差,而较低的 C 值意味着分类器将尝试最大化边界,即使这意味着更多分类错误。

特定核函数的参数取决于正在使用的核函数类型。例如,多项式核函数有用于多项式次数和多项式系数的参数,而 RBF 核函数有用于高斯函数宽度的参数。

我们可以使用交叉验证来调整 SVM 的参数。交叉验证包括将数据分割成多个子集,并在每个子集上训练分类器,同时将其余子集用于测试。这允许我们在数据的不同子集上评估分类器的性能,并选择最佳的参数集。

Example

from sklearn.model_selection import GridSearchCV
# define the parameter grid
param_grid = {
   'C': [0.1, 1, 10, 100],
   'kernel': ['linear', 'poly', 'rbf', 'sigmoid'],
   'degree': [2, 3, 4],
   'coef0': [0.0, 0.1, 0.5],
   'gamma': ['scale', 'auto']
}

# create an SVM classifier
svm = SVC()

# perform grid search to find the best set of parameters
grid_search = GridSearchCV(svm, param_grid, cv=5)
grid_search.fit(X_train, y_train)
# print the best set of parameters and their accuracy
print("Best parameters:", grid_search.best_params_)
print("Best accuracy:", grid_search.best_score_)

我们通过从 scikit-learn 中导入 GridSearchCV 模块开始,该模块是用于对一组参数执行网格搜索的工具。我们定义了一个参数网格,其中包含我们想要微调的每个参数的可能值。

我们使用 SVC() 创建一个 SVM 分类器,然后将其传递给 GridSearchCV ,连同参数网格和交叉验证折数 (cv=5)。然后我们调用 grid_search.fit(X_train, y_train) 来执行网格搜索。

网格搜索完成后,我们使用 grid_search.best_params_grid_search.best_score_, 分别打印最佳参数集及其准确率。

执行此程序时,您将获得以下输出 −

Best parameters: {'C': 0.1, 'coef0': 0.5, 'degree': 3, 'gamma': 'scale', 'kernel': 'poly'}
Best accuracy: 0.975

这意味着网格搜索找到的最佳参数集是: C=0.1, coef0=0.5, degree=3, gamma=scale, and kernel=poly 。这组参数在训练集上实现的准确率为 97.5%。

您现在可以使用这些参数来创建一个新的 SVM 分类器,并在测试集上测试其性能。