作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文网址:https://blog.csdn.net/HiWangWenBing/article/details/123840378
目录
前言:
scikit-learn支持多种不同的核函数,实现对线性不可分数据的分类,本文展现不同核函数的效果。
第1步骤:导入库
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
#from sklearn.svm import SVC 两者都可以
from sklearn import svm
from sklearn.datasets import make_circles, make_moons, make_blobs,make_classification
第2步骤:四种不同的数据集
# 创建四种不同的非线性数据集
n_samples = 100
# n_features:特征数,
# n_informative:带信息的特征数,
# n_redundant:不带信息的特征数
datasets = [
make_moons(n_samples=n_samples, noise=0.2, random_state=0),
make_circles(n_samples=n_samples, noise=0.2, factor=0.5, random_state=1),
make_blobs(n_samples=n_samples, centers=2, random_state=4),#分簇的数据集
make_classification(n_samples=n_samples,n_features = 2,n_informative=2,n_redundant=0, random_state=5)
]
#四个数据集分别是什么样子呢?
for X,Y in datasets:
plt.figure(figsize=(5,4))
plt.scatter(X[:,0],X[:,1],c=Y,s=50,cmap="rainbow")
第3步骤:四种不同的核函数
3.1 模型训练与可视化
Kernel = ["linear","poly","rbf","sigmoid"]
# 四个数据集,每个数据集可视化一行
nrows=len(datasets)
# 四个核函数,每个核函数可视化一列
# + 1:用于显示原始的数据集
ncols=len(Kernel) + 1
# 构建 4 * 5 = 20个子图
fig, axes = plt.subplots(nrows, ncols,figsize=(20,16))
#第一层循环:在不同的数据集中循环
# [*enumerate(datasets)] == list(enumerate(datasets))# enumerate、map、zip都可以这样展开
# index,(X,Y) = [(索引, array([特矩阵征X],[标签Y]))]
# X = [X1, X2]
# Y = 0 或1 标签
for ds_cnt, (X,Y) in enumerate(datasets):
ax = axes[ds_cnt, 0]
#在图像中的第一列,放置原数据的分布图
if ds_cnt == 0:
ax.set_title("Input data")
ax.scatter(X[:, 0], X[:, 1], c=Y, zorder=10, cmap=plt.cm.Paired,edgecolors='k')
ax.set_xticks(())
ax.set_yticks(())
#第二层循环:在不同的核函数中循环
#从图像的第二列开始,一个个填充分类结果
for est_idx, kernel in enumerate(Kernel):
#1. 定义子图位置
ax = axes[ds_cnt, est_idx + 1]
#2. 根据核函数不同,建立不同的模型,并进行拟合
clf = svm.SVC(kernel=kernel, gamma=2).fit(X, Y)
#3. 统计模型分数
score = clf.score(X, Y)
#4. 绘制图像本身分布的散点图
ax.scatter(X[:, 0], X[:, 1], c=Y
,zorder=10
,cmap=plt.cm.Paired,edgecolors='k')
#5. 绘制支持向量
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=50,
facecolors='none', zorder=10, edgecolors='red')# facecolors='none':透明的
#6. 绘制图形
#6.1 构建网格
x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
#np.mgrid,合并了我们之前使用的np.linspace和np.meshgrid的用法
#一次性使用最大值和最小值来生成网格
#表示为[起始值:结束值:步长]
#如果步长是复数,则其整数部分就是起始值和结束值之间创建的点的数量,并且结束值被包含在内
XX, YY = np.mgrid[x_min:x_max:200j, y_min:y_max:200j]
#np.c_,类似于np.vstack的功能
Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()]).reshape(XX.shape)
#6.2 填充等高线不同区域的颜色
ax.pcolormesh(XX, YY, Z > 0, cmap=plt.cm.Paired)
#6.3 绘制等高线
ax.contour(XX, YY, Z, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'],
levels=[-1, 0, 1])
#6.4 设定坐标轴为不显示
ax.set_xticks(())
ax.set_yticks(())
#6.5 将标题放在第一行的顶上
if ds_cnt == 0:
ax.set_title(kernel)
#6.6 为每张图添加分类的分数
ax.text(0.95, 0.06, ('%.2f' % score).lstrip('0')
, size=15
, bbox=dict(boxstyle='round', alpha=0.8, facecolor='white')
#为分数添加一个白色的格子作为底色
, transform=ax.transAxes #确定文字所对应的坐标轴,就是ax子图的坐标轴本身
, horizontalalignment='right' #位于坐标轴的什么方向
)
plt.tight_layout()
plt.show()
3.2 效果图比较
从上图可以看出:
(1)对于线性可分数据或接近线性可分数,使用线性或poly多项式核函数比较合适,rbf效果虽好,但容易过拟合,泛化能力不如线性可分。
(2)对于线性不可分数据,使用使用poly和rbf,rbf的效果更好。
simoid看不出来有什么优势。
(3)不同的数据分布,选用不同的模型,才能得到性能的最佳。
作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文网址:https://blog.csdn.net/HiWangWenBing/article/details/123840378