程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

支持用 Python 示例解释的向量机_python支持向量机参数

hfteth 2025-02-17 12:20:05 技术文章 9 ℃

支持向量机 (SVM) 是一种监督式机器学习技术。而且,尽管它主要用于分类,但它也可以应用于回归问题。

SVM 定义了一个决策边界以及一个最大边距,将几乎所有点分成两类。同时也为错误分类留下了一些空间。

支持向量机是对最大边距算法的改进。它最大的优点是它可以通过使用核函数来定义线性或非线性决策边界。这使得它更适合于现实世界的问题,在这些问题中,数据并不总是可以用直线完全分开。

分离超平面

SVM 的主要目标是定义一个超平面,将两个不同类别中的点分开。超平面也称为分离超平面或决策边界。

因此,让我们从超平面开始。可视化超平面的最简单方法是考虑二维数据集。

将两个不同类别中的点完全分开的超平面。

将有无限数量的超平面将点分成两类。但是,由于我们在二维空间中工作,因此我们定义的任何超平面都将始终具有 (2–1) = 1 维。因此,我们可以用简单的回归线来表示超平面。

定义了决策边界后,我们现在可以根据点相对于点的位置对点进行分类。

根据向量落下的位置进行分类,与决策边界相对应。

如果要处理两个以上的维度,例如,特征向量 X 具有两个以上的特征,则您正在对向量进行分类,而不是对点进行分类。

因此,概括地说,所有低于决策边界的向量都属于类 -1,如果它们高于 -1 类,则属于类 1。

使用边距提高预测置信度

我们使用训练数据来定义决策边界。但是测试集的预测质量如何呢?

如果一个向量远离决策边界,我们可以对它的类有信心,即使模型有一些误差。但是,当我们对一个向量进行分类并且它非常接近决策边界时会发生什么?我们如何确定要分配哪个类?

为了解决这个问题,支持向量机还在决策边界周围画了一个边距。此边距的目标是尽可能地将向量与决策边界分开。其背后的直觉是,利润率让我们对自己的预测更有信心。由于向量至少是远离决策边界的边距长度,因此在分类过程中的歧义较小。

边距的位置是使用最接近决策边界的向量定义的。这就是为什么位于边距顶部的向量是支持向量的原因。

通过边距作为缓冲区,我们可以根据它们相对于边距的位置对向量进行分类。其中 M 是边距的宽度。

根据向量相对于边距的位置进行分类。

存在错误分类的余地

添加边距可提高测试集中预测的质量,但它假定类是完全可分离的。

但是,在大多数现实世界的问题中,数据是混乱的,通常不能完全分离。

这就是为什么 SVM 与之前的算法有一个共同的重要特征,即支持向量分类器。它允许算法犯错误,并为某些向量分配错误的类。

支持向量分类器的决策边界和边距,以及相应的支持向量。

因此,SMV 不是试图将向量完全分成两类,而是进行权衡。它允许一些向量落在边距内和决策边界的错误一侧。

支持向量机允许在学习过程中出现一些错误分类。因此,他们可以更好地对测试集中的大多数向量进行分类。

除了边际之外,我们的模型现在还包括松弛变量,这将告诉我们两件事:

  • 如果测试观测值分类错误,
  • 其中观测值相对于决策边界和边距。

Slack 变量可以有三个可能的值:

错误分类的向量数量受参数 C 的约束。

根据向量相对于边际的位置进行分类,包括松弛变量。

我们可以看到该模型捕捉到了更多的细微差别。但它仍然建立在最大边距分类器之上。例如,如果将参数 C 设置为零,这意味着它允许零松弛变量,则它会回退到最大边距分类器。因此,您有一个线性决策边界,一个尽可能大的边距,并且不允许在其内部使用向量。

松弛变量的数量越多,允许的错误分类向量的数量就越多。这会影响边距的宽度,因为选择不同的支持向量。它还控制模型的偏差-方差权衡。

松弛变量的数量如何控制偏差-方差权衡。

有一些错误分类的空间使 SMV 更具灵活性,但它仅适用于一组有限的问题。

在大多数现实世界的问题中,很难将数据分为具有线性决策边界的两类。即使有一些出错的余地。

支持向量机

SVM 具有之前的边缘分类器的特征。它们的独特之处在于它们如何定义线性和非线性决策边界。

为了支持非线性决策边界,SMV 使用函数将原始特征空间转换为可以表示这些非线性关系的新空间。

例如,假设您用正方形来扩充原始特征空间。在本例中,您对原始要素集应用了二次函数以创建这些要素的平方。现在,在这个增强的空间中,您拥有了原始功能及其二次版本。因此,隐式地,有一个函数可以映射这两个特征空间。

使用原始特征的二次版本来扩充特征空间。

如果尝试在原始特征空间中绘制决策边界,则该边界具有二次形状。但是,如果您在增强特征空间中训练模型,您会发现一个将两个类分开的线性决策边界。由于它是变换,因此原始特征空间中的二次边界对应于增强特征空间中的线性边界。

定义这些转换的函数称为内核。它们用作训练集和测试集中观测值之间的相似性函数。

使用线性核(右)和多项式核(左)的 SVM 的决策边界和裕量,以及相应的支持向量。

每当您有一个用内部产品表示的模型时,您都可以插入内核函数。例如,线性核与将线性变换应用于要素空间相同。而且,在本例中,它与支持向量分类器相同,因为决策边界是线性的。

使用多项式核,可以将原始特征空间投影到多项式特征空间中。因此,分隔类的决策边界是用高阶多项式定义的。

内核的使用是支持向量分类器与支持向量机的区别。它们为解决更复杂的问题提供了可能性。但是,增加特征空间可能意味着额外的计算需求。因为,在足够大的特征空间下,拟合模型的成本可能很高,无论是在时间还是资源方面。

尽管增强了功能空间,但内核带来了显着的优势。SVM 实际上并不计算每个观测值到增强空间的转换。他们使用一种技巧,而是在增强空间中计算观察的内积,这在计算上要便宜得多。这称为内核技巧。

最后,SVM 做出了两个重要的假设:

  • 数据是线性可分离的。即使线性边界位于增强的特征空间中。
  • 该模型使用内部产品表示,因此可以使用内核。

让我们看几个例子

为了查看支持向量机的运行情况,我生成了一个随机数据集并将其拆分为两个不同的类。下面是生成和绘制数据的代码片段。

import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as pltdef generate_random_dataset(size):
    """ Generate a random dataset and that follows a quadratic  distribution
    """
    x = []
    y = []
    target = []    for i in range(size):
        # class zero
        x.append(np.round(random.uniform(0, 2.5), 1))
        y.append(np.round(random.uniform(0, 20), 1))
        target.append(0)        # class one
        x.append(np.round(random.uniform(1, 5), 2))
        y.append(np.round(random.uniform(20, 25), 2))
        target.append(1)        x.append(np.round(random.uniform(3, 5), 2))
        y.append(np.round(random.uniform(5, 25), 2))
        target.append(1)    df_x = pd.DataFrame(data=x)
    df_y = pd.DataFrame(data=y)
    df_target = pd.DataFrame(data=target)    data_frame = pd.concat([df_x, df_y], ignore_index=True, axis=1)
    data_frame = pd.concat([data_frame, df_target], ignore_index=True, axis=1)    data_frame.columns = ['x', 'y', 'target']
    return data_frame
# Generate dataset
size = 100
dataset = generate_random_dataset(size)
features = dataset[['x', 'y']]
label = dataset['target']# Hold out 20% of the dataset for training
test_size = int(np.round(size * 0.2, 0))# Split dataset into training and testing sets
x_train = features[:-test_size].values
y_train = label[:-test_size].valuesx_test = features[-test_size:].values
y_test = label[-test_size:].values# Plotting the training set
fig, ax = plt.subplots(figsize=(12, 7))# removing to and right border
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)# adding major gridlines
ax.grid(color='grey', linestyle='-', linewidth=0.25, alpha=0.5)
ax.scatter(features[:-test_size]['x'], features[:-test_size]['y'], color="#8C7298")plt.show()

在进行任何分类之前,训练集如下所示。

随机训练集。

两组数据点之间有一点空间。但更接近中心,尚不清楚哪个数据点属于哪个类。

二次曲线可能是分隔这些类的良好候选者。因此,让我们用二阶多项式核拟合 SVM。

from sklearn import svm
model = svm.SVC(kernel='poly', degree=2)
model.fit(x_train, y_train)

为了查看拟合该模型的结果,我们可以将决策边界和边距与数据集一起绘制。

分类后的数据集,带有决策边界(全线)、边距(虚线)和支持向量,并用圆圈标记。

下面是绘制决策边界和边距的代码。

fig, ax = plt.subplots(figsize=(12, 7))# Removing to and right border
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)# Create grid to evaluate model
xx = np.linspace(-1, max(features['x']) + 1, len(x_train))
yy = np.linspace(0, max(features['y']) + 1, len(y_train))
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).Ttrain_size = len(features[:-test_size]['x'])# Assigning different colors to the classes
colors = y_train
colors = np.where(colors == 1, '#8C7298', '#4786D1')# Plot the dataset
ax.scatter(features[:-test_size]['x'], features[:-test_size]['y'], c=colors)# Get the separating hyperplane
Z = model.decision_function(xy).reshape(XX.shape)
# Draw the decision boundary and margins
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])# Highlight support vectors with a circle around them
ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100, linewidth=1, facecolors='none', edgecolors='k')plt.show()

如果我们根据测试集计算该模型的准确性,我们会得到一个很好的结果,因为数据集非常小并且是随机生成的。

具有二阶多项式核的 SVM 模型的精度。

from sklearn.metrics import accuracy_score
predictions_poly = model.predict(x_test)
accuracy_poly = accuracy_score(y_test, predictions_poly)print("2nd degree polynomial Kernel\nAccuracy (normalized): " + str(accuracy_poly))

准确性很好,但让我们看看是否有一种更简单的方法可以解决我们的问题。要使 SVM 与线性内核拟合,我们只需要更新内核参数即可。

model = svm.SVC(kernel='linear')
model.fit(x_train, y_train)

并像我们在那里所做的那样绘制决策边界。

分类后的数据集,带有决策边界(全线)、边距(虚线)和支持向量,并用圆圈标记。

现在看起来边距内的点越来越少,错误分类的点也越来越少。计算该模型的精度,它的精度略高于具有多项式核的模型。

具有线性核的 SVM 模型的精度。

因此,事实证明,对于这个问题,一个更简单的模型,即具有线性内核的 SVM,是最好的解决方案。



Tags:

最近发表
标签列表