目录
一、概述
1.支持向量机
- 支持向量机(Support Vector Machine,SVM)是一种常用的机器学习算法,用于分类和回归分析。它的主要目的是寻找一个最优超平面,将不同属性的数据分成不同的类别。SVM是一种有效的分类器,因为它可以处理高维数据,并且可以使用核函数处理非线性可分的数据。
2.支持向量
- 离分隔超平面最近的那些点被称为支持向量
3.SVM思想
- 它的核心思想是通过将数据映射到高维空间来找到一个最优的超平面。
- SVM通过找到支持向量来定义最优超平面。支持向量是最接近超平面的数据点,它们对于定义超平面的位置和方向起着重要的作用。因此,SVM寻找最优超平面的过程可以简化为找到能够最大化支持向量到最优超平面的距离的超平面。
4.线性SVM
线性SVM的损失函数由两部分组成:铰链损失函数和正则化项:
- 如果样本正确分类且在正确的间隔之外,即 , 则
- 如果样本错误分类或在间隔内,即, 则,
二、SVM流程
-
数据预处理
在使用SVM之前,需要对数据进行预处理,包括数据清洗、特征选择和特征提取等。此外,还需要将数据分为训练集和测试集。
-
特征映射
SVM的核心思想是通过将数据映射到高维空间来找到一个最优的超平面。因此,在这一步中,需要将数据通过核函数进行映射,将原始数据映射到高维空间。
-
寻找最优超平面
在映射到高维空间后,SVM需要寻找一个最优的超平面,将数据分成不同的类别。为了找到最优超平面,需要确定一些参数,如C(惩罚系数)和γ(核函数的参数),以最大化分类器的准确性。
-
分类
在训练好分类器后,需要使用测试数据集对分类器进行测试,并计算分类器的准确率和召回率等指标。
三、python代码实现
1.数据准备
X,y = datasets.make_blobs(n_samples=150,centers=2,random_state=6)
y = np.where(y==0,-1,1) # 调整标签为-1和1
- 输出数据,标签如下
sklearn 中的 make_blobs 的参数解释
函数原型
data, label = make_blobs(n_samples=100, n_features=2, centers=3, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)
参数说明
- n_features :表示每一个样本有多少特征值 ,默认2
- n_samples :表示样本的个数 ,默认100
- centers: 是聚类中心点的个数,可以理解为label的种类数 ,默认3
- random_state :是随机种子,可以固定生成的数据
- cluster_std :设置每个类别的方差, 例如我们希望生成3类数据,可以将cluster_std设置为[1.0,3.0,5.0]。代表最后一类方差最大,分布的最散乱
- shuffle: 是否打乱数据。默认打乱
2.SVM
def __init__(self,learning_rate=0.0001,lambda_param=0.1,n_iters=1000):
self.learning_rate = learning_rate # 学习率
self.lambda_param = lambda_param # 正则化参数
self.n_iters = n_iters # 迭代次数
self.w = None # 参数w
self.b = None # 参数b
def fit(self,X,y):
n_samples,n_features = X.shape
# 将标签y转换为{-1,1},便于后续计算
y_ = np.where(y <= 0,-1,1)
#初始化权重和偏置为0
self.w = np.zeros(n_features) # 初始化参数w为全零向量
self.b = 0 # 初始化参数b为0
# 使用梯度下降法求解最优参数w和b
for _ in range(self.n_iters):
for idx,x_i in enumerate(X):
condition = y_[idx] * (np.dot(x_i,self.w) - self.b) >= 1 #遍历每个样本,检查分类条件(样本点是否位于Margin之内)
if condition:
#如果样本正确分类并且在正确的间隔之外,仅通过正则项更新权重(防止过拟合)
self.w -= self.learning_rate * (2 * self.lambda_param * self.w)
else:
#如果样本错误分类或在间隔内,则权重w更新将包括误差项,同时更新b,以使得该样本在未来能被正确分类
self.w -= self.learning_rate * (2 * self.lambda_param * self.w - np.dot(x_i,y_[idx]))
self.b -= self.learning_rate * y_[idx]
def predict(self,X):
linear_output = np.dot(X,self.w) - self.b # 计算样本点到超平面的距离
return np.sign(linear_output) # 返回样本点的类别,即其符号
- 在
__init__
函数中,定义了学习率、正则化参数和迭代次数等超参数。- 在
fit
函数中,使用梯度下降法求解最优参数w和b,其中当样本点位于Margin之外时,更新参数w和b。- 在
predict
函数中,计算样本点与超平面的距离,并返回其符号作为预测结果。
模型训练
svm = LinearSVM()
svm.fit(X,y)
增加参数C的SVM分类器
class LinearSVM:
def __init__(self,C=1.0,learning_rate=0.0001,n_iters=1000):
self.C = C
self.learning_rate = learning_rate
self.n_iters = n_iters
self.w = None
self.b = None
def fit(self,X,y):
n_samples,n_features = X.shape
y_ = np.where(y <= 0,-1,1)
self.w = np.zeros(n_features)
self.b = 0
for _ in range(self.n_iters):
for idx,x_i in enumerate(X):
condition = y_[idx] * (np.dot(x_i,self.w) - self.b) >= 1
if condition:
self.w -= self.learning_rate * (2*self.w)
else:
self.w -= self.learning_rate * ((2 * self.w) - self.C * np.dot(x_i,y_[idx]))
self.b -= self.learning_rate * self.C * y_[idx]
def predict(self,X):
linear_output = np.dot(X,self.w) - self.b
return np.sign(linear_output)
# 数据准备和模型训练
X,y = datasets.make_blobs(n_samples=150,centers=2,random_state=6)
y = np.where(y==0,-1,1) # 调整标签为-1和1
svm = LinearSVM(C=100) # 调整C参数来看不同的效果
svm.fit(X,y)
# 可视化结果
plot_hyperplane(X,y,svm.w,svm.b)
3.可视化
# 可视化结果
def plot_hyperplane(X,y,w,b):
plt.scatter(X[:,0],X[:,1],marker='o',c=y,s=100,edgecolors='k',cmap='winter')
ax = plt.gca() # 获取当前图形的坐标轴对象,以便对其进行更改或添加其他元素(标题,标签,网格线等)
xlim = ax.get_xlim() # 返回当前ax视图的x的上下限
ylim = ax.get_ylim() # 返回当前ax视图的y的上下限
xx = np.linspace(xlim[0],xlim[1],30) # 生成结构与Numpy数组类似的均匀分布的数值序列
yy = np.linspace(ylim[0],ylim[1],30)
YY,XX = np.meshgrid(yy,xx) #成为两个二维矩阵
xy = np.vstack([XX.ravel(),YY.ravel()]).T
Z = (np.dot(xy,w)-b).reshape(XX.shape)
ax.contour(XX,YY,Z,colors='k',levels=[-1,0,1],alpha=0.5,linestyles=['--','-','--'])
plt.show()
- plt.gca():获取当前图形的坐标轴对象,以便对其进行更改或添加其他元素(标题,标签,网格线等)
- get_xlim():返回当前ax视图的x的上下限
- np.linspace(start,stop,num):生成结构与Numpy数组类似的均匀分布的数值序列
- np.meshgrid(yy,xx):成为两个二维矩阵
- np.vstack ().t:使用numpy中的vstack ()函数将多个数组垂直堆叠,然后使用t属性进行转置操作。 具体来说,它会将多个数组按照垂直方向进行堆叠,然后对堆叠后的数组进行转置操作,即行变成列,列变成行。
可视化结果:
实验结果分析
由上图可知,软间隔就是增加参数C(惩罚系数)后,模型的泛化能力更强了,这两组数据之间的间隔更小了。C值越大,越重视离群点,对错误分类的惩罚较大,两组数据间隔小,可能会出现过拟合的情况;反之C越小,就很有可能出现欠拟合的情况。
四、实验总结
SVM在处理高维数据和非线性数据时表现出色,并且对于噪声数据和小样本问题也有很好的效果。但是,SVM的计算复杂度较高,并且需要选择适当的核函数,因此在实际应用中需要仔细考虑其优缺点,以选择合适的机器学习算法。