SVM数学理论:
如图所示:我们的目标是最大化margin,而margin = 2d
,so 最大化margin ,就是要最大化d。
点到直线的距离拓展到n维平面:
下面介绍 Soft Margin SVM :
C 越大, 越是不允许犯错,当C无穷大的时候,严格不允许犯错,也就是SVM分类一定要全部分对
反之则反。 hard margin svm 就是那类严格不允许犯错的。
下面用sklearn 来实践一下SVM:
# iris数据集
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] # 只使用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和KNN算法一样的,首先要对数据进行标准化处理:
from sklearn.preprocessing import StandardScaler
standardScaler = StandardScaler()
standardScaler.fit(X)
X_standard = standardScaler.transform(X)
当我们的C取非常大的时候,也就是分类非常严格,进行训练:
from sklearn.svm import LinearSVC
svc = LinearSVC(C=1e9)
svc.fit(X_standard,y)
下面我们用一个函数进行边界划分:
def plot_decision_boundary(model, axis):
x0, x1 = np.meshgrid(
np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
)
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, linewidth=5, cmap=custom_cmap)
边界如下:
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设置小一点,再试试:
svc2 = LinearSVC(C=0.01)
svc2.fit(X_standard,y)
plot_decision_boundary(svc2, 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变小了,分类也随之不严格了。
下面介绍在SVM中使用多项式特征
为啥子使用多项式,专门是为了分类一些非线性的数据,下面举个栗子,我们用moons数据集:
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()
这个情况下,我们想用多条直线进行分类,明显是不可以,这时候只能用多项式:
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[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
多项式进行分类,其实sklearn中多项式核函数也能实现:
from sklearn.svm import SVC
def PolynomialKernelSVC(degree, C=1.0):
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[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
下面是多项式核函数理论基础
核函数的作用就是,把传入的x,y进行K(x,y)变换,变成
x
i
,
y
i
x^i , y^i
xi,yi ,转成2,3…n次项,上图是2次项。
K
(
x
,
y
)
=
(
x
∗
y
+
c
)
d
K(x,y) = (x*y+c)^d
K(x,y)=(x∗y+c)d
高斯核函数
举一个例子,对上面的例子,如何把红色和蓝色分离,现在它们在一维平面,如果想要分离,高斯核函数通过高斯公式,映射到二维,如上所示。
Scikit-learn中使用RBF核(也就是高斯核函数)
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()
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
def RBFKernelSVC(gamma=1.0):
return Pipeline([
("std_scatter",StandardScaler()),
("svc",SVC(kernel="rbf",gamma=gamma))
])
svc = RBFKernelSVC(gamma=1.0)
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取100时候(这里的gamma是高斯函数里面那个r):
svc100 = RBFKernelSVC(gamma=100.0)
svc100.fit(X,y)
明显过拟合了~,调节gamma的过程就是调节超参数,找出最适合的参数。
下面讨论的问题,SVM回归问题
上面我们只讨论分类的问题,其实之前我们讨论的很多算法,既可以实现分类,同样是可以回归。
下面用波士顿房价来做个栗子:
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)
rom sklearn.svm import LinearSVR
from sklearn.svm import SVR
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)
SVM的学习笔记到此完毕,下面继续总结。