数据集在作业一
支持向量机
支持向量机(Support Vector Machine,SVM) 是一种经典的监督学习算法,主要用于分类任务(也可扩展到回归任务),其核心思想是:在特征空间中找到一个最优超平面,将不同类别的样本分割开,且使该超平面与两侧最近样本点的距离(即 “间隔”)最大。
由“使该超平面与两侧最近样本点的距离(即 “间隔”)最大”可知,该超平面的方向和位置是确定的。
算法流程
1.调用sklearn中的svm构建所需要的模型
2.进行模型训练、
3.进行模型测试
代码
线性分类
读取数据及可视化
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
from sklearn import svm
# 线性分类
# 读取数据
data=loadmat('ex6data1.mat')
X=data['X']
y=data['y']
# print(X.shape,y.shape)(51, 2) (51, 1)
# 可视化
def data_plot(X,y):
plt.scatter(X[:,0],X[:,1],c=y.flatten())
plt.xlabel('x1')
plt.ylabel('x2')
# plt.show()
决策边界,把已有的数据均匀分成500个区域,然后用等高线图画出决策边界
def plot_decision_boundary(model,X):
x_min,x_max=X[:,0].min()*1.1,X[:,0].max()*1.1
y_min,y_max=X[:,1].min()*1.1,X[:,1].max()*1.1
xx,yy=np.meshgrid(np.linspace(x_min,x_max,500),np.linspace(y_min,y_max,500))
Z=model.predict(np.c_[xx.ravel(),yy.ravel()])
Z=Z.reshape(xx.shape)
plt.contour(xx,yy,Z,cmap=plt.cm.Spectral)
plt.xlabel('x1')
plt.ylabel('x2')
这里的model就是我们要训练的分类模型。
-
np.linspace
生成从最小值到最大值的等间隔数值,这里各生成 500 个点 -
np.meshgrid
将这些点转换为网格矩阵,xx
和yy
都是形状为 (500, 500) 的矩阵,分别代表网格中每个点的 x 坐标和 y 坐标 -
xx.ravel()
和yy.ravel()
将二维网格矩阵展平为一维数组 -
np.c_[]
将两个一维数组按列组合,形成形状为 (250000, 2) 的测试点矩阵 -
使用训练好的模型对所有网格点进行预测,得到每个点的类别
使用 contour 函数绘制轮廓线,不同的类别区域会被区分开来,这些轮廓线就是模型的决策边界
通过调用sklearn.svm.SVC()创建支持向量机模型
models=[svm.SVC(C=c,kernel='linear')for c in [1,100]]
clfs=[model.fit(X,y.ravel()) for model in models]
score=[model.score(X,y) for model in clfs]
# print(score)[0.9803921568627451, 1.0]
这里的c是惩罚系数,是软间隔 SVM 中的关键参数,越大表示对误分类的惩罚越严厉
-
当
C
较小时:模型允许更多误分类(松弛变量更大),更注重最大化间隔,决策边界更 “宽松”,可能欠拟合(对训练数据拟合不足)。 -
当
C
较大时:对误分类的惩罚更严厉,模型会尽量减少误分类,甚至为了正确分类少数异常点而让间隔变窄,决策边界更 “陡峭”,可能过拟合(过度拟合训练数据中的噪声或异常点)。
model.fit()是对于传入数据集进行训练
SVM的损失函数比较特殊,它的优化目标为
前者是为了最小化间隔,后者是为了减少误分类。
画出决策边界
def plot():
titles=['C=1','C=100']
for model,title in zip(clfs,titles):
data_plot(X, y)
plot_decision_boundary(model,X)
plt.title(title)
plt.show()
plot()
非线性分类
高斯核函数
前面我们提到了处理非线性的方法之一是利用高阶特征项,这里我们可以使用另一个方法来达到同样的效果,我们可以把高斯核函数理解成指数函数,通过泰勒级数展开式来理解。
这里我们就可以避免高纬度计算了。
def gaussKernel(x1, x2, sigma):
return np.exp(-(x1 - x2) ** 2).sum() / (2 * sigma ** 2)
读取数据及可视化
data_2=loadmat('ex6data2.mat')
X2=data_2['X']
y2=data_2['y']
# print(X.shape,y.shape)(863, 2) (863, 1)
# 可视化
# data_plot(X2,y2)
# plt.show()
通过调用sklearn.svm.SVC()创建支持向量机模型
sigma=0.1
gamma=1/(2*sigma**2)
model=svm.SVC(C=1,kernel='rbf',gamma=gamma)
model.fit(X2,y2.ravel())
# plot_decision_boundary(model,X2)
# plt.show()
如何找最佳权值
下面我们的目的是找出最佳权值,使得分类效果最好
读入数据及可视化
# 读入数据
data_3=loadmat('ex6data3.mat')
X3=data_3['X']
y3=data_3['y']
# 交叉验证集
X_val=data_3['Xval']
y_val=data_3['yval']
# print(X.shape,y.shape)(51, 2) (51, 1)
# 可视化
data_plot(X3,y3)
plt.show()
通过调用sklearn.svm.SVC()创建支持向量机模型
# 通过调用sklearn.svm.SVC()创建支持向量机模型
Cvalues = (0.01, 0.03, 0.1, 0.3, 1., 3., 10., 30.) # 权重C的候选值
sigmavalues = Cvalues # 核函数参数的候选值
best_pair, best_score = (0, 0), 0 # 最佳的(C,sigma)权值 ,决定系数(R2)
for c in Cvalues:
for sigma in sigmavalues:
gamma=1/(2*sigma**2)
model=svm.SVC(C=c,kernel='rbf',gamma=gamma)
model.fit(X3,y3.ravel())
score=model.score(X_val,y_val)
if score > best_score:
best_score = score
best_pair = (c, sigma)
print('最优(C, sigma)权值:', best_pair, '决定系数:', best_score)
用确定好的权重再重新声明一次支持向量机
model = svm.SVC(C=1, kernel='rbf', gamma=np.power(0.1, -2.) / 2)
# 用确定好的权重再重新声明一次支持向量机
model.fit(X3, y3.flatten())
plot_decision_boundary(model, X3)
plt.show()
总结
读入数据——构建模型(确定线性还是非线性)——如果是非线性,可以找一下最佳权值——训练模型——测试