SVM 支撑向量机
support Vector Machine
逻辑回归:
但是当决策边界不唯一时,
定义一个概率函数,求损失函数。然后求出决策边界
我们希望的决策边界是距离红色,蓝色最近的点都尽可能的远,而且还能很好的分别红色和蓝色两种类别的数据点
hard svm
假设我们的数据是线性可分的,用 hard svm
svm求得的是 margin 最大化
margin=2d
svm也就要d 最大化
点到直线的距离:
点(x,y) 到Ax+By +C =0 的距离
∣
A
x
+
B
y
+
C
∣
A
2
+
B
2
\frac{|Ax+By+C|}{\sqrt{A^2+B^2}}
A2+B2∣Ax+By+C∣
拓展到n 维:
原来我们都是
θ
T
x
b
=
0
\theta^Tx_b = 0
θTxb=0
但是我们从上面可以二维平面看到 分母和截距C没有关系
所以式子变成
W
T
x
+
b
=
0
W^Tx+b =0
WTx+b=0
所以 就是
∣
w
T
x
+
b
∣
∣
∣
w
∣
∣
\frac{|w^Tx+b|}{||w||}
∣∣w∣∣∣wTx+b∣
∣
∣
w
∣
∣
=
w
1
2
+
w
2
2
+
w
3
2
+
.
.
.
+
w
n
2
||w|| = \sqrt{w^2_1+w^2_2+w^2_3+...+w^2_n}
∣∣w∣∣=w12+w22+w32+...+wn2
上面的 d是一个正数,
∣
∣
w
∣
∣
||w||
∣∣w∣∣也是一个正数,所以
对上面的变量进行改名,
可以上图右边的两个式子合二为一,就变成了
y
i
(
w
T
x
i
+
b
)
≥
1
y^i(w^Tx^i+b) \geq1
yi(wTxi+b)≥1
所以算法就变成了
m
i
n
1
2
∣
∣
w
2
∣
∣
min\frac{1}{2}||w^2||
min21∣∣w2∣∣的最优化问题
但是要满足
y
i
(
w
T
x
i
+
b
)
≥
1
y^i(w^Tx^i+b) \geq1
yi(wTxi+b)≥1
有条件的最优化问题
soft svm
很多时候数据不是线性可分的,就要使用 soft svm
但是当数据变成上图 ,就无法进行处理了,·我们需要有一定容错的svm,增加一个宽松量
我们可以给 其加上一个系数,来平衡这两个的比例
如果C在0,1之间。我们主要优化前面的
如果C特别大的化,我们要主要优化后面的式子
scikit-learn 中的svm
使用 svm算法和使用knn算法一样,都要先做数据标准化处理’
因为svm 是计算margin,涉及距离,如果特征数据的量纲不同则会有问题
import numpy as np
import matplotlib.pyplot as plt
# 使用鸢尾花数据集
from sklearn import datasets
iris = datasets.load_iris()
X= iris.data
y = iris.target
X = X[y <2,:2]
y =y[y<2]
plt.scatter(X[y==0,0], X[y==0,1], color='red')
plt.scatter(X[y==1,0], X[y==1,1], color='blue')
plt.show()
绘制·svm支撑点
def plot_svc_decision_boundary(model,axis):
x0,x1 = np.meshgrid(
np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)),
np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100))
)
x_new = np.c_[x0.ravel(),x1.ravel()]
y_predict = model.predict(x_new)
zz = y_predict.reshape(x0.shape)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
plt.contourf(x0,x1,zz,cmap=custom_cmap)
w = model.coef_[0]
b = model.intercept_[0]
plot_x = np.linspace(axis[0], axis[1],200)
up_y = -w[0]/w[1] * plot_x -b/w[1] + 1/w[1]
down_y = -w[0]/w[1] * plot_x -b/w[1] - 1/w[1]
up_index = (up_y >=axis[2]) & (up_y <= axis[3])
down_index = (down_y >= axis[2]) & (down_y <= axis[3])
plt.plot(plot_x[up_index], up_y[up_index],color='black')
plt.plot(plot_x[down_index], down_y[down_index],color='black')
当C=1e9时
from sklearn.preprocessing import StandardScaler
standardScaler = StandardScaler()
standardScaler.fit(X)
X_standard = standardScaler.transform(X)
from sklearn.svm import LinearSVC
svc = LinearSVC(C=1e9)
svc.fit(X_standard, y)
plot_decision_boundary(svc, axis=[-3,3,-3,3])
plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
plt.scatter(X_standard[y==1,0],X_standard[y==1,1])
plt.show()
当C=0.01时
svm中使用多项式特征
创建数据
from sklearn import datasets
X,y = datasets.make_moons()
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
对数据增加噪音
X,y = datasets.make_moons(noise=0.15, random_state=666)
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
使用多项式svm
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
def PolynomialSVC(degree,C=1.0):
return Pipeline(
[
('poly', PolynomialFeatures(degree=degree)),
('std_scaler', StandardScaler()),
('linearSVC',LinearSVC(C=C))
])
poly_svc = PolynomialSVC(degree=3)
poly_svc.fit(X,y)
plot_decision_boundary(poly_svc, axis=[-1.5,2.5,-1,1.5])
plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
plt.scatter(X_standard[y==1,0],X_standard[y==1,1])
plt.show()
使用多项式核函数的svm
from sklearn.svm import SVC
def PolynomialKernelSVC(degree,C=1):
return Pipeline(
[
('std_scaler',StandardScaler()),
('KernelSVC',SVC(kernel='poly',degree=degree,C=C))
]
)
poly_kernel_svc = PolynomialKernelSVC(degree=3)
poly_kernel_svc.fit(X,y)
plot_decision_boundary(poly_kernel_svc, axis=[-1.5,2.5,-1,1.5])
plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
plt.scatter(X_standard[y==1,0],X_standard[y==1,1])
plt.show()
什么是核函数
svm 的本质
其中的K叫核函数
对于二次多项式的核函数:
高斯核函数 RBF核
将每一样本点映射到一个无穷维的特征空间
多项式特征: 依靠升维使得原本新型不可分的数据线性可分
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-4,5,1)
y = np.array((X>=-2) & (X<=2), dtype='int')
plt.scatter(x[y==0],[0]*len(x[y==0]))
plt.scatter(x[y==1],[0]*len(x[y==1]))
plt.show()
def gaussian(x,l):
gamma = 1
return np.exp(-gamma * (x-l)**2)
l1,l2 = -1,1
X_new =np.empty((len(x),2))
for i,data in enumerate(x):
X_new[i,0] = gaussian(data,l1)
X_new[i,1] = gaussian(data, l2)
plt.scatter(X_new[y==0,0],X_new[y==0,1])
plt.scatter(X_new[y==1,0],X_new[y==1,1])
plt.show()
高斯核函数中的gamma
gamma越大,高斯分布越窄
gamma越小,高斯分布越宽
测试数据
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
X,y = datasets.make_moons(noise=0.15, random_state=666)
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
创建RBF svm对象
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
def RBFKernelSVC(gamma=1):
return Pipeline([
('std_scaler',StandardScaler()),
('svc',SVC(kernel='rbf',gamma=gamma))
])
# 画图
def plot_decision_boundary(model,axis):
x0,x1 = np.meshgrid(
np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)),
np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100))
)
x_new = np.c_[x0.ravel(),x1.ravel()]
y_predict = model.predict(x_new)
zz = y_predict.reshape(x0.shape)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
plt.contourf(x0,x1,zz,cmap=custom_cmap)
def get_RBF_SVM_plot(gamma=1)
svc = RBFKernelSVC(gamma=gamma)
svc.fit(X,y)
plot_decision_boundary(svc, axis=[-1.5,2.5,-1,1.5])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
当 gamma=1时:
当 gamma=100时
当gamma=10时
当 gamma=0.5时
当gamma=0.1时
gamma越大。就会出现过拟合,
gamma越小,就会出现欠拟合
svm 思路解决回归问题
分类问题是在margin中值越小越好,
回归问题是在margin 中,包含的点越多越好,然后取中间的直线
在scikit-learn 中使用 svm 解决回归问题
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
boston = datasets.load_boston()
X = boston.data
y = boston.target
from sklearn.model_selection import train_test_split
X_train,X_test, y_train,y_test = train_test_split(X,y, random_state=666)
from sklearn.svm import LinearSVR
# from sklearn.svm import SVR # 可以使用 SVR ,也可以使用LinearSVR ,和上面一样
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
def StandardLinearSVR(epsilon=0.1):
return Pipeline([
('std_scaler',StandardScaler()),
('linearSVR',LinearSVR(epsilon=epsilon))
])
svr = StandardLinearSVR()
svr.fit(X_train,y_train)
svr.score(X_test, y_test) # 0.6357705223702143
# 这里的值比较低。因为有很多的 超参数可以调整,