一、原理
将实例的特征向量(以二维为例)映射为空间中的一些点,如下图的实心点和空心点,它们属于不同的两类。SVM 的目的就是想要画出一条线,以“最好地”区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。
二、实现
1.引包
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import PolynomialFeatures,StandardScaler
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
2.定义函数
#非线性SVM分类,当degree为0表示线性
def PolynomialSVC(degree,C=1.0):
return Pipeline([
("poly",PolynomialFeatures(degree=degree)),#生成多项式
("std_scaler",StandardScaler()),#标准化
("linearSVC",LinearSVC(C=C))#最后生成svm
])
#绘制决策边界
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, cmap=custom_cmap)
#核函数
def PolynomialKernelSVC(degree,C=1.0):
return Pipeline([
("std_scaler",StandardScaler()),
("kernelSVC",SVC(kernel="poly")) # poly代表多项式特征
])
#高斯核函数
def RBFKernelSVC(gamma=1.0):
return Pipeline([
('std_scaler',StandardScaler()),
('svc',SVC(kernel='rbf',gamma=gamma))
])
3.月亮数据集
#使用生成的数据
x_moom, y_moom = datasets.make_moons()
#展示数据
plt.scatter(x_moom[y_moom==0,0],x_moom[y_moom==0,1])
plt.scatter(x_moom[y_moom==1,0],x_moom[y_moom==1,1])
plt.show()
#随机生成噪声点,random_state是随机种子,noise是方差
x_moom, y_moom = datasets.make_moons(noise=0.15,random_state=520)
#展示处理过后的数据
plt.scatter(x_moom[y_moom==0,0],x_moom[y_moom==0,1])
plt.scatter(x_moom[y_moom==1,0],x_moom[y_moom==1,1])
plt.show()
多项式拟合
#多项式
poly_svc_moom = PolynomialSVC(degree=5,C=10)
#拟合
poly_svc_moom.fit(x_moom,y_moom)
#打印权重和截距
print("权重w:",poly_svc_moom.named_steps['linearSVC'].coef_[0])
print("截距b:",poly_svc_moom.named_steps['linearSVC'].intercept_[0])
# 绘制决策边界
plot_decision_boundary(poly_svc_moom,axis=[-1.5,2.5,-1.5,2.5])
# 绘制原始数据
plt.scatter(x_moom[y_moom==0,0],x_moom[y_moom==0,1])
plt.scatter(x_moom[y_moom==1,0],x_moom[y_moom==1,1])
plt.show()
结果
权重w: [ 0.00000000e+00 -2.68881114e-01 -1.93434224e-01 -4.32431665e+00
-1.27622864e+00 1.12044138e-01 2.86142335e+00 -8.18291030e-01
5.40734568e-01 -9.34618896e-01 2.85214778e+00 1.03673531e+00
-1.22260779e+00 -1.75260078e-03 -8.60782048e-01 3.04529279e+00
7.81531082e-01 4.99785129e-01 -4.91386835e-01 -4.04710857e-01
-5.40394614e-01]
截距b: -0.34700847782477684
高斯核拟合
#高斯核处理 参数为1
rbf_svc_moom = RBFKernelSVC(1)
#拟合
rbf_svc_moom.fit(x_moom,y_moom)
#打印对偶系数以及截距
print("系数w:",rbf_svc_moom.named_steps['svc'].dual_coef_)
print("截距b:",rbf_svc_moom.named_steps['svc'].intercept_)
# 绘制决策边界
plot_decision_boundary(rbf_svc_moom,axis=[-1.5,2.5,-1.0,1.5])
# 绘制原始数据
plt.scatter(x_moom[y_moom==0,0],x_moom[y_moom==0,1])
plt.scatter(x_moom[y_moom==1,0],x_moom[y_moom==1,1])
plt.show()
结果
系数w: [[-1. -1. -1. -0.40295592 -1. -1.
-0.18341255 -1. -1. -1. -1. -1.
-0.40741147 -0.50289862 -1. -0.26412961 1. 1.
0.56356408 1. 1. 1. 0.64182852 0.93540944
1. 0.50279559 1. 0.65360387 0.29516456 0.16844209
1. 1. ]]
截距b: [-0.00446522]
4.鸢尾花数据集
iris = datasets.load_iris()
x_iris = iris.data
y_iris = iris.target
x_iris = x_iris [y_iris<2,:2] #只取y<2的类别,也就是0 1 并且只取前两个特征
y_iris = y_iris[y_iris<2] # 只取y<2的类别
# 分别画出类别0和1的点
plt.scatter(x_iris[y_iris==0,0],x_iris[y_iris==0,1])
plt.scatter(x_iris[y_iris==1,0],x_iris[y_iris==1,1])
plt.show()
多项式拟合
#多项式
poly_svc_iris = PolynomialSVC(degree=5,C=10)
#拟合
poly_svc_iris.fit(x_iris,y_iris)
#打印权重和截距
print("权重w:",poly_svc_iris.named_steps['linearSVC'].coef_[0])
print("截距b:",poly_svc_iris.named_steps['linearSVC'].intercept_[0])
# 绘制决策边界
plot_decision_boundary(poly_svc_iris,axis=[4,7.5,1,4.5]) # x,y轴都在-3到3之间
# 绘制原始数据
plt.scatter(x_iris[y_iris==0,0],x_iris[y_iris==0,1])
plt.scatter(x_iris[y_iris==1,0],x_iris[y_iris==1,1])
plt.show()
结果
权重w: [ 0. 1.20796725 -0.34684046 0.92506485 0.24563948 -0.42663654
0.67750728 0.36384265 -0.22308894 -0.4711197 0.46589838 0.28366651
-0.11284252 -0.38924762 -0.48646267 0.28920488 0.1681849 -0.0905382
-0.34010598 -0.44936597 -0.47998167]
截距b: 0.6436493839359197
高斯核拟合
#高斯核处理 参数为1
rbf_svc_iris = RBFKernelSVC(1)
#拟合
rbf_svc_iris.fit(x_iris,y_iris)
#打印对偶系数以及截距
print("系数w:",rbf_svc_iris.named_steps['svc'].dual_coef_)
print("截距b:",rbf_svc_iris.named_steps['svc'].intercept_)
# 绘制决策边界
plot_decision_boundary(rbf_svc_iris,axis=[4,7.5,1,4.5])
# 绘制原始数据
plt.scatter(x_iris[y_iris==0,0],x_iris[y_iris==0,1])
plt.scatter(x_iris[y_iris==1,0],x_iris[y_iris==1,1])
plt.show()
结果
系数w: [[-0.76759127 -0.47423075 -0.2011925 -0.77968419 -0.31804531 -0.50982507
-1. -0.80508958 -0.35824411 -0.74252356 -1. 0.61031154
1. 0.79408519 0.70381878 0.74512265 0.18015706 0.07385213
0.47768741 1. 1. 0.37139158]]
截距b: [0.0900694]
三、总结
通过sklearn实现SVM算法
四、参考
https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html#sklearn.svm.LinearSVC
https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC