【机器学习】SVM实例——对glass数据集进行分类处理实验详解

一、SVM是什么?

支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;
SVM还包括核函数,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。
概述:支持向量机的基本模型是定义在特征空间的间隔最大的线性分类器,其中间隔最大使它有别于感知机。支持向量机旨在求一个分离超平面。这个超平面使得离它最近的点能够最远。SVM用scikit-learn库实现起来比较简单。

1.线性可分

首先来了解一下什么是线性可分,在二维空间,两类点被一条直线完全分开叫做线性可分。严格的数学定义是: D 0 D_0 D0 D 1 D_1 D1 n n n维欧式空间中的两个点集。如果存在 n n n维向量 w w w和实数 b b b,使得 D 0 D_0 D0的点 x i x_i xi都有 w x i + b > 0 wx_i+b>0 wxi+b>0,而对于所有属于 D 1 D_1 D1的点 x j x_j xj则有 w x j + b < 0 wx_j+b<0 wxj+b<0,则我们称 D 0 D_0 D0 D 1 D_1 D1线性可分。

2.最大间隔超平面

从二维扩展到多维空间中时,将 D 0 D_0 D0 D 1 D_1 D1完全正确地划分开的 w x + b = 0 wx+b=0 wx+b=0就成了一个超平面。

为了使这个超平面更具鲁棒性,我们会去找最佳超平面,以最大间隔把两类样本分开的超平面,也称之为最大间隔超平面。

  • 两类样本分别分割在该超平面的两侧;
  • 两侧距离超平面最近的样本点到超平面的距离被最大化了。

3.支持向量

图1 超平面图
样本中距离超平面最近的这些点,叫做支持向量。

4.SVM最优化问题

SVM 想要的就是找到各类样本点到超平面的距离最远,也就是找到最大间隔超平面。任意超平面可以用下面这个线性方程来描述:
w T x + b = 0 w^T x+b=0 wTx+b=0
二维空间点 ( x , y ) (x,y) (x,y)到直线 A x + B y + C = 0 Ax+By+C= 0 Ax+By+C=0的距离公式是:
( ∣ A x + B y + C ∣ ) / √ ( A 2 + B 2 ) (|Ax+By+C|)/√(A^2+B^2 ) (Ax+By+C)/(A2+B2)
扩展到n维空间后,点 x = ( x 1 , x 2 , … x n ) x=(x_1,x_2,…x_n) x=(x1,x2,xn)到直线 w T x + b = 0 w^T x+b=0 wTx+b=0 的距离为:
( ∣ w T x + b ∣ ) / ( ∣ ∣ w ∣ ∣ ) (|w^T x+b|)/(||w||) (wTx+b)/(w)
其中 ∣ ∣ w ∣ ∣ = √ ( w 1 2 + ⋯ w n 2 ) ||w||= √(w_1^2+⋯w_n^2 ) w=(w12+wn2)
如上图1所示,根据支持向量的定义我们知道,支持向量到超平面的距离为 d d d,其他点到超平面的距离大于 d d d
于是就有了下述公式:
在这里插入图片描述

转换可以得到:

∣ ∣ w ∣ ∣ d ||w||d wd是正数,暂且令其为1(之所以令它等于 1,是为了方便推导和优化,且这样做对目标函数的优化没有影响),故:

将两个方差合并,可以简写为: y ( w T x + b ) ≥ 1 y(w^T x+b)≥1 y(wTx+b)1
于是可以得到最大间隔超平面的上下两个超平面,每个支持向量到超平面的距离可以写为:
d = ( ∣ w T x + b ∣ ) / ( ∣ ∣ w ∣ ∣ ) d= (|w^T x+b|)/(||w||) d=(wTx+b)/(w)
由上述 y ( w T x + b ) > 1 > 0 y(w^T x+b)>1>0 y(wTx+b)>1>0可以得到 y ( w T x + b ) = ∣ w T x + b ∣ y(w^T x+b)= |w^T x+b| y(wTx+b)=wTx+b,即:
d = ( y ( w T x + b ) ) / ( ∣ ∣ w ∣ ∣ ) d= (y(w^T x+b))/(||w||) d=(y(wTx+b))/(w)
最大化这个距离:
m a x 2 ∗ ( y ( w T x + b ) ) / ( ∣ ∣ w ∣ ∣ ) max2* (y(w^T x+b))/(||w||) max2(y(wTx+b))/(w)
这里乘上2倍是为了后面的推导,对目标函数没有影响,对于得到的支持向量 y ( w T x + b ) = 1 y(w^T x+b)=1 y(wTx+b)=1,可以得到:
m a x 2 / ( ∣ ∣ w ∣ ∣ ) max 2/(||w||) max2/(w)
再做一个转换:
m i n 1 / 2 ∣ ∣ w ∣ ∣ min 1/2||w|| min1/2w
为方便计算(去除||w||的根号),可以转换为:
m i n 1 / 2 ∣ ∣ w ∣ ∣ 2 min 1/2 ||w||^2 min1/2w2
所以得到的最优化问题是:
m i n 1 / 2 ∣ ∣ w ∣ ∣ 2 s . t y i ( w T x i + b ) ≥ 1 min 1/2 ||w||^2 s.t y_i (w^T x_i+b)≥1 min1/2w2s.tyi(wTxi+b)1

5.具体求解步骤

步骤1:构造拉格朗日函数

在这里插入图片描述

步骤2:利用强对偶转换

在这里插入图片描述

步骤3:SMO算法求解

核心思想比较简单:每次只优化一个参数,其他参数先固定住,仅求当前这个优化参数的极值。
1.选择两个需要更新的参数 λ i λ_i λi λ j λ_j λj,固定其他参数。于是就有以下约束:
λ i y i + λ j y j = c λ i ≥ 0 , λ j ≥ 0 λ_i y_i+ λ_j y_j=c λ_i ≥0 ,λ_j ≥0 λiyi+λjyj=cλi0,λj0
由此可以得出 λ j = ( c − λ i y i ) / y j λ_j=(c- λ_i y_i)/y_j λj=(cλiyi)/yj ,也就是说我们可以用 λ i λ_i λi的表达式代替 λ j λ_j λj。这样就相当于把目标问题转化成了仅有一个约束条件的最优化问题,仅有的约束是 λ i ≥ 0 λ_i ≥0 λi0
2. 对于仅有一个约束条件的最优化问题,可以在 λ i λ_i λi上对优化目标求偏导,令导数为零,从而求出变量值 λ ( i n e w ) λ_(i_new ) λ(inew),然后根据 λ ( i n e w ) λ_(i_new ) λ(inew)求出 λ ( j n e w ) λ_(j_new ) λ(jnew)
3. 多次迭代直至收敛。
通过SMO求得最优解 λ ∗ λ^* λ

步骤4:求得偏导得到w,求得支持向量的均值得到b

在这里插入图片描述

在这里插入图片描述

步骤5:构造分类决策函数

w w w b b b都求出来,就能构造出最大分割超平面: w T x + b = 0 w^T x+b=0 wTx+b=0

分类决策函数: f ( x ) = s i g n ( w T x + b ) f(x)=sign(w^T x+b) f(x)=sign(wTx+b)

二、使用步骤

1.引入库

import pandas
import time
import numpy as np
import sklearn
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn import svm
from collections import Counter
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split

2.获取数据

首先数据集获取,采用glass.csv数据集,下载地址:https://archive.ics.uci.edu/ml/machine-learning-databases/glass/glass.data

glass = pandas.read_csv('glass.csv')

数据集是这个样子:
在这里插入图片描述
前9个特征是glass样本的属性,包括:

  • RI: Refractive Index
  • Na: Sodium
  • Mg: Magnesium
  • Al: Aluminum
  • Si: Silicon
  • K: Potassium
  • Ca: Calcium
  • Ba: Barium
  • Fe: Iron

最后一列为glass样本的类型,共有7类:

  • Class 1: building windows (float processed)
  • Class 2: building windows (non-float processed)
  • Class 3: vehicle windows (float processed)
  • Class 4: vehicle windows (non-float processed)
  • Class 5: containers
  • Class 6: tableware
  • Class 7: headlamps

3.统计个类型的数量

glass = pandas.read_csv('glass.csv')
X = glass[ ['RI','Na','Mg','Al','Si','K','Ca','Ba','Fe']].values
Y = glass[['Type of glass']].values
Y = np.ravel(Y)
print('统计个数:',dict(Counter(Y)))

统计结果如下:
在这里插入图片描述

4.将原始数据划分成训练集和测试集:

#分训练集、测试集
X_train , X_test, y_train, y_test = train_test_split(X,Y,random_state=1,test_size=0.2)

用train_test_split将数据分为训练集和测试集,测试集占总数据的20%(test_size=0.3),random_state是随机数种子(随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。比如你每次都填1,其他参数一样的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:种子不同,产生不同的随机数;种子相同,即使实例不同也产生相同的随机数。)

5.模型搭建

clf = SVC(C=20, kernel='rbf')#核函数选用rbf
clf = fit(X_train,y_train)#训练
print('train accuracy:', clf.score(X_train, y_train))#输出训练集准确率
print('test accuracy:', clf.score(X_test, y_test))#输出测试集准确率

准确率结果如下:
在这里插入图片描述

6.不同核函数测试

svm1 = SVC(C=20,kernel='linear')
svm2 = SVC(C=20,kernel='rbf')
svm3 = SVC(C=20,kernel='poly')
svm4 = SVC(C=20,kernel='sigmoid')

t0 = time.time()
svm1.fit(X_train,y_train)
t1 = time.time()
svm2.fit(X_train,y_train)
t2 = time.time()
svm3.fit(X_train,y_train)
t3 = time.time()
svm4.fit(X_train,y_train)
t4 = time.time()

# 准确率对比
svm1_score1 = svm1.score(X_train, y_train)
svm1_score2 = svm1.score(X_test, y_test)

svm2_score1 = svm2.score(X_train, y_train)
svm2_score2 = svm2.score(X_test, y_test)

svm3_score1 = svm3.score(X_train, y_train)
svm3_score2 = svm3.score(X_test, y_test)

svm4_score1 = svm4.score(X_train, y_train)
svm4_score2 = svm4.score(X_test, y_test)

kernels = ['linear', 'rbf', 'poly', 'sigmoid']
time_e = [t1 - t0, t2-t1, t3-t2, t4-t3]
y_score1 = [svm1_score1, svm2_score1, svm3_score1, svm4_score1]
y_score2 = [svm1_score2, svm2_score2, svm3_score2, svm4_score2]


for index in range(4):
    print('核函数{:^10s}训练所需时间为:{:.5f}秒, 在训练集的准确率是:{:2.3f}%,在测试集上的准确率是:{:2.3f}%'.format(kernels[index], time_e[index], y_score1[index] * 100, y_score2[index] * 100))

不同核函数测试结果如下:
在这里插入图片描述

7.最佳模型的混淆矩阵以及图形化展示

cfm = confusion_matrix(y_test,y_pred)
print("Confusion Matrix: ")
print(cfm)
# 矩阵变形
# 计算矩阵每一行的数据和
row_sums = np.sum(cfm, axis=1)
# 计算矩阵每一行的数据所占该数据总和的比例
err_matrix = cfm / row_sums
# 让矩阵对角线数据更改为0,因为对角线的数据全是模型预测正确的样本数量,而分析混淆矩阵的主要目的是查看模型预测错误的地方
# fill_diagonal(矩阵,m):将对角线的数据全改成m
np.fill_diagonal(err_matrix,0)
# 可视化
plt.matshow(err_matrix,cmap=plt.cm.YlGn)
plt.show()

confusion_matrix函数的使用:官方文档中给出的用法是

sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None, sample_weight=None)
y_true: 是样本真实分类结果,y_pred: 是样本预测分类结果,labels:是所给出的类别,通过这个可对类别进行选择,sample_weight : 样本权重

混淆矩阵运行结果:
在这里插入图片描述
可视化运行结果:
在这里插入图片描述

完整代码

import pandas
import time
import numpy as np
import sklearn
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn import svm
from collections import Counter
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
######################################################################
glass = pandas.read_csv('glass.csv')
X = glass[ ['RI','Na','Mg','Al','Si','K','Ca','Ba','Fe']].values
Y = glass[['Type of glass']].values
Y = np.ravel(Y)
print('统计个数:',dict(Counter(Y)))
######################################################################
#分训练集、测试集
X_train , X_test, y_train, y_test = train_test_split(X,Y,test_size=0.2)
######################################################################
y_pred = clf.predict(X_test)
#用svm分类
svm1 = SVC(C=20,kernel='linear')
svm2 = SVC(C=20,kernel='rbf')
svm3 = SVC(C=20,kernel='poly')
svm4 = SVC(C=20,kernel='sigmoid')

t0 = time.time()
svm1.fit(X_train,y_train)
t1 = time.time()
svm2.fit(X_train,y_train)
t2 = time.time()
svm3.fit(X_train,y_train)
t3 = time.time()
svm4.fit(X_train,y_train)
t4 = time.time()
# 准确率对比
svm1_score1 = svm1.score(X_train, y_train)
svm1_score2 = svm1.score(X_test, y_test)

svm2_score1 = svm2.score(X_train, y_train)
svm2_score2 = svm2.score(X_test, y_test)

svm3_score1 = svm3.score(X_train, y_train)
svm3_score2 = svm3.score(X_test, y_test)

svm4_score1 = svm4.score(X_train, y_train)
svm4_score2 = svm4.score(X_test, y_test)
# 不同核函数
kernels = ['linear', 'rbf', 'poly', 'sigmoid']
time_e = [t1 - t0, t2-t1, t3-t2, t4-t3]
y_score1 = [svm1_score1, svm2_score1, svm3_score1, svm4_score1]
y_score2 = [svm1_score2, svm2_score2, svm3_score2, svm4_score2]

for index in range(4):
    print('核函数{:^10s}训练所需时间为:{:.5f}秒, 在训练集的准确率是:{:2.3f}%,在测试集上的准确率是:{:2.3f}%'.format(kernels[index], time_e[index], y_score1[index] * 100, y_score2[index] * 100))
######################################################################
cfm = confusion_matrix(y_test,y_pred)
print("Confusion Matrix: ")
print(cfm)
# 矩阵变形
# 计算矩阵每一行的数据和
row_sums = np.sum(cfm, axis=1)
# 计算矩阵每一行的数据所占该数据总和的比例
err_matrix = cfm / row_sums
# 让矩阵对角线数据更改为0,因为对角线的数据全是模型预测正确的样本数量,而分析混淆矩阵的主要目的是查看模型预测错误的地方
# fill_diagonal(矩阵,m):将对角线的数据全改成m
np.fill_diagonal(err_matrix,0)
# 可视化
plt.matshow(err_matrix,cmap=plt.cm.YlGn)
plt.show()

总结

以上是关于SVM基础概念以及对于glass数据集处理的实例处理的用法,欢迎大家一起交流学习强调内容

参考

从零开始的机器学习之SVM一个简单的实现案例——鸢尾花分类
混淆矩阵及confusion_matrix函数的使用
数据分析——“玻璃的类型”数据集
支持向量机(SVM)——原理篇
机器学习算法(一)SVM

  • 8
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
调库使用SVM对基于标准MNIST数据集进行分类实验,可使用Python的scikit-learn库进行实现。 首先,导入所需的库和数据集。使用scikit-learn中的datasets模块,导入MNIST数据集: ```python from sklearn import datasets mnist = datasets.load_digits() ``` 接下来,对数据集进行处理。将数据集分为训练集和测试集,同时对数据进行归一化处理。在这里,我们选择使用train_test_split函数将数据集划分为训练集和测试集,其中70%的数据用于训练,30%的数据用于测试: ```python from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.3, random_state=0) scaler = StandardScaler() X_train = scaler.fit_transform(X_train) X_test = scaler.transform(X_test) ``` 然后,使用scikit-learn中的svm模块,导入SVM模型,构建并训练分类器: ```python from sklearn import svm clf = svm.SVC() clf.fit(X_train, y_train) ``` 最后,评估模型的性能并记录实验结果。使用预测的测试集标签与真实的测试集标签进行比较,计算准确率来评估模型的分类性能: ```python from sklearn import metrics y_pred = clf.predict(X_test) accuracy = metrics.accuracy_score(y_test, y_pred) print("准确率: %.2f%%" % (accuracy * 100)) ``` 通过以上步骤,我们可以使用SVM对基于标准MNIST数据集进行分类实验,并记录实验结果。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值