【初中生讲机器学习】4. 支持向量机算法怎么用?一个实例带你看懂!

创建时间:2024-02-02
最后编辑时间:2024-02-03
作者:Geeker_LStar

你好呀~这里是 Geeker_LStar 的人工智能学习专栏,很高兴遇见你~
我是 Geeker_LStar,一名初三学生,热爱计算机和数学,我们一起加油~!
⭐(●’◡’●) ⭐
那就让我们开始吧!

上一篇【初中生讲机器学习】3. 支持向量机(SVM)一万字详解!超全超详细超易懂!当中,我们已经详细了解了支持向量机算法以及它背后的数学原理,但是上一篇文章中没有给出实例代码,so 这一篇主要就通过一个实例来看看支持向量机算法应该怎么实现,有哪些要点~

完整代码见文末~

实例:利用支持向量机对鸢尾花进行分类。
(神奇,我这学期的作文里貌似三次写到鸢尾花诶)

话不多说,首先,我们导入各种需要的库(or 需要的函数方法 or 数据集)。

'''第一步,导入各种需要的库'''
import matplotlib.pyplot as plt    # 用于数据可视化
import matplotlib as mpl
from sklearn import svm    # 引入封装好的 SVM 算法
from sklearn.datasets import load_iris    # 引入鸢尾花数据集,共 150 组数据
from sklearn.model_selection import train_test_split    # 划分训练集和测试集的函数方法
from sklearn.metrics import accuracy_score    # 评判测试准确度的函数方法
import numpy as np    # 进行科学计算

matplotlib,进行数据可视化的库。
numpy 用于进行科学计算。
scikit learn,即 sklearn 库,是机器学习中非常重要的一个库,它封装了大量常用算法,如分类、回归、降维、聚类等,并且提供一些常用数据集,其中就包括本例中用到的鸢尾花数据集。

接着,我们需要对鸢尾花数据集有一个了解,先加载它,然后输出一些它的特征。

iris = load_iris()    # 加载数据集
print(iris.target)    # 数据标签(分类结果标签)
print(iris.target_names)    # 三种鸢尾花的名字
print(iris.feature_names)    # 四个分类特征的名字

这是输出结果,可以看到,数据集中的鸢尾花一共有三类 150 个,每一类有 50 个。分类标准是【萼片长度】【萼片宽度】【花瓣长度】【花瓣宽度】。

[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2]
['setosa' 'versicolor' 'virginica']
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

再来看一下每一个鸢尾花数据是怎么表示的(没错其实就是四维向量,因为四个特征嘛),以及它们对应的数据标签。

X = iris.data    # 输入数据(150 个四维向量),样本特征,[n_samples * n_features] 的二维数组
print(X.shape, X)    # X.shape,输出 X 数组的行数和列数
y = iris.target    # 数据标签 or 分类结果(共三种每种 50 个数据)
print(y.shape, y)

输出如下(一部分),大意是:输入数据一共 150 个,每个都是一个四维向量,对应的数据标签是 0 或 1 或 2。

(150, 4) [[5.1 3.5 1.4 0.2][4.9 3.  1.4 0.2][4.7 3.2 1.3 0.2][4.6 3.1 1.5 0.2](150,) [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2]

哦?这样不够直观?看不出这 150 组数据在分布上有什么特点?没事,咱有 matplotlib,画个图嘛!
errr,我们分别以前两个特征(萼片长宽)和后两个特征(花瓣长宽)为特征画图。画完图其实可以看出一些东西,不过这里先不透露。

# 以前两个特征(花萼长度、花萼宽度)绘图
X = iris.data[:, :2]    # 切片操作,选取前两个特征
plt.scatter(X[y == 0, 0], X[y == 0, 1], color = "red", marker = "o")
plt.scatter(X[y == 1, 0], X[y == 1, 1], color = "green", marker = "+")
plt.scatter(X[y == 2, 0], X[y == 2, 1], color = "blue", marker = "x")
plt.xlabel('sepal length', fontsize=20)
plt.ylabel('sepal width', fontsize=20)
plt.title('Iris names', fontsize=30)
plt.show()

这是这些鸢尾花的萼片长宽的分布图,不难发现,通过萼片长宽可以比较好的将第一种鸢尾花(红色)和第二三种(绿/蓝色)区分开,但是第二种和第三种之间却不太好区分。

萼片长宽分布

再来看看花瓣长宽的情况。

# 以后两个特征(花瓣长度、花瓣宽度)绘图(发现后两个特征能够更好地区分三类鸢尾花)
X = iris.data[:, 2:]
plt.scatter(X[y == 0, 0], X[y == 0, 1], color = "red", marker = "o")
plt.scatter(X[y == 1, 0], X[y == 1, 1], color = "green", marker = "+")
plt.scatter(X[y == 2, 0], X[y == 2, 1], color = "blue", marker = "x")
plt.xlabel('petal length', fontsize=20)
plt.ylabel('petal width', fontsize=20)
plt.title('Iris names', fontsize=30)
plt.show()

分布图长这样,不难看出,可以通过花瓣长宽特征将三种鸢尾花大致分开,【只按照花瓣特征分】比【只按照萼片特征分】的效果更好(为什么提到这个,因为后面要写相关代码~)。

花瓣长宽分布

ok,现在我们对整个数据集已经有了大致的了解,可以利用支持向量机来分类啦!

通常来讲,用 SVM 分类可以按照这个顺序进行,其中 2、3 可以反过来:

  1. 获取所需数据集(全部特征 or 某个或某几个特征(切片))
  2. 定义支持向量机(svm.SVC())
  3. 划分训练集和测试集(train_test_split())
  4. 利用训练集进行训练(fit())
  5. 测试,预测测试集的输出结果(predict())
  6. 计算测试准确率并输出,模型评价(accuracy_score())
  7. 绘制结果(如果需要)

那我们就按照这个步骤来吧!先来最简单的,用全部特征进行分类,先训练再测试。

第一步,获取所需数据集,这两行代码的意思上面已经解释过:

X = iris.data
y = iris.target

第二步,定义支持向量机,解释一下其中的一些参数,这些参数的详细讲解都在上一篇:

  • kernel:核函数类型,“linear” 表示线性核函数,“poly” 表示多项式核函数,“rbf” 表示高斯核函数(径向基函数)。
  • C:惩罚项,默认值为 1。C 的值很关键,过小会导致模型的泛化能力弱(过拟合),过大又会导致欠拟合。
  • gamma:核函数的核系数,一般情况下默认为 1/n_features。
  • probability:是否支持输出样本属于不同类的概率,True 表示支持。
svm1 = svm.SVC(kernel="rbf", C=1, gamma="auto", probability=True)

第三步,划分训练集和测试集
train_test_split() 用于划分训练集和测试集,其中,test_size 指测试集数据量占数据总量的百分比,0.3 即有 30% 的数据用于测试,其余数据用于训练;random_state 是随机数种子,改变它可以获得不同的数据划分,通常在交叉验证中使用。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=218)

第四步,利用训练集进行训练
fit() 方法,用于训练支持向量机,也就是拟合

svm2.fit(X_train, y_train)

第五步,测试,预测测试集的输出结果
训练完 SVM,就让它去预测一下测试集的数据吧。
predict() 函数用于预测。

y_predict = svm2.predict(X_test)

第六步,计算测试准确率并输出,也就是模型评价:
accuracy_score() 函数计算模型预测的准确率,是评价模型性能的一项参考指标,与之类似的参考指标还有召回率、ROC 曲线、AUC 值等,这些在第二篇中讲过~(sklearn 库也提供其他参考指标的函数方法,但是本例中用不到)。

print("准确率:", accuracy_score(y_test, y_predict))

ok!此时一个 SVM 的训练+测试就完成了!我这里的准确率是 95.6%。

如果对准确率不满意,可以尝试调整惩罚系数 C,也可以尝试换一种核函数,或者提高训练集的占比使模型得到更充分的训练,等等。

ok,走了一遍基础流程,其实 SVM 的训练并不难的()下面我们来看看如果我们想按照某些特征进行分类(比如之前提到的按照萼片长宽分类),并且想更直观地看到这个超平面是怎么划分的,我们应该怎么做。

其实大体上没什么变化,只不过在获取数据的时候需要做一个切片处理,语法和 Python 当中的列表切片是一样的。

X2 = iris.data[:, :2]    # :2 表示取前两个特征,即萼片长和萼片宽

别的代码和上面完全一样,为了和上面进行区分,把 svm 和 X 的角标改了一下:

X2 = iris.data[:, :2]    # :2 表示取前两个特征,即萼片长和萼片宽
svm3 = svm.SVC(kernel="rbf", C=3, gamma="auto")
X2_train, X2_test, y2_train, y2_test = train_test_split(X2, y, test_size=0.3, random_state=218)
svm3.fit(X2_train, y2_train)
y2_predict = svm3.predict(X2_test)
print("准确率:", accuracy_score(y2_test, y2_predict))
draw1(svm3, X2)    # 绘图

你可能发现了,这段代码里定义了一个用于绘图的 draw 函数,这个函数蛮关键的,我们拆解着来写。

first,明确需求,我们希望通过前两个特征(萼片长宽)进行分类,并将结果可视化,也就是要画出决策超平面,直观地看出萼片长宽在哪一部分的花会被分到哪一类

先把最终结果放在这,这样后面拆解每一步就会变得好理解~

下图中,背景色块相交的地方就是决策超平面(其实就是一条线),不同的色块代表花萼长宽在不同范围的鸢尾花会被分到不同的类(一个色块就是一类)。

花萼分类结果

其实这块主要是数据处理 and 可视化,并且这种可视化套路其实是通用的,后面的文章中会讲 KNN(K 最近邻)算法,它的实例也可以用这一套可视化流程。

首先,花萼长宽的分布都在一定范围内,我们可以用它们的最小值和最大值作为 xy 轴的起止点,如下。

# 获取坐标值的范围
x1_min, x1_max = X[:, 0].min(), X[:, 0].max()
x2_min, x2_max = X[:, 1].min(), X[:, 1].max()
# 坐标轴范围
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)

接着,问题来了,怎么找到决策线?上图中那些表示分类的背景色块是怎么画出来的?

这个思路很好:色块其实就是一个个点密集分布组成的,我们可以在坐标系中取很多很多点(为了保证精确度,这些点之间的间隔应该相等且足够小),用已经训练好的模型预测这些点会被分到哪一类。对于分到不同类的点,用不同的颜色在坐标系中画出它们。这样这些密集的点就会形成一个“色块”,不同颜色的色块也就代表了不同的类。
(对之所以高亮这一部分就是我觉得这个思路真的太棒了!)

来写写。

first,我们要取一堆间隔足够小的点,比如在横纵坐标最小值和最大值之间都均等取 200 个值,这样一共就选取了 200*200 = 40000 个点,这么多点足以让坐标系看起来被填满了。

# 生成坐标系中的网格点(2D)
# 200j,复数,即在这个范围中取 200 个点
x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]

second,目前的 x1、x2 都还只是单独的横坐标和单独的纵坐标,用 stack() 函数把它们重新组合一下,新的数组是 40000 个点的坐标。

# 构造测试点(坐标点)并输出其坐标
# stack() 方法,将两个二维数组合并成一个新的二维数组
grid_test = np.stack((x1.flat, x2.flat), axis=1)
print('坐标点的坐标数据:\n', grid_test)

输出是这样的,可以看到和图中的坐标范围是一致的。

坐标点的坐标数据:[[1.        0.1      ][1.        0.1120603][1.        0.1241206]...[6.9       2.4758794][6.9       2.4879397][6.9       2.5      ]]

上一篇中提到了函数间隔,它反映点到决策超平面的距离,函数间隔大于等于 1 说明分类正确,越大说明越可能是这一类。

这里获得输出构造的坐标点的函数间隔(可以看出它们应该分到哪一类),用 decision_function() 函数,然后输出坐标点预测结果。

and then 输出一下原始数据集中的数据被分到每一类的概率,用 predict_proba() 函数。

其实这些可以不用输出,但是为了更详细地知道每个函数都干了什么,我把输出结果放在代码后面了。

# decision_function 多分类情况
# 输出样本到决策超平面的距离(函数间隔),反映属于每个分类的可能性
# 第 n 个数是属于第 n 类的可能性
# 数越大,说明越有可能属于这个分类
z = svm.decision_function(grid_test)
print('坐标点到超平面的距离(函数间隔):\n', z)
# 预测并输出分类结果,得到 [0, 0, ..., 2, 2]
grid_hat = svm.predict(grid_test)
print('坐标点预测结果:\n', grid_hat)
# 预测并输出测试集中的数据属于每个类别的概率
probably = svm.predict_proba(X)
print('测试数据的预测概率:\n', probably)

输出结果:

坐标点到超平面的距离(函数间隔):[[ 2.21808359 -0.18477028  0.86886414][ 2.21824232 -0.18491925  0.86865134][ 2.21838742 -0.18505706  0.86845955]...[-0.18169166  0.85623648  2.22058861][-0.18145152  0.85663691  2.22031407][-0.18120477  0.85704722  2.22003204]]坐标点预测结果:[0 0 0 ... 2 2 2]
测试数据的预测概率:[[0.95790549 0.0183466  0.02374791][0.95790549 0.0183466  0.02374791][0.95498744 0.01979717 0.02521539][0.95897025 0.01779033 0.02323941](这里省略了后面的)

重要的逻辑都说完了,剩下就是画图的事情了,画图部分的代码的功能注释里都写了~

# 使得 grid_hat 和 x1 的数组形式一致
grid_hat = grid_hat.reshape(x1.shape)
cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
cm_dark = mpl.colors.ListedColormap(['g', 'b', 'r'])
# pcolormesh 绘制背景颜色块(前面取坐标点并获得它们的分类结果就是为了这个)
# 用于区分坐标系中的哪一部分会被分到哪一类
# cmap 自定义颜色(用亮色绘制背景,用暗色绘制测试集中的数据点)
# 绘制测试集中的点
plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light)
plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(y), edgecolor='k', s=50, cmap=cm_dark)
plt.scatter(X_test[:, 0], X_test[:, 1], s=120, facecolor='none', zorder=10)
# 坐标轴标签
plt.xlabel(iris_feature[0], fontsize=20)
plt.ylabel(iris_feature[1], fontsize=20)
# 坐标轴范围
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)
# 坐标轴标题
plt.title('Iris classification based on SVM', fontsize=30)
# 绘图
plt.grid()
plt.show()

ok!画图函数已经完成,完整代码:

# 定义绘图函数(以前两个特征作为分类依据)
def draw1(svm, X):iris_feature = 'sepal length', 'sepal width', 'petal length', 'petal width'    # 四个特征# 获取坐标值的范围x1_min, x1_max = X[:, 0].min(), X[:, 0].max()x2_min, x2_max = X[:, 1].min(), X[:, 1].max()# 生成坐标系中的网格点(2D)# 200j,复数,即在这个范围中取 200 个点x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]# 构造测试点(坐标点)# stack() 方法,将两个二维数组合并成一个新的二维数组,并且数组 1 中的第 i 项和数组 2 中的第 i 项合并为新数组的第 i 项# 输出构造的点的坐标grid_test = np.stack((x1.flat, x2.flat), axis=1)print('坐标点的坐标数据:\n', grid_test)# decision_function 多分类情况# 输出样本到决策超平面的距离(函数间隔),反映属于每个分类的可能性# 第 n 个数是属于第 n 类的可能性# 数越大,说明越有可能属于这个分类z = svm.decision_function(grid_test)print('坐标点到超平面的距离(函数间隔):\n', z)# 预测并输出分类结果,得到 [0, 0, ..., 2, 2]grid_hat = svm.predict(grid_test)print('坐标点预测结果:\n', grid_hat)# 预测并输出测试集中的数据属于每个类别的概率probably = svm.predict_proba(X)print('测试数据的预测概率:\n', probably)# 使得 grid_hat 和 x1 的数组形式一致grid_hat = grid_hat.reshape(x1.shape)cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])cm_dark = mpl.colors.ListedColormap(['g', 'b', 'r'])# pcolormesh 绘制背景颜色块(前面取坐标点并获得它们的分类结果就是为了这个)# 用于区分坐标系中的哪一部分会被分到哪一类# cmap 自定义颜色(用亮色绘制背景,用暗色绘制测试集中的数据点)# 绘制测试集中的点plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light)plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(y), edgecolor='k', s=50, cmap=cm_dark)plt.scatter(X_test[:, 0], X_test[:, 1], s=120, facecolor='none', zorder=10)# 坐标轴标签plt.xlabel(iris_feature[0], fontsize=20)plt.ylabel(iris_feature[1], fontsize=20)# 坐标轴范围plt.xlim(x1_min, x1_max)plt.ylim(x2_min, x2_max)# 坐标轴标题plt.title('Iris classification based on SVM', fontsize=30)# 绘图plt.grid()plt.show()

最后得到的准确率是 73% 左右,和我们从图中直观看出来的是差不多的,即只按照花萼长宽进行分类的结果并不很好

按照花瓣长宽分类和按照花萼长宽分类完全是一个道理,最后画出的图长这样,准确率在 97% 左右,说明对于鸢尾花,花瓣的特征更加鲜明,作为分类依据会更好。

按花瓣长宽分类的结果

还有一个有趣的结果——按照四个特征分类的准确率居然比只按照花瓣长宽两个特征分类的准确率低(至少在本文的 “实验条件” 下是这样的),可能是因为花萼长宽中的部分数据特征不够鲜明或者有噪声数据(比如某朵花变异了之类的)。

这也说明在训练模型的时候,特征的选取有时并不是越多越好,选取特征的时候需要考虑特征是否鲜明、区分度高。如果特征选取不当,可能会对模型的性能造成负面影响。

ok!以上就是本文的全部内容啦!完整代码:

# 利用支持向量机(SVM)对鸢尾花进行分类,一共分成三类
# Scikit learn 是机器学习中常见的第三方模块,封装了常用算法,包括回归、降维、分类、聚类等
# 鸢尾花数据集:共 150 组数据,每组数据 4 个特征(四维向量)
# matplotlib 用于数据可视化
# numpy 用于科学计算'''第一步,导入各种需要的库'''
import matplotlib.pyplot as plt    # 用于数据可视化
import matplotlib as mpl
from sklearn import svm    # 引入封装好的 SVM 算法
from sklearn.datasets import load_iris    # 引入鸢尾花数据集,共 150 组数据
from sklearn.model_selection import train_test_split    # 分割训练集和测试集的函数方法
from sklearn.metrics import accuracy_score    # 评判测试准确度的函数方法
import numpy as np    # 进行科学计算'''第二步,输出数据集的各种信息并绘制散点图(直观分类)'''
iris = load_iris()    # 加载数据集
print(iris.target)    # 数据标签(分类结果标签)
print(iris.target_names)    # 三种鸢尾花的名字
print(iris.feature_names)    # 四个分类特征的名字
X = iris.data    # 输入数据(150 个四维向量),样本特征,[n_samples * n_features] 的二维数组
print(X.shape, X)    # X.shape,输出 X 数组的行数和列数
y = iris.target    # 数据标签 or 分类结果(共三种每种 50 个数据)
print(y.shape, y)
# 以前两个特征(花萼长度、花萼宽度)绘图
X = iris.data[:, :2]    # 切片操作,选取前两个特征
plt.scatter(X[y == 0, 0], X[y == 0, 1], color = "red", marker = "o")
plt.scatter(X[y == 1, 0], X[y == 1, 1], color = "green", marker = "+")
plt.scatter(X[y == 2, 0], X[y == 2, 1], color = "blue", marker = "x")
plt.xlabel('sepal length', fontsize=20)
plt.ylabel('sepal width', fontsize=20)
plt.title('Iris names', fontsize=30)
plt.show()
# 以后两个特征(花瓣长度、花瓣宽度)绘图(发现后两个特征能够更好地区分三类鸢尾花)
X = iris.data[:, 2:]
plt.scatter(X[y == 0, 0], X[y == 0, 1], color = "red", marker = "o")
plt.scatter(X[y == 1, 0], X[y == 1, 1], color = "green", marker = "+")
plt.scatter(X[y == 2, 0], X[y == 2, 1], color = "blue", marker = "x")
plt.xlabel('petal length', fontsize=20)
plt.ylabel('petal width', fontsize=20)
plt.title('Iris names', fontsize=30)
plt.show()'''第三步,尝试用不同的方式进行训练'''
# 步骤:
# 1. 获取所需数据集(全部特征 or 某个或某几个特征(切片))
# 2. 定义支持向量机(svm.SVC())
# 3. 划分训练集和测试集(train_test_split())
# 4. 利用训练集进行训练(fit())
# 5. 测试,预测测试集的输出结果(predict())
# 6. 计算测试准确率并输出(accuracy_score())# svm.SVC() 函数是实现 SVM 算法的封装方法之一
# kernel:核函数类型,linear 代表线性,poly 代表多项式,rbf 代表径向基
# C:惩罚系数
# gamma:核函数中的核系数,默认为 1/n_features(特征数的倒数)'''第一类:不分训练集和测试集,用全部特征进行分类'''
X = iris.data
svm1 = svm.SVC(kernel="rbf", C=1, gamma="auto", probability=True)
svm1.fit(X, y)    # 用全部特征进行训练
print("训练得分:", svm1.score(X, y))
print("预测:", svm1.predict([[7, 5, 2, 0.5], [7.5, 4, 7, 2]]))
print('\n')'''第二类:分训练集和测试集,训练集训练完后用测试集测试,用全部特征进行分类'''
# test_size 表示训练数据在数据集中的占比,0.2 表示 20%
# random_state 表示随机数种子,改变该值可获得不同的分割方法
svm2 = svm.SVC(kernel="rbf", C=3, gamma="auto", probability=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=218)
svm2.fit(X_train, y_train)    # 用训练集进行训练
y_predict = svm2.predict(X_test)    # 用测试集进行测试
print("准确率:", accuracy_score(y_test, y_predict))    # 计算准确率(正确的所占百分比)
print('\n')'''第三类:分训练集和测试集,用不同特征进行分类'''
# 定义绘图函数(以前两个特征作为分类依据)
def draw1(svm, X):iris_feature = 'sepal length', 'sepal width', 'petal length', 'petal width'    # 四个特征# 获取坐标值的范围x1_min, x1_max = X[:, 0].min(), X[:, 0].max()x2_min, x2_max = X[:, 1].min(), X[:, 1].max()# 生成坐标系中的网格点(2D)# 200j,复数,即在这个范围中取 200 个点x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]# 构造测试点(坐标点)# stack() 方法,将两个二维数组合并成一个新的二维数组,并且数组 1 中的第 i 项和数组 2 中的第 i 项合并为新数组的第 i 项# 输出构造的点的坐标grid_test = np.stack((x1.flat, x2.flat), axis=1)print('坐标点的坐标数据:\n', grid_test)# decision_function 多分类情况# 输出样本到决策超平面的距离(函数间隔),反映属于每个分类的可能性# 第 n 个数是属于第 n 类的可能性# 数越大,说明越有可能属于这个分类z = svm.decision_function(grid_test)print('坐标点到超平面的距离(函数间隔):\n', z)# 预测并输出分类结果,得到 [0, 0, ..., 2, 2]grid_hat = svm.predict(grid_test)print('坐标点预测结果:\n', grid_hat)# 预测并输出测试集中的数据属于每个类别的概率probably = svm.predict_proba(X)print('测试数据的预测概率:\n', probably)# 使得 grid_hat 和 x1 的数组形式一致grid_hat = grid_hat.reshape(x1.shape)cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])cm_dark = mpl.colors.ListedColormap(['g', 'b', 'r'])# pcolormesh 绘制背景颜色块(前面取坐标点并获得它们的分类结果就是为了这个)# 用于区分坐标系中的哪一部分会被分到哪一类# cmap 自定义颜色(用亮色绘制背景,用暗色绘制测试集中的数据点)# 绘制测试集中的点plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light)plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(y), edgecolor='k', s=50, cmap=cm_dark)plt.scatter(X_test[:, 0], X_test[:, 1], s=120, facecolor='none', zorder=10)# 坐标轴标签plt.xlabel(iris_feature[0], fontsize=20)plt.ylabel(iris_feature[1], fontsize=20)# 坐标轴范围plt.xlim(x1_min, x1_max)plt.ylim(x2_min, x2_max)# 坐标轴标题plt.title('Iris classification based on SVM', fontsize=30)# 绘图plt.grid()plt.show()# 用前两个特征进行分类
X2 = iris.data[:, :2]    # :2 表示取前两个特征,即萼片长和萼片宽
svm3 = svm.SVC(kernel="rbf", C=3, gamma="auto", probability=True)
X2_train, X2_test, y2_train, y2_test = train_test_split(X2, y, test_size=0.3, random_state=218)
svm3.fit(X2_train, y2_train)
y2_predict = svm3.predict(X2_test)
print("准确率:", accuracy_score(y2_test, y2_predict))
draw1(svm3, X2)    # 绘图print('\n')
# 定义绘图函数(以后两个特征作为分类依据)
def draw2(svm, X):iris_feature = 'sepal length', 'sepal width', 'petal length', 'petal width'    # 四个特征# 获取坐标值的范围x1_min, x1_max = X[:, 0].min(), X[:, 0].max()x2_min, x2_max = X[:, 1].min(), X[:, 1].max()# 生成坐标系中的网格点(2D)# 200j,复数,即在这个范围中取 200 个点x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]# 构造测试点(坐标点)# stack() 方法,将两个二维数组合并成一个新的二维数组,并且数组 1 中的第 i 项和数组 2 中的第 i 项合并为新数组的第 i 项# 输出构造的点的坐标grid_test = np.stack((x1.flat, x2.flat), axis=1)print('坐标点的坐标数据:\n', grid_test)z = svm.decision_function(grid_test)print('坐标点到超平面的距离(函数间隔):\n', z)# 预测并输出分类结果,得到 [0, 0, ..., 2, 2]grid_hat = svm.predict(grid_test)print('坐标点预测结果:\n', grid_hat)# 预测并输出测试集中的数据属于每个类别的概率probably = svm.predict_proba(X)print('测试数据的预测概率:\n', probably)# 使得 grid_hat 和 x1 的数组形式一致grid_hat = grid_hat.reshape(x1.shape)cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])cm_dark = mpl.colors.ListedColormap(['g', 'b', 'r'])# pcolormesh 绘制背景颜色块(前面取坐标点并获得它们的分类结果就是为了这个)# 用于区分坐标系中的哪一部分会被分到哪一类# cmap 自定义颜色(用亮色绘制背景,用暗色绘制测试集中的数据点)# 绘制测试集中的点plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light)plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(y), edgecolor='k', s=50, cmap=cm_dark)plt.scatter(X_test[:, 0], X_test[:, 1], s=120, facecolor='none', zorder=10)# 坐标轴标签plt.xlabel(iris_feature[2], fontsize=20)plt.ylabel(iris_feature[3], fontsize=20)# 坐标轴范围plt.xlim(x1_min, x1_max)plt.ylim(x2_min, x2_max)# 坐标轴标题plt.title('Iris classification based on SVM', fontsize=30)# 绘图plt.grid()plt.show()# 用后两个特征进行分类
X3 = iris.data[:, 2:]    # 分割出后两个特征
svm4 = svm.SVC(kernel="rbf", C=3, gamma="auto", probability=True)
X3_train, X3_test, y3_train, y3_test = train_test_split(X3, y, test_size=0.3, random_state=218)
svm4.fit(X3_train, y3_train)    # 进行拟合(训练)
y3_predict = svm4.predict(X3_test)    # 预测(测试)
print("准确率:", accuracy_score(y3_test, y3_predict))    # 输出测试准确率
draw2(svm4, X3)

ok!!!!!以上就是支持向量机算法的实例!!

嘿嘿真的非常开心你能够看到这里!!一起加油!

如果有任何 bug 欢迎评论区拷打我!!

本文中所有的代码我都做了认真的分析(and 注释),希望对你有所帮助!我们下篇再见!⭐
——Geeker_LStar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665639.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

火贱兔奔月

欢迎来到程序小院 火贱兔奔月 玩法&#xff1a;点击左右箭头&#xff0c;控制火贱兔躲开障碍物&#xff0c;奔向月球和嫦娥姐姐约会&#xff0c;贱兔就是矫情&#xff0c;快去本月吧^^。开始游戏https://www.ormcc.com/play/gameStart/267 html <canvas id"gameCanva…

深度学习技巧应用35-L1正则化和L2正则在神经网络模型训练中的应用

大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用35-L1 正则化和L2正则在神经网络模型训练中的应用。L1正则化和L2正则化是机器学习中常用的两种正则化方法,用于防止模型过拟合并提高模型的泛化能力。这两种正则化方法通过在损失函数中添加惩罚项来控制模型的复杂性。…

ChatGPT 4.0 升级指南, ChatGPT Plus(GPT 4.0) 有何优势?

1.ChatGPT 是什么&#xff1f; ChatGPT 是由 OpenAI 开发的一种基于人工智能的聊天机器人&#xff0c;它基于强大的语言处理模型 GPT&#xff08;Generative Pre-trained Transformer&#xff09;构建。它能够理解人类语言&#xff0c;可以为我们解决实际的问题。 ChatGPT 4.…

获取github某项目软件的最新版本方法(通过命令行)

场景&#xff1a; 如果我们项目中需要实现某个Github公共软件的最新版本更新 那么获取软件的最新的发布版本就是一个比较重要的工作了 对此&#xff0c;Github提供对外api不需要自己手动填写脚本了 解决方案&#xff1a; 替换黄色字体的项目地址&#xff0c;然后在cmd中执行…

chisel之scala 语法

Chisel新手教程之Scala语言&#xff08;1&#xff09; Value & variable Value是immutable的&#xff0c;当它被分配一个数据后&#xff0c;无法进行重新分配。用 val 表示。 Variable是mutable的&#xff0c;可以重复赋值。用 var 表示。示例如下&#xff1a; val a …

牛客寒假训练营H题

思路&#xff1a;找出所有m的子集&#xff0c;加到价值中&#xff0c;找出最大价值即可。 代码&#xff1a; void solve(){int n, m;cin >> n >> m;vector<pii>a(n 1);for(int i 1;i < n;i )cin >> a[i].first >> a[i].second;int ans 0…

获取响应请求头里的信息

如图所示这是一个导出excel的接口&#xff0c;后端响应头部&#xff0c;要获取Content-Disposition里的值&#xff0c; 由于命名问题&#xff0c;没有办法用res.Content-Disposition的方式获取它的值 按理来说使用res[Content-Disposition]就可以获取到&#xff0c;但是咩有&…

简单几步,借助Aapose.Cells将 Excel 工作表拆分为文件

近年来&#xff0c;Excel 文件已成为无数企业数据管理的支柱。然而&#xff0c;管理大型 Excel 文件可能是一项艰巨的任务&#xff0c;尤其是在高效共享和处理数据时。为了应对这一挑战&#xff0c;大型 Excel 工作簿被拆分为较小的工作簿以增强电子表格管理。Aspose提供了这样…

【LeetCode: 462. 最小操作次数使数组元素相等 II + 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

redis复习笔记05(小滴课堂)

案例实战之注册登录-图形验证码谷歌开源Kaptcha引入 验证码配置工具类。 验证码存储Redis逻辑编码实战 工具类用于获取本机ip和md5加密&#xff0c;直接使用就行&#xff0c;我们这里主要是学习redis不是学习这个。 获取验证码并存到redis中的接口&#xff1a; 运行测试&…

QT exe软件输出

本教程对应的软件是Qt Creater&#xff0c;只有绿色便携版能正常运行才能够打包成单文件版和可安装版。 一、绿色便携版 特点&#xff1a;给别人发送的时候需要先制作成一个压缩包文件&#xff0c;解压即用。 使用Qt自带的程序 1、给exe软件添加图标 exe软件的图标&…

[word] 怎么将word文档中的文字转换成一个4行5列的表格 #职场发展#笔记#经验分享

怎么将word文档中的文字转换成一个4行5列的表格 怎么将word文档中的文字转换成一个4行5列的表格&#xff1f; 将文档中的四行文字转换成一个4行5列的表格的具体步骤如下&#xff1a; 1、首先打开需要编辑的Word文档&#xff0c;进入到编辑页面中。 2、然后选中需要编辑的文字…

Unity3d C# 在WebGL平台加载并解析xml文件实现总结

前言 xml是可扩展标记语言&#xff0c;由一系列的元素、属性、值节点等构成的一个树形结构&#xff0c;除了可读性差一点&#xff0c;别的用于存储一些结构化的数据还是比较方便的。这个功能在Unity3d端的实现是比较方便快捷的&#xff1a; void GetXML1() {string filePath …

web前端------弹性盒子

display属性&#xff0c;用于指定元素的盒子类型。 属性值flex&#xff0c;表示生成一个弹性容器&#xff0c;简称容器。 容器中每一个子元素都叫做项目。 我们知道了弹性盒子由容器和项目组成。 而CSS中提供了很多属性来实现弹性布局&#xff0c;按照作用范围的不同&#…

顺序表:数据结构的建筑积木

朋友们大家好啊&#xff0c;本节内容我们进入数据结构的第二节&#xff0c;顺序表有关内容&#xff0c;同步我们会学习计组原理与cpp相关知识&#xff0c;求三连啊&#xff01; 本节我们重点探讨动态顺序表关于插入数据和删除数据的多种情况的分析 顺序表 线性表顺序表静态顺序…

[职场] 研发工程师的简历该怎么写 #学习方法#媒体#学习方法

研发工程师的简历该怎么写 研发工程师的工作内容有&#xff1a; 根据开发项目的要求&#xff0c;制订机械结构、外形的设计方案。 按时完成上级分配的机械、外形设计任务。 负责自己设计的结构及外形安装&#xff0c;并解决安装过程中出现的问题。 协助设计产品的材料选购…

前端JavaScript篇之JavaScript有哪些内置对象

目录 JavaScript有哪些内置对象常见的内置对象的简单描述和参考代码总结 JavaScript有哪些内置对象 JavaScript中常见的内置对象包括&#xff1a; Object&#xff1a;用于创建对象的构造函数&#xff0c;对象是键值对的集合&#xff0c;用于存储和传递数据。 Array&#xff1…

python计算两个DataFrame的指定两列中,相同的数据有多少

目的&#xff1a;查询数据1和数据2中&#xff0c;red与red列相同 并且blue与blue列相同的&#xff0c;情况有多少。 &#xff08;备注&#xff1a;两个数据中格式不一致&#xff0c;需要经过json提取等处理步骤&#xff09; 思路步骤&#xff1a; 1、读取数据1&#xff0c;筛选…

【MongoDB】跨库跨表查询(python版)

MongoDB跨表跨库查询 1.数据准备&#xff1a;2.跨集合查询3.跨库查询应该怎么做&#xff1f; 讲一个简单的例子&#xff0c;python连接mongodb做跨表跨库查询的正确姿势 1.数据准备&#xff1a; use order_db; db.createCollection("orders"); db.orders.insertMan…

2021-10-12 51蛋骗鸡数码管前7位显示1-7第8位显示0-9

缘由 51单片机数码管问题-编程语言-CSDN问答 #include "REG52.h" sbit K1 P3^0; sbit K2 P3^1; sbit K3 P3^2; sbit K4 P3^3; bit k1,wk0; unsigned char code SmZiFu[]{63,6,91,79,102,109,125,7,127,111,128,255,64};//0-9.消隐- unsigned char Js0,miao0,fen…