基本思想
- SVM(Support Vector Machine)分类算法,在工业界、学术界均广泛使用,尤其对于小数据集,效果往往比神经网络要好;
- 基本思想是:找一个最大间距的线性分割超平面,将所有的样本正确分类,提高分类算法的鲁棒性(对噪声的适应能力)
- 假设此时的正负样本及分割超平面如下:
分割超平面: w ⃗ T x ⃗ + b = 0 \vec w^T \vec x +b = 0 wTx+b=0 其中 w ⃗ = ( w 1 w 2 ) \vec{w} = \begin{pmatrix} w_1 \\ w_2 \\ \end{pmatrix} w=(w1w2)
x ⃗ = ( x ( 1 ) x ( 2 ) ) \vec{x}=\begin{pmatrix} x^{(1)} \\ x^{(2)} \\ \end{pmatrix} x=(x(1)x(2))
与上虚线相切的点
x
⃗
0
\vec x_0
x0,到分割超平面的距离公式
d
=
∣
w
1
x
0
(
1
)
+
w
2
x
0
(
2
)
+
b
∣
w
1
2
+
w
2
2
=
1
w
1
2
+
w
2
2
d=\frac { \left |w_1x_0^{(1)}+w_2x_0^{(2)}+b \right |} {\sqrt {w_1^2 + w_2^2 }} = \frac {1} {\sqrt {w_1^2 + w_2^2 }}
d=w12+w22
w1x0(1)+w2x0(2)+b
=w12+w221
所以求上下虚线间距最大,就求
2
∗
d
2*d
2∗d的最大值,即
w
1
2
+
w
2
2
2
=
∣
∣
w
⃗
∣
∣
2
\frac {\sqrt {w_1^2 + w_2^2 }} {2} = \frac {\left || \vec{w} \right ||} {2}
2w12+w22=2∣∣w∣∣的最小值,且对于所有的样本
x
⃗
i
\vec x_i
xi同时满足不等式约束:
y
i
(
w
⃗
T
x
⃗
i
+
b
)
≥
1
y_i(\vec w^T \vec x_i+b)\geq 1
yi(wTxi+b)≥1
硬间隔
- 找一个最大间距的线性分割超平面,将所有的样本正确分类;
- 优化目标为
- 最大间距,求 ∣ ∣ w ⃗ ∣ ∣ 2 2 \frac {\left || \vec w \right ||^2} {2} 2∣∣w∣∣2 的最小值,为了方便计算,这里取平方;
- 正确分类, y i ( w ⃗ T x ⃗ i + b ) ≥ 1 y_i(\vec w^T \vec x_i+b)\geq 1 yi(wTxi+b)≥1
软间隔
- 找一个最大间距的线性分割超平面,
尽量
将所有的样本正确分类; - 优化目标为
- 最大间距,求 ∣ ∣ w ⃗ ∣ ∣ 2 2 + C ∑ i N ϵ i \frac {\left || \vec w \right ||^2} {2} + C\sum_i^N \epsilon_i 2∣∣w∣∣2+Ci∑Nϵi ϵ i ≥ 0 \epsilon_i \geq 0 ϵi≥0 的最小值,为了方便计算,这里模取平方;
- 正确分类, y i ( w ⃗ T x ⃗ i + b ) ≥ 1 − ϵ i y_i(\vec w^T \vec x_i+b)\geq 1 - \epsilon_i yi(wTxi+b)≥1−ϵi
硬间隔的损失
- 带有不等式约束的损失函数,采用拉格朗日乘子式;
核函数
以上数据再加入一个
x
2
x^2
x2平方的维度,即可在二维空间线性可分;
sklearn中的SVM
代码:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
#读取csv 数据
df = pd.read_csv("samples.txt",header=None,names=["x","y","label"])
print(df.head())
#分片选择样本实例,标记
X,y = df.iloc[:,:-1].values,df["label"].values
X0 = X[y==0]
X1 = X[y==1]
#画出样本点
#设置显示中文
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
#训练SVM分类模型
from sklearn.svm import SVC
#使用linear
linear_model = SVC(C=1.0,kernel="linear")
poly_model = SVC(C=1.0,kernel="poly",degree=3)
rbf1_model = SVC(C=1.0,kernel="rbf",gamma=0.5)
rbf2_model = SVC(C=1.0,kernel="rbf",gamma=0.1)
models = [linear_model,poly_model,rbf1_model,rbf2_model]
titles = ["线性核","三阶多项式核","高斯核$\gamma = 0.5$","高斯核$\gamma = 0.1$"]
#生成网格点
x1_min,x2_min = X.min(axis=0)
x1_max,x2_max =X.max(axis=0)
x1_range = np.linspace(x1_min-1,x1_max+1,100)
x2_range = np.linspace(x2_min-1,x2_max+1,100)
#张成网格
xx1,xx2 = np.meshgrid(x1_range,x2_range)
#组织成样本点
xx = np.c_[xx1.ravel(),xx2.ravel()]
#遍历模型,训练,画出决策线
for idx,model in enumerate(models):
model.fit(X,y)
#预测网格点
y_pred = model.predict(xx)
#画子图
plt.subplot(2,2,idx+1)
plt.subplots_adjust(left=0.1,right=1,top=1,bottom=0.1,wspace=0.5,hspace=1.2)
#画点
plt.scatter(X0[:,0],X0[:,1],s=80,c="r",edgecolors=None,marker="s",label="0类")
plt.scatter(X1[:,0],X1[:,1],s=80,c="b",edgecolors=None,marker="^",label="1类")
plt.title(titles[idx],fontsize=20)
plt.xlabel("x 轴",fontsize=20)
plt.ylabel("y 轴",fontsize=20)
plt.grid(linestyle="-")
plt.legend(loc="upper right",frameon=True,framealpha=0.3)
#画决策线
plt.contour(xx1,xx2,y_pred.reshape(xx1.shape),cmap="cool")
plt.show()