SVM算法学习实践(二)

SVM算法入门学习实践

1、SVM原理与线性不可分

支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。SVM的算法核心是找到几何间距,找到几何间距margin,处理线性可分问题,对应的非线性问题处理方法是:非线性VM,由于前面我已经讲解过SVM算法,这里不过多介绍。具体请参考上一篇学习的博客

1.问题引入

在实际应用中,大多情况下数据并不是线性可分的,这个时候满足这样条件的超平面根本就不存在,而本文将主要针对了解SVM算法在解决线性不可分类时,对特征集进行多项式、核函数转换(升维)将其转换为线性可分类问题的思想。

所以就有了核函数。

核函数

核函数特点:

  1. 不需要每次都具体计算出原始样本点映射的新的无穷维度的样本点,直接使用映射后的新的样本点的点乘计算公式即可;
  2. 减少计算量
  3. 减少存储空间
  4. 一般将原始样本变形,通常是将低维的样本数据变为高维数据,存储高维数据花费较多的存储空间;使用核函数,不用考虑原来样本改变后的样子,也不用存储变化后的结果,只需要直接使用变化的结果进行运算并返回运算结果即可;
  5. 核函数的方法和思路不是 SVM 算法特有,只要可以减少计算量和存储空间,都可以设计核函数方便运算;
  6. 对于比较传统的常用的机器学习算法,核函数这种技巧更多的在 SVM 算法中使用;

2. 多项式核函数:

代码格式:

from sklearn.svm import SVC
svc = SVC(kernel = 'ploy')

实现思路:

设计一个函数(K(x,x)),传入原始样本(x(i)、xi),返回添加了多项式特征后的新样本的计算结果(x’(i) , xi) ;

先对x、xj添加多项式,得到: xi)、xi),再进行运算: x(i) .x(i) ;

3.高斯/RBF核函数:

1636696348600

高斯核函数也叫RBF核(Radia Basis Function Kernel),核函数依赖升维使得原本线性不可分的数据变得线性可分。高斯核本质是在衡量样本和样本之间的“相似度”,在一个刻画“相似度”的空间中,让同类样本更好的聚在一起,进而线性可分。

思路:

业务的目的是样本分类,采用的方法:按一定规律统一改变样本的特征数据得到新的样本,新的样本按新的特征数据能更好的分类,由于新的样本的特征数据与原始样本的特征数据呈一定规律的对应关系,因此根据新的样本的分布及分类情况,得出原始样本的分类情况。

应该是试验反馈,将样本的特征数据按一定规律统一改变后,同类样本更好的凝聚在了一起;

高斯核和多项式核干的事情截然不同的,如果对于样本数量少,特征多的数据集,高斯核相当于对样本降维;

高斯核的任务:找到更有利分类任务的新的空间。

2.重新使用代码完成之前的练习

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.引入数据进行分类

1月亮数据集

#使用生成的数据
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()

1636696600587

#使用多项式核函数进行拟合
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()

1636697344419

#再使用高斯核处理 参数为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()

1636697409240

2. 鸢尾花数据集

1,先导入数据看一下

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()

1636697462319

#多项式
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()

1636697505983

同样再使用高斯核函数

#高斯核处理 参数为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()

1636697562782

3、总结

通过这次再次实验将这两个数据集进行分类了解了关于实际应用中,数据线性可不分的情况下,通过核函数将数据进行升维变换再进行更加精准的分类

posted @ 2021-11-12 14:42  Sioalq  阅读(135)  评论(0编辑  收藏  举报
Live2D