支持向量机 (SVM)(二)-Kernel SVM,在前一节中,我们了解了如何使用简单的SVM算法来寻找线性可分数据的决策边界。然而,对于非线性可分数据,如下图1所示,直线不能作为决策边界。
图1:非线性可分数据
对于非线性可分数据,不能使用简单的SVM算法。而是使用了一种改进的SVM,称为内核SVM。
基本上,核支持向量机将非线性可分数据的下维投影到高维的线性可分数据上,将属于不同类的数据点分配到不同的维上。同样,这涉及到复杂的数学问题,但使用SVM时您不必担心。相反,我们可以简单地使用Python的Scikit-Learn库来实现和使用内核支持向量机。
用Scikit-Learn实现内核支持向量机
使用Scikit-Learn实现内核支持向量机类似于简单的支持向量机。在本节中,我们将使用著名的iris数据集,基于四种属性来预测植物所属的类别:sepal-width、sepal-length、petalwidth和petallength。
数据集可从以下连结下载:
https://archive.ics.uci.edu/ml/datasets/iris4
剩下的步骤都是典型的机器学习步骤,只需要很少的解释,直到我们到达训练我们的内核SVM的部分。
导入库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
导入数据集
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
# Assign colum names to the dataset
colnames = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']
# Read dataset to pandas dataframe
irisdata = pd.read_csv(url, names=colnames)
预处理
X = irisdata.drop('Class', axis=1)
y = irisdata['Class']
训练和测试数据分离
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
训练算法
为了训练核支持向量机,我们使用了与Scikit-Learn支持向量机库相同的SVC类。区别在于SVC类的内核参数的值。对于简单的SVM,我们使用“linear”作为核参数的值。但是,对于核支持向量机,您可以使用高斯(Gaussian)、多项式(polynomial)、sigmoid或computable kernel。我们将实现多项式、高斯和sigmoid内核,看看哪一个更适合我们的问题。
Polynomial Kernel
在多项式核的情况下,还必须为SVC类的度参数传递一个值。这就是多项式的次数。看看我们如何使用多项式核实现核SVM:
from sklearn.svm import SVC
svclassifier = SVC(kernel='poly', degree=8)
svclassifier.fit(X_train, y_train)
做预测
现在,一旦我们训练了算法,下一步就是对测试数据进行预测。
执行以下脚本:
y_pred = svclassifier.predict(X_test)
评估算法
通常,任何机器学习算法的最后一步都是对多项式核函数进行求值。执行以下脚本:
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
使用多项式核(Polynomial Kernel)的核SVM的输出是这样的:
[[11 0 0]
[ 0 12 1]
[ 0 0 6]]
precision recall f1-score support
Iris-setosa 1.00 1.00 1.00 11
Iris-versicolor 1.00 0.92 0.96 13
Iris-virginica 0.86 1.00 0.92 6
avg / total 0.97 0.97 0.97 30
现在让我们对高斯和sigmoid内核重复相同的步骤。
Gaussian Kernel
看看我们如何使用多项式核实现核SVM:
from sklearn.svm import SVC
svclassifier = SVC(kernel='rbf')
svclassifier.fit(X_train, y_train)
要使用高斯核函数,必须指定“rbf”作为SVC类的核参数。
预测和评估
y_pred = svclassifier.predict(X_test)
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
高斯核支持向量机的输出是这样的:
[[11 0 0]
[ 0 13 0]
[ 0 0 6]]
precision recall f1-score support
Iris-setosa 1.00 1.00 1.00 11
Iris-versicolor 1.00 1.00 1.00 13
Iris-virginica 1.00 1.00 1.00 6
avg / total 1.00 1.00 1.00 30
sigmoid Kernel
最后,让我们使用一个sigmoid内核来实现内核SVM。请看下面的脚本:
from sklearn.svm import SVC
svclassifier = SVC(kernel='sigmoid')
svclassifier.fit(X_train, y_train)
要使用sigmoid内核,必须将’sigmoid’指定为SVC类的内核参数的值。
预测和评估
y_pred = svclassifier.predict(X_test)
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
带Sigmoid核的核SVM的输出是这样的:
[[ 0 0 11]
[ 0 0 13]
[ 0 0 6]]
precision recall f1-score support
Iris-setosa 0.00 0.00 0.00 11
Iris-versicolor 0.00 0.00 0.00 13
Iris-virginica 0.20 1.00 0.33 6
avg / total 0.04 0.20 0.07 30
内核性能比较
如果比较不同类型内核的性能,我们可以清楚地看到sigmoid内核的性能最差。这是由于sigmoid函数返回两个值0和1的原因,因此它更适合于二进制分类问题。然而,在我们的例子中,我们有三个输出类。
在高斯核和多项式核中,我们可以看到高斯核的预测率达到了100%,而多项式核对一个实例进行了误分类。因此高斯核的表现稍好一些。但是,对于哪种内核在每种场景中执行得最好,并没有硬性的规则。这一切都与测试所有内核和选择在测试数据集上具有最佳结果的内核有关。
结论
在本节中,我们研究了简单支持向量机和内核支持向量机。我们研究了支持向量机算法背后的直觉,以及如何使用Python的Scikit-Learn库实现它。我们还研究了不同类型的内核,可以用来实现内核支持向量机。我建议您尝试在kaggle.com等网站提供的真实数据集上实现这些算法。
我还建议您探索支持向量机背后的实际数学。虽然使用SVM算法并不一定需要它,但是当您的算法正在寻找决策边界时,了解幕后实际发生了什么仍然非常方便。
资源
想了解更多关于SVMs、Scikit-Learn和其他有用的机器学习算法吗?我建议你查阅一些更详细的资料,比如下面这些书:
- Learning with Kernels: Support Vector Machines, Regularization, Optimization, and Beyond
- Python Data Science Handbook: Essential Tools for Working with Data
- Data Science from Scratch: First Principles with Python