文章目录
一、支持向量机的概念
支持向量机(Support Vector Machine, SVM) 是一类按监督学习(supervised learning)方式对数据进行二元分类的广义线性分类器(generalized linearclassifier),其决策边界是对学习样本求解的最大边距超平面(maximum-margin hyperplane)。
SVM:使用铰链损失函数(hinge loss)计算经验风险(empirical risk)并在求解系统中加入了正则化项以优化结构风险(structural risk),是一个具有稀疏性和稳健性的分类器。
SVM可以通过核方法(kernel method)进行非线性分类,是常见的核学习(kernel learning)方法之一
二、LinearSVC(C)方式实现分类
使用Jupyter Notebook编辑器
在Anaconda3的文件夹里找到Jupyter的,打开它。
它会出现一个控制台,也就是写入数据的后台,需要保持后台开启。然后打开一个网页用于编辑
在网页点击NEW选择python3
开始编辑
制作原始数据
在编辑框粘贴如下代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X = iris.data
y = iris.target
X = X [y<2,:2] # 只取y<2的类别,也就是0 1 并且只取前两个特征
y = y[y<2] # 只取y<2的类别
# 分别画出类别 0 和 1 的点
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()
点击运行
结果如下
这时未经标准化的原始数据点分布,接下来我们需要编写代码将之分类以及各种处理
训练模型
添加如下代码
# 标准化
standardScaler = StandardScaler()
standardScaler.fit(X)
# 计算训练数据的均值和方差
X_standard = standardScaler.transform(X) # 再用 scaler 中的均值和方差来转换 X ,使 X 标准化
svc = LinearSVC(C=1e9) # 线性 SVM 分类器
svc.fit(X_standard,y) # 训练svm
运行结果如下
其中C 值是控制正则项的重要程度,C 越小,容错空间越大
绘制决策边界
导入一个 ListedColormap 包
from matplotlib.colors import ListedColormap # 导入 ListedColormap 包
添加如下代码
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)
custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
plt.contourf(x0, x1, zz, cmap=custom_cmap) #绘制决策边界
plot_decision_boundary(svc,axis=[-3,3,-3,3]) # x,y轴都在-3到3之间
# 绘制原始数据
plt.scatter(X_standard[y==0,0],X_standard[y==0,1],color='red')
plt.scatter(X_standard[y==1,0],X_standard[y==1,1],color='blue')
plt.show()
运行结果如下
决策边界绘制出来了,再改变c值看看会发生什么变化
设置超参数 C 值
添加如下代码
svc2 = LinearSVC(C=0.01)
svc2.fit(X_standard,y)
plot_decision_boundary(svc2,axis=[-3,3,-3,3]) # x,y轴都在-3到3之间
# 绘制原始数据
plt.scatter(X_standard[y==0,0],X_standard[y==0,1],color='red')
plt.scatter(X_standard[y==1,0],X_standard[y==1,1],color='blue')
plt.show()
运行结果如下,可以看到左下红点分类是错误的。
分类后的内容基础上添加上下边界
修改定义的函数如下
def plot_svc_decision_boundary(model, axis):
x0, x1 = np.meshgrid(
np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),# 600个,影响列数
np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),# 600个,影响行数
)
# x0 和 x1 被拉成一列,然后拼接成360000行2列的矩阵,表示所有点
X_new = np.c_[x0.ravel(), x1.ravel()] # 变成 600 * 600行, 2列的矩阵
y_predict = model.predict(X_new) # 二维点集才可以用来预测
zz = y_predict.reshape(x0.shape) # (600, 600)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)
w = model.coef_[0]
b = model.intercept_[0]
index_x = np.linspace(axis[0], axis[1], 100)
# f(x,y) = w[0]x1 + w[1]x2 + b
# 1 = w[0]x1 + w[1]x2 + b 上边界
# -1 = w[0]x1 + w[1]x2 + b 下边界
y_up = (1-w[0]*index_x - b) / w[1]
y_down = (-1-w[0]*index_x - b) / w[1]
x_index_up = index_x[(y_up<=axis[3]) & (y_up>=axis[2])]
x_index_down = index_x[(y_down<=axis[3]) & (y_down>=axis[2])]
y_up = y_up[(y_up<=axis[3]) & (y_up>=axis[2])]
y_down = y_down[(y_down<=axis[3]) & (y_down>=axis[2])]
plt.plot(x_index_up, y_up, color="black")
plt.plot(x_index_down, y_down, color="black")
plot_svc_decision_boundary(svc, axis=[-3, 3, -3, 3])
plt.scatter(X_standard[0:y2,0], X_standard[0:y2,1],color='red')
plt.scatter(X_standard[y2:y1,0], X_standard[y2:y1,1],color='blue')
plt.show()
运行结果
修改c值
plot_svc_decision_boundary(svc2, axis=[-3, 3, -3, 3])
plt.scatter(X_standard[0:y2,0], X_standard[0:y2,1],color='red')
plt.scatter(X_standard[y2:y1,0], X_standard[y2:y1,1],color='blue')
plt.show()
运行结果
三、总结
可以得知常数C越大,容错空间越小,上下边界较近;常数C越小,容错空间越大,上下边界越远。