支持向量机是另一种简单的算法,它性能相对较好,计算成本较低。在回归中,SVM 通过在 N 维空间(N 个特征)中找到一个超平面来工作,该超平面适合多维数据,同时考虑边距。在分类中,计算相同的超平面,但在考虑余量的同时再次对数据点进行明确分类。可以选择许多可能的超平面。然而,目标是找到具有最大边距的超平面,即目标类之间的最大距离。
SVM 可用于回归和分类问题,但它被广泛用于分类。
在我们继续之前,让我们解释一些术语。
内核是用于将数据转换为更高维度的函数。
超平面是分隔类别的线(用于分类问题)。对于回归,它是我们拟合数据以预测持续结果值的线。
边界线是形成我们之前提到的错误区域的线。它们是围绕超平面的两条线,代表边距。
支持向量是最接近这些边界线的数据点。
我们提到内核是将我们的数据转换为更高维度的函数。那么这对我们有什么用呢?
有时数据的分布方式无法通过使用线性线(分隔符)获得精确拟合。 SVR 可以使用核函数处理高度非线性的数据。该函数隐式地将特征映射到更高的维度,这意味着更高的特征空间。这使我们也可以使用线性超平面来描述它。
最常用的三个内核是:
与线性回归模型类似,SVR 也试图找到最适合数据集的曲线。记住我们的数据集方程,它具有线性回归的一个特征:
y=w1x1+c
考虑到同样具有一个特征的数据集的 SVR,等式看起来很相似,但考虑到了错误。
−e≤y−(w1x1+c)≤e
查看等式,可以清楚地看到在成本计算中只考虑 e 误差区域之外的点。
通过使用类似于多项式回归中的高维特征项,SVR 当然也可以用于具有更多特征的复杂数据集。
当超平面与可能的最大点数重合时,它最适合数据。我们确定边界线(e 的值,即与超平面的距离),以便离超平面最近的点位于边界线内。
请记住,因为边距(边界线之间)是可以容忍的,它不会被计算为错误。我想你已经可以想象这个术语将如何让我们调整模型的复杂性(欠拟合/过拟合)。
import numpy as np from sklearn.svm import SVR import matplotlib.pyplot as plt np.random.seed(5) X = np.sort(5 * np.random.rand(40, 1), axis=0) T = np.linspace(0, 5, 5)[:, np.newaxis] y = np.sin(X).ravel() # Add noise to targets y[::5] += 1 * (0.5 - np.random.rand(8)) # Fit regression model SVR_rbf = SVR(kernel='rbf' ) SVR_lin = SVR(kernel='linear') SVR_poly = SVR(kernel='poly') y_rbf = SVR_rbf.fit(X, y).predict(X) y_lin = SVR_lin.fit(X, y).predict(X) y_poly = SVR_poly.fit(X, y).predict(X) # look at the results plt.scatter(X, y, c='k', label='data') plt.plot(X, y_rbf, c='b', label='RBF') plt.plot(X, y_lin, c='r',label='Linear') plt.plot(X, y_poly, c='g',label='Polynomial') plt.xlabel('data') plt.ylabel('outcome') plt.title('Support Vector Regression') plt.legend() plt.show()
我们已经看到了“支持向量机 (SVM)”算法如何用于回归。对于分类,这个想法实际上几乎相同。事实上,SVM 主要用于分类问题。我相信你已经可以想象为什么……
对于回归,我们提到 SVM 会尝试找到最适合数据集的曲线,然后使用该曲线对新点进行预测。好吧,可以很容易地使用相同的曲线将数据分类为两个不同的类别。对于具有 n 维的多维空间(意味着具有 n 个特征的数据),该模型拟合一个最能区分这两个类别的超平面(也称为决策边界)。记住我们解释内核的回归部分的图像......
边距是每个类中两个最近点之间的距离,即从超平面到最近点(支持向量)的距离。最适合数据的超平面,也就是最好地将两个类分开的超平面,是具有最大可能边距的超平面。因此,SVM 算法搜索具有最大边距(到最近点的距离)的超平面。
就像我们在回归部分已经提到的那样,某些数据集不适合被线性超平面分类……在这种情况下,“内核技巧”再次帮助我们将数据隐式映射到更高维度,因此可以要由线性超平面分类的数据。由于我们已经讨论了内核类型及其工作原理,我将继续一个实现示例……
让我们继续使用 scikit learn 库中的癌症数据集:
from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split X, y = load_breast_cancer(return_X_y = True) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) X_sub = X[:, 0:2] # create a mesh to plot in x_min, x_max = X_sub[:, 0].min() - 1, X_sub[:, 0].max() + 1 y_min, y_max = X_sub[:, 1].min() - 1, X_sub[:, 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)) #import the SVM model from sklearn import svm C = 1.0 # SVM regularization parameter svc = svm.SVC(kernel='linear').fit(X_sub, y) #play with this, change kernel to rbf plt.subplot(1, 1, 1) Z = svc.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8) plt.scatter(X_sub[:, 0], X_sub[:, 1], c=y, cmap=plt.cm.Paired) plt.scatter(X_sub[svc.support_, 0], X_sub[svc.support_, 1],c='k', cmap=plt.cm.Paired) plt.xlabel('Sepal length') plt.ylabel('Sepal width') plt.xlim(xx.min(), xx.max()) plt.title('SVC with linear kernel') plt.show()
#Create and instance of the classifier model with a linear kernel lsvm = svm.SVC(kernel="linear") #fit the model to our train split from previous example lsvm.fit(X_train,y_train) #Make predictions using the test split so we can evaluate its performance y_pred = lsvm.predict(X_test)
让我们通过将预测与测试集中的真实值进行比较来比较模型的性能……
from sklearn import metrics print("Accuracy:",metrics.accuracy_score(y_test, y_pred)) print("Precision:",metrics.precision_score(y_test, y_pred)) print("Recall:",metrics.recall_score(y_test, y_pred))
我们能够达到 95.6% 的准确率,这非常好。让我们比较一下训练和测试的分数来检查是否过拟合……
print("training set score: %f" % lsvm.score(X_train, y_train)) print("test set score: %f" % lsvm.score(X_test, y_test))
训练分数似乎比测试分数高一点。我们可以说这个模型是过拟合的,虽然不多。
如果你喜欢这个,请随时关注我以获得更多免费的机器学习教程和课程!