机器学习(4)

10 篇文章 1 订阅
10 篇文章 1 订阅

支持向量机(SVM)是一种非常强大的机器学习模型,能够进行线性、非线性分类、回归问题,还能检测异常值。SVM特别适用于复杂但小型或中型的数据集的分类。

一,线性SVM分类

(Linear SVM Classification)

在这里插入图片描述

如图,从左图我们可以看到现在有两类数据,只需要1条直线就能把它们分开,其中红线和紫线都能把这两类数据完美的分开,但是两条直线都非常靠近样本,如果有新的样本加入,有比较大的可能会分类错误。

因此线性SVM的思想就是如右图的黑色实线,决策边界在正确分类的同时离最近的样本尽可能的远。而这些最近的样本(途中虚线上的点)即为支持向量(support vector)。因此只要没有点在这些点划分的区域之间,决策边界就只由这些支持向量所决定。

需要注意:SVM对特征之间的尺度比较敏感,因此要先对特征进行缩放(如标准化(StandardScaler))

软间隔分类 Soft Margin Classification

上面严格的把所有样本用一条直线分开为两类,叫做Hard margin classification。但是在实际情况中,可能存在一些异常点(如下图),左图中的异常点在另一类之中,没有办法用一条直线分开;右图中异常点离另一类很近,虽然能分开,但是决策线看起来非常不好。

在这里插入图片描述

为了解决这种问题,需要一个更加宽松灵活的模型,来权衡尽可能分开以及限制支持向量组成的区域里面点的个数,这就叫Soft Margin Classification

在Scikit-learn的SVM类中,可以通过调剂松弛因子C来权衡,C越大,分类越严格;C越小,在margin内的点越多。

在这里插入图片描述

需要注意:如果你的SVM模型过拟合了,可以尝试减小C

下面通过加载Iris数据,标准化后训练一个线性SVM模型(C=0.1),使用的损失函数为hinge loss:max(0,1−t)

import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X = iris["data"][:, (2, 3)] # petal length, petal width
y = (iris["target"] == 2).astype(np.float64) # Iris-Virginica
svm_clf = Pipeline((
("scaler", StandardScaler()),
("linear_svc", LinearSVC(C=1, loss="hinge")),
))
svm_clf.fit(X, y)

#预测
pre_result = svm_clf.predict([[5.5, 1.7]])
print(pre_result)

需要注意:SVM分类器不像Logistic回归分类器一样有predict_proba()方法来计算得分(概率),因为SVM只是靠支持向量来构建决策线。而且loss函数一定要记得填”hinge”,因为默认不是”hinge”。

除了使用LinearSVC类来训练线性SVM外,还可以使用SVC类,参数为(kernel=“linear”,C=1),不过这种方法会比LinearSVC慢很多。还可以用SGDClassifier类,参数为(loss=“hinge”,alpha=1/(m*C)),这种使用随机梯度下降方法来训练SVM,虽然没有LinearSVC收敛快,但是能够处理数据量庞大的训练集,而且能够在线学习。

二,非线性SVM分类

Nonlinear SVM Classification

由于现实数据中更多的是线性不可分的数据。为了能用线性分类器分类线性不可分的数据,其中一种方法就是如上一节的多项式分类想法一样,通过增加x2,x3x2,x3等特征,使得数据能够线性可分。

多项式核(Polynomial Kernel)

基于这个思想,可以增加多项式特征来进行非线性分类。但是如果degree设置的比较小,则比较难分类比较复杂的数据;如果degree设置的比较大,产生了大量模型,导致训练的非常慢。

​ 幸运的是,SVM能用运用一些数学的技巧,称为核技巧(Kernel trick)(后面会说到)。可以不真正的增加这些(如多项式)特征,来达到增加这些特征相同的效果。所以高degree并不会带来特征的急剧增加,因为并没有真正增加特征。这种方法可以在SVC类中使用。下面是一个例子:

from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
#构造球型数据集
(X,y)=make_moons(200,noise=0.2)
#使用SVC类中的多项式核训练
poly_kernel_svm_clf = Pipeline((
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))
))
poly_kernel_svm_clf.fit(X, y)

其中参数coef0为高degree特征相比低degree特征对模型的影响程度。参数degree为选择多项式特征的维度,参数C为松弛因子。

还可以把决策线画出来看看效果如何:

import numpy as np
import matplotlib.pyplot as plt
xx, yy = np.meshgrid(np.arange(-2,3,0.01), np.arange(-1,2,0.01))
y_new=poly_kernel_svm_clf.predict(np.c_[xx.ravel(),yy.ravel()])
plt.contourf(xx, yy, y_new.reshape(xx.shape),cmap="PuBu")
plt.scatter(X[:,0],X[:,1],marker="o",c=y)
plt.show()

在这里插入图片描述

可以看到能够比较好的完成非线性分类。

需要注意:模型的参数应该使用Grid search来调整到一个比较好的状态,如果过拟合(可以通过交叉验证来评价),则可以适当减小degree;如果欠拟合,则增加。

高斯径向基核(Gaussian RBF Kernel)

除了通过多项式增加特征以外,还有别的增加特征的方式,比如通过Gaussian Radial Basis Function (RBF)增加相似特征。高斯RBF的表达式为:

在这里插入图片描述

如下左图为一维线性不可分的情况,比如通过设置参数γ为0.3,参数ll(landmark)为-2和1,可以看到RBF函数对应的函数曲线类似钟形。假设为x1=−1增加特征,

在这里插入图片描述

在这里插入图片描述

将所有点增加特征后如右图,可以发现增加特征后能够线性可分。

在这里插入图片描述

如何选择landmark。 最简单的方法是在数据集中的每个实例的位置创建一个landmark。这创建了许多特征,从而使得变换后的训练集将是线性可分的。缺点是具有m个实例和n个特征的训练集被转换成具有m个实例和m个特征的训练集(假设放弃了原始特征)。如果训练集非常大,则会得到大量的特征,影响计算速度。

然而对于SVM,正如上面所说可以并不真正增加特征而达到同样的效果,下面利用SVC类的RBF核来试验一下:

#训练RBF核SVM
rbf_kernel_svm_clf = Pipeline((
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="rbf", gamma=5, C=0.001))
))
rbf_kernel_svm_clf.fit(X, y)
#画出决策线
import numpy as np
import matplotlib.pyplot as plt
xx, yy = np.meshgrid(np.arange(-2,3,0.01), np.arange(-1,2,0.01))
y_new=rbf_kernel_svm_clf.predict(np.c_[xx.ravel(),yy.ravel()])
plt.contourf(xx, yy, y_new.reshape(xx.shape),cmap="PuBu")
plt.scatter(X[:,0],X[:,1],marker="o",c=y)

在这里插入图片描述

可以看到实现了非线性分类,然而决策边界范围很小,如果γγ比较大,会使得决策线变窄,变得不规则。相反,小的γγ使决策线变宽,边平滑。所以γγ就像一个正则化参数:如果你的模型过拟合,可以适当减少它,如果它欠拟合,可以增加它(类似于C超参数)。

除了多项式核和高斯RBF核以外还有一些别的核,但都不太常用,一般用于一些特殊数据。

有这么多的内核可供选择,应该使用哪一个?一个经验法则,应该总是先尝试线性内核(LinearSVC比SVC(kernel =“linear”)快得多),特别是当训练集非常大或者有很多特征的时候。如果训练集不是太大,应该尝试高斯RBF核; 它在大多数情况下运行良好。如果你有空闲时间和计算能力,你还可以使用交叉验证和网格搜索来试验其他一些内核,特别是如果有专门用于你的训练集的数据结构的内核。

三,SVM回归

SVM除了能进行分类任务以外还能做回归任务。与SVM分类任务尽量让点在margin以外,而SVM回归则是尽量让点在margin以内通过参数εε控制margin的大小,εε越大,margin越大,否则越小。(如下图)

在这里插入图片描述

下面为训练一个线性SVM回归模型的例子,对应的类为LinearSVR

from sklearn.svm import LinearSVR
svm_reg = LinearSVR(epsilon=1.5)
svm_reg.fit(X, y)

SVM非线性回归问题与分类问题类似,通过设置核来实现。

from sklearn.svm import SVR
svm_poly_reg = SVR(kernel="poly", degree=2, C=100, epsilon=0.1)
svm_poly_reg.fit(X, y)

四,工作原理

参考资料:https://cuijiahua.com/blog/2017/11/ml_8_svm_1.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aqiu12316

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值