使用Scikit-learn支持向量机

本文概述

与其他分类器(例如逻辑回归和决策树)相比, SVM提供了非常高的准确性。以处理非线性输入空间的内核技巧而闻名。它用于各种应用程序, 例如面部检测, 入侵检测, 电子邮件, 新闻文章和网页的分类, 基因的分类以及手写识别。

在本教程中, 你将在Python中使用scikit-learn。如果你想了解有关此Python软件包的更多信息, 建议你看一下我们的scikit-learn监督学习课程。

SVM是一种令人兴奋的算法, 其概念相对简单。分类器使用具有最大余量的超平面分离数据点。这就是SVM分类器也被称为判别式分类器的原因。 SVM找到了一个最佳的超平面, 该平面有助于对新数据点进行分类。

在本教程中, 你将涵盖以下主题:

  • 支持向量机
  • 它是如何工作的?
  • 内核
  • Scikit-learn中的分类器构建
  • 调整超参数
  • 优点和缺点

支持向量机

通常, 支持向量机被认为是一种分类方法, 但可以同时用于分类和回归问题。它可以轻松处理多个连续和类别变量。 SVM在多维空间中构造一个超平面以分离不同的类。 SVM以迭代方式生成最佳超平面, 用于最小化误差。 SVM的核心思想是找到最大的边际超平面(MMH), 以最大程度地将数据集划分为类。

支持向量

支持向量

支持向量是最靠近超平面的数据点。这些点将通过计算边距更好地定义分隔线。这些要点与分类器的构建更相关。

超平面

超平面是一个决策平面, 它在具有不同类成员资格的一组对象之间进行分隔。

边距

边距是最接近的类点上的两条线之间的间隙。这是从线到支持向量或最接近点的垂直距离来计算的。如果两个类别之间的边距较大, 则认为是良好的边距, 较小的边距是较差的边距。

SVM如何工作?

主要目的是以最佳方式隔离给定的数据集。两个最近的点之间的距离称为边距。目的是在给定的数据集中选择在支持向量之间具有最大可能余量的超平面。 SVM通过以下步骤搜索最大边缘超平面:

  1. 生成以最佳方式隔离类的超平面。左侧图显示了三个超平面黑色, 蓝色和橙色。此处, 蓝色和橙色具有较高的分类误差, 但是黑色正确地将两个类别分隔开。
  2. 从右侧的两个数据点中选择一个具有最大隔离度的右侧超平面, 如右侧图所示。
线性分离器

处理非线性和不可分割的平面

线性超平面无法解决某些问题, 如下图(左侧)所示。

在这种情况下, SVM使用内核技巧将输入空间转换为较高维的空间, 如右图所示。数据点绘制在x轴和z轴上(Z是x和y的平方和:z = x ^ 2 = y ^ 2)。现在, 你可以使用线性分离轻松地分离这些点。

高维

SVM内核

SVM算法实际上是使用内核实现的。内核将输入数据空间转换为所需的形式。 SVM使用一种称为内核技巧的技术。在这里, 内核占用一个低维的输入空间, 并将其转换为一个高维的空间。换句话说, 你可以说它通过添加更多维度来将不可分离的问题转换为可分离的问题。它在非线性分离问题中最有用。内核技巧可帮助你构建更准确的分类器。

  • 线性核线性核可以用作任意两个给定观测值的正态点积。两个向量之间的乘积是每对输入值的乘积之和。
K(x, xi) = sum(x * xi)
  • 多项式内核多项式内核是线性内核的更广义形式。多项式核可以区分弯曲或非线性输入空间。
K(x, xi) = 1 + sum(x * xi)^d

d是多项式的次数。 d = 1与线性变换相似。该程度需要在学习算法中手动指定。

  • 径向基函数内核径向基函数内核是常用的支持向量机分类中常用的内核函数。 RBF可以将输入空间映射为无穷维。
K(x, xi) = exp(-gamma * sum((x – xi^2))

此处的gamma是一个参数, 范围从0到1。较高的gamma值将完全适合训练数据集, 这会导致过度拟合。 Gamma = 0.1被认为是一个很好的默认值。伽马值需要在学习算法中手动指定。

Scikit-learn中的分类器构建

到目前为止, 你已经了解了SVM的理论背景。现在, 你将使用scikit-learn了解其在Python中的实现。

在模型的构建部分中, 你可以使用癌症数据集, 这是一个非常著名的多类别分类问题。该数据集是根据乳腺肿块的细针抽吸(FNA)的数字化图像计算得出的。它们描述了图像中存在的细胞核的特征。

数据集包含30个特征(平均半径, 平均纹理, 平均周长, 平均面积, 平均平滑度, 平均紧实度, 平均凹度, 平均凹点, 平均对称性, 平均分形维数, 半径误差, 纹理误差, 周长误差, 面积误差, 平滑度误差, 紧密度误差, 凹度误差, 凹点误差, 对称性误差, 分形维数误差, 最差半径, 最差纹理, 最差周长, 最差区域, 最差平滑度, 最差紧实度, 最差凹度, 最坏凹点, 最差对称性和最差分形维数)和目标(癌症类型)。

此数据有两种类型的癌症:恶性(有害)和良性(无害)。在这里, 你可以建立模型来对癌症类型进行分类。数据集在scikit-learn库中可用, 或者你也可以从UCI机器学习库中下载。

加载数据中

首先, 加载所需的数据集。

#Import scikit-learn dataset library
from sklearn import datasets

#Load dataset
cancer = datasets.load_breast_cancer()

探索数据

加载数据集后, 你可能想了解更多有关它的信息。你可以检查功能和目标名称。

# print the names of the 13 features
print("Features: ", cancer.feature_names)

# print the label type of cancer('malignant' 'benign')
print("Labels: ", cancer.target_names)
Features:  ['mean radius' 'mean texture' 'mean perimeter' 'mean area'
 'mean smoothness' 'mean compactness' 'mean concavity'
 'mean concave points' 'mean symmetry' 'mean fractal dimension'
 'radius error' 'texture error' 'perimeter error' 'area error'
 'smoothness error' 'compactness error' 'concavity error'
 'concave points error' 'symmetry error' 'fractal dimension error'
 'worst radius' 'worst texture' 'worst perimeter' 'worst area'
 'worst smoothness' 'worst compactness' 'worst concavity'
 'worst concave points' 'worst symmetry' 'worst fractal dimension']
Labels:  ['malignant' 'benign']

让我们进一步探索它。你也可以使用shape检查数据集的形状。

# print data(feature)shape
cancer.data.shape
(569, 30)

让我们检查功能集的前5条记录。

# print the cancer data features (top 5 records)
print(cancer.data[0:5])
[[1.799e+01 1.038e+01 1.228e+02 1.001e+03 1.184e-01 2.776e-01 3.001e-01
  1.471e-01 2.419e-01 7.871e-02 1.095e+00 9.053e-01 8.589e+00 1.534e+02
  6.399e-03 4.904e-02 5.373e-02 1.587e-02 3.003e-02 6.193e-03 2.538e+01
  1.733e+01 1.846e+02 2.019e+03 1.622e-01 6.656e-01 7.119e-01 2.654e-01
  4.601e-01 1.189e-01]
 [2.057e+01 1.777e+01 1.329e+02 1.326e+03 8.474e-02 7.864e-02 8.690e-02
  7.017e-02 1.812e-01 5.667e-02 5.435e-01 7.339e-01 3.398e+00 7.408e+01
  5.225e-03 1.308e-02 1.860e-02 1.340e-02 1.389e-02 3.532e-03 2.499e+01
  2.341e+01 1.588e+02 1.956e+03 1.238e-01 1.866e-01 2.416e-01 1.860e-01
  2.750e-01 8.902e-02]
 [1.969e+01 2.125e+01 1.300e+02 1.203e+03 1.096e-01 1.599e-01 1.974e-01
  1.279e-01 2.069e-01 5.999e-02 7.456e-01 7.869e-01 4.585e+00 9.403e+01
  6.150e-03 4.006e-02 3.832e-02 2.058e-02 2.250e-02 4.571e-03 2.357e+01
  2.553e+01 1.525e+02 1.709e+03 1.444e-01 4.245e-01 4.504e-01 2.430e-01
  3.613e-01 8.758e-02]
 [1.142e+01 2.038e+01 7.758e+01 3.861e+02 1.425e-01 2.839e-01 2.414e-01
  1.052e-01 2.597e-01 9.744e-02 4.956e-01 1.156e+00 3.445e+00 2.723e+01
  9.110e-03 7.458e-02 5.661e-02 1.867e-02 5.963e-02 9.208e-03 1.491e+01
  2.650e+01 9.887e+01 5.677e+02 2.098e-01 8.663e-01 6.869e-01 2.575e-01
  6.638e-01 1.730e-01]
 [2.029e+01 1.434e+01 1.351e+02 1.297e+03 1.003e-01 1.328e-01 1.980e-01
  1.043e-01 1.809e-01 5.883e-02 7.572e-01 7.813e-01 5.438e+00 9.444e+01
  1.149e-02 2.461e-02 5.688e-02 1.885e-02 1.756e-02 5.115e-03 2.254e+01
  1.667e+01 1.522e+02 1.575e+03 1.374e-01 2.050e-01 4.000e-01 1.625e-01
  2.364e-01 7.678e-02]]

让我们看一下目标集。

# print the cancer labels (0:malignant, 1:benign)
print(cancer.target)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 1 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 0
 1 0 1 0 0 1 1 1 0 0 1 0 0 0 1 1 1 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 1 0 1 1
 1 1 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 1 1 0 1 1 0 1 1 1 1 0 1
 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 0 0 1 0
 1 0 1 1 1 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 1 1 0 1 0 0 0 0 1 1 0 0 1 1
 1 0 1 1 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 1 1 1 0 1 1 1 1 1 0 1 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 1 1 1 1 1 1 0 1 0 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1
 1 0 1 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 1 1
 1 1 0 1 0 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 0
 0 1 0 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 0 1 1 0 0 1 1 1 1 1 1 0 1 1 1 1 1 1
 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 0 1 0 1 1 1 1 1 0 1 1
 0 1 0 1 1 0 1 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1
 1 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 1 0 0 1 0 1 0 1 1 1 1 1 0 1 1 0 1 0 1 0 0
 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 0 0 0 0 0 0 1]

分割数据

为了了解模型的性能, 将数据集分为训练集和测试集是一个很好的策略。

使用函数train_test_split()拆分数据集。你需要传递3个参数功能, 目标和test_set大小。此外, 你可以使用random_state随机选择记录。

# Import train_test_split function
from sklearn.model_selection import train_test_split

# Split dataset into training set and test set
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size=0.3, random_state=109) # 70% training and 30% test

产生模型

让我们建立支持向量机模型。首先, 通过将参数内核作为线性内核传递到SVC()函数中, 导入SVM模块并创建支持向量分类器对象。

然后, 使用fit()将模型拟合到训练集上, 并使用predict()对测试集执行预测。

#Import svm model
from sklearn import svm

#Create a svm Classifier
clf = svm.SVC(kernel='linear') # Linear Kernel

#Train the model using the training sets
clf.fit(X_train, y_train)

#Predict the response for test dataset
y_pred = clf.predict(X_test)

评估模型

让我们估计分类器或模型可以多么准确地预测患者的乳腺癌。

可以通过比较实际测试设置值和预测值来计算准确性。

#Import scikit-learn metrics module for accuracy calculation
from sklearn import metrics

# Model Accuracy: how often is the classifier correct?
print("Accuracy:", metrics.accuracy_score(y_test, y_pred))
Accuracy: 0.9649122807017544

嗯, 你的分类率为96.49%, 被认为是非常不错的准确性。

为了进一步评估, 你还可以检查模型的精度和召回率。

# Model Precision: what percentage of positive tuples are labeled as such?
print("Precision:", metrics.precision_score(y_test, y_pred))

# Model Recall: what percentage of positive tuples are labelled as such?
print("Recall:", metrics.recall_score(y_test, y_pred))
Precision: 0.9811320754716981
Recall: 0.9629629629629629

好吧, 你的精度为98%, 召回率为96%, 这被认为是非常好的值。

调整超参数

  • 内核:内核的主要功能是将给定的数据集输入数据转换为所需的形式。有各种类型的函数, 例如线性, 多项式和径向基函数(RBF)。多项式和RBF对于非线性超平面很有用。多项式和RBF内核在更高维度上计算分隔线。在某些应用程序中, 建议使用更复杂的内核来分离弯曲或非线性的类。这种转换可以导致更准确的分类器。
  • 正则化:python的Scikit-learn C参数中的正则化参数用于维护正则化。 C是惩罚参数, 代表错误分类或错误项。错误分类或错误术语告诉SVM优化可承受多少错误。这是你如何控制决策边界和分类错误项之间的折衷方法。较小的C值将创建较小的超平面, 而较大的C值将创建较大的超平面。
  • Gamma:较低的Gamma值将宽松地适合训练数据集, 而较高的Gamma值将完全适合训练数据集, 这会导致过度拟合。换句话说, 可以说, 较低的gamma值在计算分隔线时仅考虑附近的点, 而gamma的a值在计算分隔线时考虑所有数据点。

优点

与朴素贝叶斯算法相比, SVM分类器可提供良好的准确性并执行更快的预测。他们还使用较少的内存, 因为他们在决策阶段使用了训练点的子集。 SVM可以很好地工作, 并且具有明显的分隔边缘和高维空间。

缺点

SVM不适合大型数据集, 因为其训练时间长, 并且与朴素贝叶斯相比, 它需要花费更多的训练时间。它与重叠的类一起使用时效果不佳, 并且对使用的内核类型也很敏感。

结论

恭喜, 你已完成本教程的结尾!

在本教程中, 你使用Scikit-learn软件包涵盖了关于支持向量机算法, 其工作, 内核, 超参数调整, 乳腺癌数据集模型构建和评估的许多基础知识。你还介绍了它的优点和缺点。希望你学到了一些有价值的东西!

要了解有关这种类型的分类器的更多信息, 你应该看看我们的Python线性分类器课程。它介绍了其他类型的回归和损失函数, 以及支持向量机。

我期待听到任何反馈或问题。你可以通过发表评论来提问, 我会尽力回答。

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?