支持向量机(Support Vector Machine,SVM)是一种强大的监督学习算法,广泛用于分类和回归问题。它能够有效处理线性和非线性数据,并在复杂数据集中表现出色。本文将介绍如何使用Python和scikit-learn库实现SVM,以及如何通过可视化不同参数设置来理解其工作原理。
一、什么是支持向量机(SVM)?
支持向量机是一种二类分类模型,它的基本思想是在特征空间中找到一个最优的超平面,能够将不同类别的数据点分隔开来,并且使得两侧距离最近的数据点(支持向量)到超平面的距离最大化。对于非线性可分的数据集,SVM通过核函数将数据映射到高维空间,使得数据线性可分。
二、实现步骤
我们将使用Python的scikit-learn库来实现一个简单的支持向量机分类器,并在一个合成的数据集上进行可视化展示。
1、导入必要的库和数据集生成
from sklearn import svm
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
import numpy as np
2、定义绘制决策边界和支持向量的函数
# 定义绘制决策边界和支持向量的函数
def plot_hyperplane(clf, X, y, h=0.02, draw_sv=True, title='Hyperplane'):
# 确定绘图边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
# 设置绘图属性
plt.title(title)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.xticks(())
plt.yticks(())
# 生成网格数据并进行预测
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 绘制决策边界
plt.contourf(xx, yy, Z, cmap='hot', alpha=0.5)
# 定义不同类别的标记和颜色
markers = ['o', 's', '^']
colors = ['b', 'r', 'c']
labels = np.unique(y)
# 绘制数据点
for label in labels:
plt.scatter(X[y==label][:, 0],
X[y==label][:, 1],
c=colors[label],
marker=markers[label])
# 如果指定绘制支持向量,则绘制支持向量
if draw_sv:
sv = clf.support_vectors_
plt.scatter(sv[:, 0], sv[:, 1], c='y', marker='x')
3、生成合成数据集
使用make_moons
函数生成一个合成的月亮形数据集,用于后续的分类器训练和可视化。
#生成包含150个样本的合成数据集,噪声为0.15
X, y = make_moons(n_samples=150, noise=0.15, random_state=42)
make_moons
函数生成一个合成的月亮形状数据集。n_samples
: 数据集样本数量。noise
: 噪声水平,增加数据的随机性。random_state
: 随机种子,确保每次运行生成的数据一致性。
4、初始化不同参数设置的SVM分类器
初始化了六个不同参数设置的SVM分类器,分别探索了不同的gamma
和C
参数组合对分类性能的影响。
# 初始化不同参数设置的SVM分类器
#初始化一个RBF核支持向量机分类器,设置参数C和gamma。
clf_rbf1 = svm.SVC(C=1, kernel='rbf', gamma=0.01)
clf_rbf2 = svm.SVC(C=1, kernel='rbf', gamma=5)
clf_rbf3 = svm.SVC(C=100, kernel='rbf', gamma=0.01)
clf_rbf4 = svm.SVC(C=100, kernel='rbf', gamma=5)
clf_rbf5 = svm.SVC(C=10000, kernel='rbf', gamma=0.01)
clf_rbf6 = svm.SVC(C=10000, kernel='rbf', gamma=5)
# 创建绘图区域
plt.figure()
# 将所有分类器放入列表中
clfs = [clf_rbf1, clf_rbf2, clf_rbf3, clf_rbf4, clf_rbf5, clf_rbf6]
# 设置每个子图的标题
titles = ['gamma=0.01, C=1',
'gamma=0.01, C=100',
'gamma=0.01, C=10000',
'gamma=5, C=1',
'gamma=5, C=100',
'gamma=5, C=10000']
- 初始化了六个不同参数设置的SVM分类器对象。
svm.SVC
: 创建一个支持向量机分类器。C
: 正则化参数。kernel
: 核函数类型,这里使用径向基函数(RBF)。gamma
: RBF核函数的参数,影响决策边界的灵活性和复杂度。clfs
: 包含所有分类器的列表。titles
: 每个分类器对应的标题,用于在图表中显示参数设置。
5、绘制不同参数设置下的SVM决策边界
最后,我们通过循环遍历每个分类器,对其进行训练并绘制出相应的决策边界和支持向量。
# 对每个分类器进行训练和绘图
for clf, i in zip(clfs, range(len(clfs))):
clf.fit(X, y) # 训练分类器
plt.subplot(3, 2, i+1) # 创建3行2列的子图,并选择当前子图
plot_hyperplane(clf, X, y, title=titles[i]) # 绘制决策边界和支持向量
plt.show() # 显示图形
- 创建一个12x10英寸大小的图形窗口。
- 使用
zip
函数将每个分类器clf
与其对应的索引i
组合。 - 对每个分类器进行训练(
clf.fit(X, y)
)并调用plot_hyperplane
函数绘制决策边界。 plt.subplot(3, 2, i+1)
: 将图形分成3行2列的子图,当前绘制第i+1
个子图。plt.tight_layout()
: 调整子图的布局,防止重叠。plt.show()
: 显示绘制的图形。
三、结果分析
这幅图展示了使用较小的gamma(0.01)和较小的正则化参数C(1)训练的SVM模型。
决策边界相对平滑,模型的复杂度较低。
可以看到一些支持向量被标记为黄色的'x'符号。
这幅图展示了相同的低gamma值(0.01),但更大的正则化参数C(100)。
决策边界仍然平滑,但稍微更接近一些数据点,对噪声更敏感。
使用了极大的C值(10000),同时gamma仍然较低(0.01)。
决策边界非常接近许多数据点,模型非常复杂,几乎适应了每个数据点,可能存在过拟合的风险。
这幅图展示了较高的gamma值(5)和较小的正则化参数C(1)。
决策边界非常复杂,几乎适应了每个数据点,可能出现了过拟合。
在高gamma(5)和较大C(100)的设置下,决策边界略有平滑化,但仍然相对复杂。
最后一幅图展示了高gamma(5)和非常大的C值(10000)。
决策边界非常复杂,几乎适应了每个数据点,存在严重的过拟合可能性。
总体分析:
参数gamma控制了决策边界的灵活性,较大的gamma值会导致决策边界更复杂,更贴近训练数据点。参数C是正则化参数,控制了对错误分类的惩罚,较大的C值会导致模型更关注训练数据,可能会导致过拟合。在低gamma和低C值的情况下,决策边界相对平滑,模型简单;而在高gamma和高C值的情况下,决策边界更复杂,可能会过度适应训练数据。