机器学习之支持向量机实现与应用
支持向量机
从几何学上更加直观的方法进行求解,如下图所示:
上图展示了支持向量机分类的过程。图中\(wx十b=0\)为分割直线,我们通过这条直线将数据点分开。与此同时,分割时会在直线的两边再设立两个互相平行的虚线,这两条虚线与分割直线的距离一致。这里的距离往往也被我们称之为「间隔」,而支持向量机的分割特点在于,要使得分割直线和虚线之间的间隔最大化。同时也就是两虚线之间的间隔最大化。
对于线性可分的正负样本点而言,位于\(wc十b=1\)虚线外的点就是正样本点,而位于\(wx十b=一1\)虚线外的点就是负样本点。另外,正好位于两条虚线上方的样本点就被我们称为支持向量,这也就是支持向量机的名字来源。
1 |
|
make_blobs
是一个在 Python 的
sklearn.datasets
模块中定义的函数,用于生成一个二维或多维的分类数据集,这些数据集由多个圆形或球形的簇组成,通常用于测试和演示聚类算法。下面是函数
make_blobs
的参数解释:
n_samples
: 这是一个整数,表示每个中心点(cluster center)周围生成的样本数量。如果提供了一个元组,第一个元素表示每个簇的样本数量,第二个元素表示生成的簇的数量。centers
: 这是一个整数或数组,表示簇的数量。如果是一个整数,表示生成的簇的总数;如果是一个数组,则数组的长度表示簇的数量,数组中的每个元素是一个簇的中心点坐标。random_state
: 这是一个整数或None
,用于控制随机数生成器的种子,确保每次生成的数据集是相同的。如果设置为None
,则每次生成的数据集可能不同。cluster_std
: 这是一个浮点数,表示簇内数据点的标凊差(或方差的标准差)。它决定了簇内数据点的分布范围,值越大,簇内的数据点分布越分散。
使用 make_blobs
函数可以生成一个具有多个簇的数据集,每个簇的数据点围绕一个中心点分布,并且具有一定的随机性。这在机器学习中,特别是在聚类算法的测试和验证中非常有用。
函数间隔与几何间隔在支持向量机中的意义
在支持向量机(Support Vector Machine, SVM)中,函数间隔和几何间隔是衡量数据点与决策边界(即分类面)之间关系的两个重要概念。下面是它们的定义和意义:
- 几何间隔(Geometric Margin):
- 几何间隔是指数据点到决策边界(超平面)的最短距离。对于线性可分的情况,几何间隔是数据点到超平面的垂直距离。
- 几何间隔是实际的物理距离,可以直观地反映数据点在空间中的位置与决策边界的关系。
- 几何间隔越大,表示数据点与决策边界的距离越远,模型的分类能力越强,泛化能力越好。
- 函数间隔(Functional Margin):
- 函数间隔是指数据点在决策函数上的值与决策边界的距离。在二元分类问题中,决策函数可以表示为 \(\( f(x) = w \cdot x + b \)\),其中 \(\( w \)\) 是权重向量,$( b ) $是偏置项。
- 函数间隔计算的是 \(\( y_i (w \cdot x_i + b) \)\) 的值,其中 \(\( y_i \)\) 是第 \(\( i \)\) 个数据点的真实标签,\(\( x_i \)\) 是其特征向量。函数间隔的绝对值越大,表示数据点越容易被正确分类。
- 函数间隔是相对于权重向量 \(\( w \)\) 的,因此它与模型的参数(权重和偏置)有关。
它们之间的关系和意义: - 几何间隔与函数间隔的关系:几何间隔是函数间隔的缩放版本。具体来说,函数间隔 \(\( y_i (w \cdot x_i + b) \)\) 除以权重向量的范数 \(\( \|w\| \)\) 可以得到几何间隔 \(\( \frac{y_i (w \cdot x_i + b)}{\|w\|} \)\)。 - 优化目标:在SVM的训练过程中,目标是最大化函数间隔,而不是几何间隔。这是因为函数间隔与模型的参数直接相关,而几何间隔则依赖于权重向量的范数,这使得函数间隔更容易在优化过程中控制。 - 泛化能力:函数间隔越大,意味着模型对训练数据的拟合度越高,但也可能意味着过拟合。因此,SVM通过最大化函数间隔来寻找一个平衡点,从而提高模型的泛化能力。 - 决策边界:几何间隔直接决定了决策边界的位置。支持向量是那些几何间隔为零的数据点,它们是距离决策边界最近的点,对决策边界的形成有直接影响。
总结来说,几何间隔和函数间隔在SVM中都是衡量数据点与决策边界关系的重要指标,但它们在优化和泛化能力方面的作用有所不同。SVM的训练过程主要关注最大化函数间隔,以获得更好的泛化效果。
SVM的实现
scikit-learn 中的支持向量机分类器对应的类及参数为: 1
sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape='ovr', random_state=None)
C: 支持向量机中对应的惩罚参数。 kernel: 核函数,linear, poly, rbf, sigmoid, precomputed 可选,下文详细介绍。 degree: poly 多项式核函数的指数。 tol: 收敛停止的容许值。
如下图所示,支持向量机中当训练数据集并非完全线性可分时,这样在保证每个点都被正确分开后会造成过拟合,为了解决过拟合问题,引入惩罚因子 \(\xi\) ,可以看作上面的参数 C ,允许少部分的点出错。在训练集不完全线性可分情况下,我们就要使几何间隔尽可能的大,同时使误分类点的个数尽量小,C 则是调合二者的系数。
当我们使用支持向量机求解这类问题时,就会把最大间隔称之为最大「软间隔」,而软间隔就意味着可以容许零星噪声数据被误分类。而上文中能将数据完美分开的最大间隔也就被称为「硬间隔」。
这里,我们还是使用上面生成的示例数据训练支持向量机模型。由于是线性可分数据,kernel
参数指定为 linear
即可
线性支持向量机
- 数据准备
1 |
|
想要将两类数据分开,通过可视化我们能够看出我们有很多种直线可以选择
1 |
|
使用支持向量机可以是我们找到间距最大的那条直线
1 |
|
可视化支持向量机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def svc_plot(model):
# 获取到当前 Axes 子图数据,并为绘制分割线做准备
ax = plt.gca()
x = np.linspace(ax.get_xlim()[0], ax.get_xlim()[1], 50)
y = np.linspace(ax.get_ylim()[0], ax.get_ylim()[1], 50)
Y, X = np.meshgrid(y, x)
xy = np.vstack([X.ravel(), Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)
# 使用轮廓线方法绘制分割线
ax.contour(X, Y, P, colors="green", levels=[-1, 0, 1], linestyles=["--", "-", "--"])
# 标记出支持向量的位置
ax.scatter(
model.support_vectors_[:, 0], model.support_vectors_[:, 1], c="green", s=100
)加入噪点
1 |
|
通过改变参数C
的值,有不同的效果
1 |
|
非线性支持向量机
- 构造数据
1 |
|
1 |
|
1 |
|