目录
一.svm概述
1.概念
支持向量机(Support Vector Machine, SVM) 本身是一个二元分类算法,是对感知器算法模型的一种扩展,在的 SVM 算法支持线性分类和非线性分类的分类应用
二.感知算法思想
svm算法是感知机的一种扩展,所以来介绍一下什么是感知器
1.感知器思想
感知器是由一位心理医生Rosenblatt在1985年提出的,他的原理很简单:在任意空间中,感知器模型寻找的就是一个超平面,让可以线性可分的数据二元分割开.
感知器模型为: y = s i g n ( θ x ) = { + 1 θx>0 − 1 θx<0 y = sign(θx) =\begin{cases}+1& \text{θx>0}\\-1& \text{θx<0} \end{cases} y=sign(θx)={+1−1θx>0θx<0
正确分类为y*θx>0,错误分类为y**θx<0,因此可以定义损失函数为:期望使所有分类错误的样本到超平面的距离之和最小
三.svm算法思想
1.与感知机的异同
相同:svm也是通过寻找超平面,来解决二分类问题的分类算法,模型判别式和感知器一样.
不同:①感知机通过判错的点寻找超平面,而svm通过支持向量寻找超平面
②感知机和上次说的逻辑回归都是通过最小化损失函数来求解,而svm有两种解法,一种是最小化损失函数,另一种是寻找支持向量,找到支持向量超平面也就找到了
svm更好的地方:在感知器模型中,我们可以找到多个可以分类的超平面,假设未来拿到的数据有一部分有噪声,那么不同的超平面对噪声的容忍度是不同的.那么我们就需要让离超平面比较近的点尽可能远离超平面,svm就是这个思想.
2.支持向量机
1.线性可分支持向量机
硬间隔最大化
2.线性支持向量机
软间隔最大化
3.非线性支持向量机
升维
分割超平面
将数据集分隔开的直线/平面叫做分割超平面
线性可分
在数据集中可以找出一个超平面将两组数据分开,那么这个数据集叫做线性可分数据集
线性不可分
在数据集中找不到一个超平面可以将两组数据分开,那么这个数据集叫做线性不可分数据集
间隔
数据点到分割超平面的距离
支持向量
离超平面最近的一个或多个点
本文主要说的是线性可分支持向量机
3.线性可分支持向量机
硬间隔最大化
寻找这样一个超平面:
1.完美分类正负例
2.距离超平面最近的点越远越好
目标:
能正确分类的平面中,距离越近的点越远越好,也就是找到一组最好的w和b固定一个超平面,这个超平面能完美区分正负例,距离最近的点间隔最大
转化为有约束函数最优化问题就是: m a x w , b γ m i n = y m i n ( w x m i n + b ) ∣ ∣ w ∣ ∣ max_{w,b} γ_{min}=\frac{y_{min}(wx_{min}+b)}{||w||} maxw,bγmin=∣∣w∣∣ymin(wxmin+b)
s . t y i ( w T x i + b ) = γ ′ ( i ) > = γ ′ ( i = 1 , 2 , . . . m ) s.t\quad y_i(w^Tx_i+b) = γ^{'(i)}>=γ^{'}(i=1,2,...m) s.tyi(wTxi+b)=γ′(i)>=γ′(i=1,2,...m)
γ’代表支持向量的函数距离
令γ’=1,则原最优化问题为: m a x 1 ∣ ∣ w ∣ ∣ 2 max\frac{1}{||w||_2} max∣∣w∣∣21
s . t y i ( w T x i + b ) > = 1 ( i = 1 , 2 , . . . m ) s.t\quad y_i(w^Tx_i+b) >=1(i=1,2,...m) s.tyi(wTxi+b)>=1(i=1,2,...m)
等价于:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 2 min\frac{1}{2}{||w||_2^2} min21∣∣w∣∣22
s . t y i ( w T x i + b ) > = 1 ( i = 1 , 2 , . . . m ) s.t\quad y_i(w^Tx_i+b) >=1(i=1,2,...m) s.tyi(wTxi+b)>=1(i=1,2,...m)
四.svm实现
svm两种实现方式
1.同过拉格朗日将上面函数转化为另一种形式在用smo处理
2.将上面函数转换为hinge函数加上正则化项即: m i n w , b ∑ i = 1 m [ 1 − y ( i ) ( w T x ( i ) + b ) ] + + λ ∣ ∣ w ∣ ∣ 2 min_{w,b} \sum_{i=1}^{m}[1-y^{(i)}(w^Tx^{(i)}+b)]_++λ||w||^2 minw,bi=1∑m[1−y(i)(wTx(i)+b)]++λ∣∣w∣∣2
在上述式子中,当λ = 1/2C时,等价于原目标函数
1.数据读取(文末完整数据)
import numpy as np
import matplotlib.pyplot as plt
def data_set():#数据准备
fr = open(r"D:\1.txt")
features = []
labels = []
for line in fr.readlines():
temp = line.strip().split()
features.append([float(temp[0]),float(temp[1])])
labels.append(int(temp[2]))
return np.array(features),np.array(labels)
可以通过以下函数查看样本
def draw_point(x,y):
x1 = []
y1 = []
x2 = []
y2 = []
for i in range(len(y)):
if y[i] == -1:
x1.append(x[i][0])
y1.append(x[i][1])
elif y[i] == 1:
x2.append(x[i][0])
y2.append(x[i][1])
plt.scatter(x1, y1, marker='^', c='b', label="-1")
plt.scatter(x2, y2, marker='o', c='g', label="1")
plt.show()
2.hinge损失函数
hinge loss L ( y ( w x + b ) ) = [ 1 − y ( w x + b ) ] + L(y(wx+b))=[1-y(wx+b)]_+ L(y(wx+b))=[1−y(wx+b)]+
下标"+"表示取正值函数
[ z ] + = { z z>0 0 z<= 0 [z]_+ =\begin{cases}z& \text{z>0}\\0& \text{z<= 0} \end{cases} [z]+={z0z>0z<= 0
hinge损失图像如下
# Hinge损失函数
def hinge_loss(w, X, y):
# 计算 hinge 损失
distances = 1 - y * (np.dot(X, w[:-1]) + w[-1])
return np.maximum(0,distances)
根据这个函数,可以看出如果数据被正确分类,则损失为0,否则损失为z
3.svm损失函数
通过hinge函数可以将原目标函数转变为 m i n w , b ∑ i = 1 m [ 1 − y ( i ) ( w T x ( i ) + b ) ] + + λ ∣ ∣ w ∣ ∣ 2 min_{w,b} \sum_{i=1}^{m}[1-y^{(i)}(w^Tx^{(i)}+b)]_++λ||w||^2 minw,bi=1∑m[1−y(i)(wTx(i)+b)]++λ∣∣w∣∣2
在上述式子中,当λ = 1/(2C) 时,等价于原目标函数 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i \frac{1}{2} ||w||^2+ C\sum_{i=1}^{m}ξ_i 21∣∣w∣∣2+Ci=1∑mξi
def objective_function(w, X, y, C=1.0):#C就是λ
# Hinge 损失部分
hinge = hinge_loss(w, X, y)
# L2 正则化部分
regularization = 0.5 * np.dot(w[:-1], w[:-1])#||w||
# 目标函数的值
return np.mean(hinge) + C * regularization
4.通过梯度下降来最小化损失函数
def gradient_descent(X, y, C=1.0, learning_rate=0.01, iterations=1000):#C就是λ,正则化参数.learning_rate学习率,控制次迭代的步长.iterations为迭代总次数
n_samples, n_features = X.shape
# 初始化权重向量 w,最后一项为偏置值即b
w = np.zeros(n_features + 1)
for i in range(iterations):
# 计算梯度
grad = np.zeros(n_features + 1)
for j in range(n_samples):
# 计算预测值
decision = np.dot(X[j], w[:-1]) + w[-1]
# 如果样本在间隔之外或在错误的一侧,则计算Hinge损失的梯度
if decision * y[j] < 1:
grad[:-1] += -y[j] * X[j]
grad[-1] += -y[j]
# 计算正则化项的梯度
grad[:-1] += 2 * C * learning_rate * w[:-1]
# 应用梯度下降更新
w -= learning_rate * grad
return w
可以得到w为(最后一项为偏置值b)
5.结果
通过以下代码可以看到
def plotBestFit(wei, X, y):
print("Weights:", wei)
# 假设 wei 的最后一项是偏置项 b
weights = wei[:-1]
b = wei[-1]
# 获取数据集
dataArr, labelMat = data_set()
# 分离两类数据
X1 = X[labelMat == 1]
X2 = X[labelMat == -1]
# 创建图形和坐标轴
fig, ax = plt.subplots()
# 绘制数据点
ax.scatter(X1[:, 0], X1[:, 1], c='red', marker='s', label='Class 1')
ax.scatter(X2[:, 0], X2[:, 1], c='green', marker='o', label='Class -1')
# 绘制决策边界
x_min, x_max = -3, 3
y_min, y_max = -3, 3
x = np.arange(x_min, x_max, 0.05)
y = (-b - weights[0] * x) / weights[1] # 假设是二维数据
ax.plot(x, y, 'k-') # 黑色实线
# 设置图例
ax.legend()
# 设置坐标轴标签
plt.xlabel('X1')
plt.ylabel('X2')
# 显示图形
plt.show()
将数据集全分对了,并且离超平面最近的点距离最远
五.总结
svm是作为感知机扩展的一种二元分类算法,不仅可以支持线性可分数据分类,还能处理非线性数据,通过寻找最合适超平面,并使离超平面最近的点最远来完成分类.svm有两种主要求解方式一种是通过最小化损失函数,另一种是通过寻找支持向量.
线性可分支持向量机
线性可分SVM的目标是找到一个超平面,该超平面不仅能够完美地分类数据,而且使得距离最近的点(支持向量)尽可能远离超平面。这转化为一个约束优化问题,可以通过拉格朗日乘子法和序列最小优化(SMO)算法求解。
SVM实现
SVM的实现有两种主要方法:
- 使用拉格朗日乘子法将问题转化为对偶问题,然后应用SMO算法求解。
- 将问题转化为使用Hinge损失函数和L2正则化的形式,然后通过梯度下降法求解。(本文使用方法)
实现步骤
- 数据读取:使用data_set函数从文本文件中读取特征和标签,返回NumPy数组。
- 数据可视化:draw_point函数用于将不同类别的数据点绘制在图上,以便于观察。
- Hinge损失函数:定义了hinge_loss函数来计算每个样本的Hinge损失。
- 目标函数:objective_function函数结合了Hinge损失和L2正则化,用于评估模型的性能。
- 梯度下降法:gradient_descent函数通过迭代更新权重来最小化目标函数,从而求解最优权重向量w。
结果
通过梯度下降法训练SVM模型后,可以使用plotBestFit函数来可视化结果,该函数能够展示数据点和决策边界,从而验证模型是否能够正确分类,并且最大化了间隔。
附(完整数据集)
0.12 0.34 -1
1.23 4.56 1
1.45 3.67 1
2.22 1.11 -1
3.33 4.44 1
0.55 0.66 -1
1.78 2.89 1
2.56 3.21 1
0.31 0.42 -1
1.11 2.22 1
0.45 0.78 -1
2.34 3.45 1
1.67 2.98 1
0.22 0.33 -1
3.21 4.32 1
1.23 0.45 -1
2.11 3.22 1
0.56 0.78 -1
1.34 2.56 1
3.45 4.67 1
0.12 1.23 -1
2.34 3.45 1
0.67 0.89 -1
1.23 3.45 1
0.98 1.23 -1
3.21 4.56 1
1.11 0.22 -1
2.33 3.44 1
0.55 0.66 -1
1.78 2.89 1
2.34 3.21 1
0.31 0.42 -1
1.11 2.22 1
0.45 0.78 -1
2.34 3.45 1
1.67 2.98 1
0.22 0.33 -1
3.21 4.32 1
1.23 0.45 -1
2.11 3.22 1
0.56 0.78 -1
1.34 2.56 1
3.45 4.67 1
0.12 1.23 -1
2.34 3.45 1
0.67 0.89 -1
1.23 3.45 1
0.98 1.23 -1
3.21 4.56 1
1.11 0.22 -1
2.33 3.44 1
0.55 0.66 -1
1.78 2.89 1
2.56 3.21 1
0.31 0.42 -1
1.11 2.22 1
0.45 0.78 -1
2.34 3.45 1
1.67 2.98 1
0.22 0.33 -1
3.21 4.32 1
1.23 0.45 -1
2.11 3.22 1
0.56 0.78 -1
1.34 2.56 1
3.45 4.67 1
0.12 1.23 -1
2.34 3.45 1
0.67 0.89 -1
1.23 3.45 1
0.98 1.23 -1
3.21 4.56 1
1.11 0.22 -1
2.33 3.44 1
0.55 0.66 -1
1.78 2.89 1
2.56 3.21 1
0.31 0.42 -1
1.11 2.22 1
0.45 0.78 -1
2.34 3.45 1
1.67 2.98 1
0.22 0.33 -1
3.21 4.32 1
1.23 0.45 -1
2.11 3.22 1
0.56 0.78 -1
1.34 2.56 1
3.45 4.67 1
0.12 1.23 -1
2.34 3.45 1
0.67 0.89 -1
1.23 3.45 1
0.98 1.23 -1
3.21 4.56 1
1.11 0.22 -1
2.33 3.44 1
0.42 0.56 -1
1.89 3.12 1
0.34 0.89 -1
2.45 3.67 1
1.22 0.99 -1
3.78 4.56 1
0.61 0.73 -1
1.57 2.23 1
2.89 3.45 1
0.21 0.34 -1
1.45 2.67 1
0.56 0.78 -1
2.34 3.45 1
1.89 2.98 1
0.33 0.45 -1
3.67 4.32 1
1.12 0.34 -1
2.56 3.78 1
0.78 0.99 -1
1.34 2.45 1
3.23 4.56 1
0.23 0.45 -1
2.67 3.89 1
0.89 0.12 -1
1.56 3.45 1
0.98 1.45 -1
3.45 4.78 1
1.22 0.67 -1
2.78 3.56 1
0.45 0.56 -1
1.89 2.67 1
2.67 3.45 1
0.34 0.45 -1
1.12 2.34 1
0.56 0.67 -1
2.78 3.89 1
1.45 2.56 1
0.34 0.45 -1
3.45 4.56 1
1.12 0.34 -1
-0.38 0.56 -1
0.73 4.56 1
1.45 3.67 1
1.72 1.11 -1
3.33 4.44 1
0.05 0.66 -1
1.78 2.89 1
2.06 3.21 1
-0.19 0.42 -1
0.61 2.22 1
-0.05 0.78 -1
2.34 3.45 1
1.17 2.98 1
-0.28 0.33 -1
3.21 4.32 1
-1.58 -0.56 -1
-2.78 4.56 1
-1.45 3.67 1
-2.34 1.11 -1
-2.96 4.44 1
-2.53 0.66 -1
-1.84 2.89 1
-2.45 3.21 1
-2.01 0.42 -1
-2.64 2.22 1
-2.72 0.78 -1
-1.91 3.45 1
-2.37 2.98 1
-2.83 0.33 -1
-2.48 4.32 1
-1.98 -0.56 -1
-0.83 4.56 1
-0.65 3.67 1
-0.94 1.11 -1
-0.91 4.44 1
-1.53 0.66 -1
-0.85 2.89 1
-0.74 3.21 1
-0.99 0.42 -1
-0.76 2.22 1
-0.87 0.78 -1
-0.51 3.45 1
-0.73 2.98 1
-1.92 0.33 -1
-0.61 4.32 1