2022Fall 机器学习

1. 实验要求

  1. 考虑两种不同的核函数:i) 线性核函数; ii) ⾼斯核函数
  2. 可以直接调⽤现成 SVM 软件包来实现
  3. ⼿动实现采⽤ hinge loss 和 cross-entropy loss 的线性分类模型,并⽐较它们的优劣

2. 实验内容

1) SVM 模型的⼀般理论
2) 采⽤不同核函数的模型和性能⽐较及分析
3) 采⽤ hinge loss 的线性分类模型和 SVM 模型之间的关系
4) 采⽤ hinge loss 线性分类模型和 cross-entropy loss 线性分类模型⽐较
5) 训练过程(包括初始化⽅法、超参数参数选择、⽤到的训练技巧等)
6) 实验结果、分析及讨论

实验数据:

  • 数据集: 手写体数据集

  • 数据描述:

    • 第 1 行是表头,介绍了文件中各列表示的信息;其余的每一行对应一个样本,各样本包含 785列。

    • 第 1 列是标签,值为 0 或 1;其余 784 列是手写体的像素值,值的区间是 0 到 255。

3. 实验过程

1) SVM 模型的⼀般理论

​ 支持向量机(Support Vector Machine)是一种按监督学习方式对二元数据进行分类的广义线性分类器,它的学习目标是要在n维的特征空中找到一个最大边距的超平面对数据进行分类,该超平面可以将求解最优参数的原问题转化为一个求解凸二次规划的对偶问题;

​ 在训练样本的特征空间中,根据其是否线性可分,引申出了两种侧重点不同的SVM模型,一种是硬间隔SVM(Hard Margin),另一种是软间隔SVM(Soft Margin),前者假定了样本在其特征空间中是线性可分的(也就是能找到一个超平面,可以将不同类别的样本划分开),后者则假定了样本在其特征空间中线性不可分,其引入了松弛变量(Slack Variable)ξi≥0\xi_i \geq 0ξi​≥0 (表示样本偏离支持向量的距离)允许SVM在一些样本上出错,但会得到相应的惩罚ξi\xi_iξi​ ;这里提到的Margin是指与分类的超平面距离最近的样本点(支持向量)之间的距离,为了让模型能够在Unseen Data上表现尽可能地好,因此需要让这个Margin尽可能地大;

​ 在硬间隔SVM中,为了使得间隔最大,我们要找到满足KaTeX parse error: Undefined control sequence: \norm at position 38: …b} \frac{1}{2} \̲n̲o̲r̲m̲{\bold{w}}^2的最优的w\bold{w}w和b,使得y(l)(wTx+b)≥1, forl=1,2,...,Ny^{(l)}(\bold{w}^T\bold{x}+b)\geq1 ,\ for \ l=1,2,...,Ny(l)(wTx+b)≥1, for l=1,2,...,N 成立;而在软间隔SVM中,为了使得间隔最大,而又要考虑松弛变量,我们要找到满足KaTeX parse error: Undefined control sequence: \norm at position 38: …b} \frac{1}{2} \̲n̲o̲r̲m̲{\bold{w}}^2 + …(这里的C是惩罚系数,用来控制惩罚力度)使得y(l)(wTx+b)≥1−ξn, forl=1,2,...,Ny^{(l)}(\bold{w}^T\bold{x}+b)\geq1-\xi_n ,\ for \ l=1,2,...,Ny(l)(wTx+b)≥1−ξn​, for l=1,2,...,N 成立;

​ 总之,在线性可分时,在原空间寻找两类样本的最优分类超平面。在线性不可分时,加入松弛变量并通过使用非线性映射(核函数)将低维度输入空间的样本映射到高维度空间使其变为线性可分,这样就可以在该特征空间中寻找最优分类超平面。SVM 的特性是 “支持向量” , 即线性超平面只由少数 “支持向量” 所决定。

2) 采⽤不同核函数的模型和性能⽐较及分析

在本次实验中,采用skearn包中提供的SVM模型;

  1. 线性核函数

相关代码:

SVM Train

def svm_train(path, kernel):classifiers = []trainset = pandas.read_csv(path)label = trainset.values[:, 0]data = trainset.values[:, 1:]for k in kernel:clf = svm.SVC(kernel='linear').fit(data, label)train_score = clf.score(data, label)print("The train accuracy under kernel %s is %f: " % (clf.kernel, train_score))classifiers.append(clf)return classifiers

这里使用了sklearn svm中的SVC模型来进行训练,采用线性核函数,并且调用fit来计算出超平面,且所有相关属性都保存在了分类器 clf中;

实验结果:

从训练和测试的准确度来看,分别取得了1和0.999054的分数;

线性核函数的时候在训练集上的准确度达到了1,但是在测试集上的表现却相对来说没那么好,因此估计在使用线性核函数的时候,有可能出现了过拟合的现象。

故考虑对惩罚系数C进行调整,当C比较小时,意味我们不想理那些离群点,会选择较少的样本来做支持向量,最终的支持向量和超平面的模型也会简单:

def svm_train(path, kernel):classifiers = []trainset = pandas.read_csv(path)label = trainset.values[:, 0]data = trainset.values[:, 1:]for k in kernel:clf = svm.SVC(kernel=k, C=0.0000001).fit(data, label)train_score = clf.score(data, label)print("The train accuracy under kernel %s is %f: " % (clf.kernel, train_score))classifiers.append(clf)return classifiers

最后发现,在C为0.0000001的时候,模型在测试集上表现得比之前更好,达到了0.999527的分数

这有可能是因为SVM在训练的过程中,超平面的划分对训练集中的数据的要求没有那么大了,它会尽可能地最大化Margin,而不是尽可能地让所有数据都能够被区分开(而牺牲了Margin的最大化,相当于牺牲了Generalization),因此它会在测试集上表现得比之前C=1的时候要好。

  1. ⾼斯核函数

SVM Train

def svm_train(path, kernel):classifiers = []trainset = pandas.read_csv(path)label = trainset.values[:, 0]data = trainset.values[:, 1:]for k in kernel:clf = svm.SVC(kernel='rbf').fit(data, label)train_score = clf.score(data, label)print("The train accuracy under kernel %s is %f: " % (clf.kernel, train_score))classifiers.append(clf)return classifiers

这部分代码与上面类似,使用了sklearn svm中的SVC模型来进行训练,这里采用高斯核函数;

实验结果:

在默认参数下取得的准确度如下:

在训练集和测试集上,分别取得了0.999921和0.999527的分数;

  1. 在不同kernel下SVM的表现:

综上我们发现:

SVM模型在核函数为高斯核函数的时候,在测试集上表现最好(0.999921),而使用线性核函数的时候在训练集上的准确度达到了1,但是在测试集上的表现却相对来说没那么好,因此估计在使用线性核函数的时候,有可能出现了过拟合的现象,最后通过调整惩罚系数C,让SVM尽可能地最大化Margin,而不是关注于将训练集中的数据完美地区分开。

参数调整:

(1)网格搜索

model = svm.SVC()
params = [{'kernel': ['linear'], 'C': [1, 10, 100, 1000]},{'kernel': ['poly'], 'C': [1, 10], 'degree': [2, 3]},{'kernel': ['rbf'], 'C': [1, 10, 100, 1000],'gamma': [1, 0.1, 0.01, 0.001]}]
model = GridSearchCV(estimator=model, param_grid=params, cv=5, n_jobs=8)
model.fit(data, label)print("模型的最优参数:", model.best_params_)
print("最优模型分数:", model.best_score_)
print("最优模型对象:", model.best_estimator_)

使用了8个进程跑,速度十分慢;

最后得到了:

使用搜索出来的参数进行测试:

def svm_train(path, kernel):classifiers = []trainset = pandas.read_csv(path)label = trainset.values[:, 0]data = trainset.values[:, 1:]for k in kernel:# clf = svm.SVC(kernel=k).fit(data, label)clf = svm.SVC(kernel='poly', degree=2).fit(data, label)train_score = clf.score(data, label)print("The train accuracy under kernel %s is %f: " % (clf.kernel, train_score))classifiers.append(clf)return classifiers

得到的准确度如下

反而比高斯核函数在测试集上的准确率要来得低

3) 采⽤ hinge loss 的线性分类模型和 SVM 模型之间的关系

Hinge Loss的公式为:L(z)=max(0,1−z)L(z) = max(0, 1-z)L(z)=max(0,1−z) z在这里为yy^y \hat{y}yy^​, y^=xw\hat{y}=\bold{xw}y^​=xw指的是分类结果,也就是说,如果样本被正确分类,那么它的Hinge Loss为0,否则就是1−yy^1- y\hat{y}1−yy^​

对Hinge Loss求梯度可得:

KaTeX parse error: Undefined control sequence: \part at position 7: \frac{\̲p̲a̲r̲t̲(L(\bold{w}))}{…

Hinge Loss的图像如下:

对采用Hinge Loss的线性分类器进行训练,使用的参数为:

num_epochs = 360
learning_rate = 0.00001

需要注意的是,在原数据集中标签采用的都是0和1,但是在hinge loss中所关注的标签为-1和1,所以在使用Hinge Loss之前需要将标签转换为-1和1两类

使用Hinge Loss的线性分类器所得到的准确率约为0.996217

  • 它们两者之间的关系:

​ 在SVM中,软间隔SVM所使用的松弛变量就是hinge loss,即KaTeX parse error: Undefined control sequence: \norm at position 38: …b} \frac{1}{2} \̲n̲o̲r̲m̲{\bold{w}}^2 + …,其中ξn\xi_nξn​就是L(z)=max(0,1−yiyi^)L(z) = max(0, 1-y_i\hat{y_i})L(z)=max(0,1−yi​yi​^​)

​ 它用来表示样本偏离支持向量的距离,允许SVM在一些样本上出错,而在这里,我们则是求Hinge loss的梯度,利用梯度下降的方法逐步地来更新参数,我认为,在SVM中,由于其特性,其超平面的确定只由支持向量来决定(和分类最相关的少数点,考虑局部),其余大多数样本都不需保留,而采⽤ hinge loss 的线性分类模型则相反,它考虑了所有训练样本(考虑全局)。

4)采⽤ hinge loss 线性分类模型和 cross-entropy loss 线性分类模型⽐较

Cross-entropy Loss的公式为:L(w)=−ylog(σ(xw))−(1−y)log(1−σ(xw))L(\bold{w}) = -ylog(\sigma(\bold{xw}))-(1-y)log(1-\sigma(\bold{xw}))L(w)=−ylog(σ(xw))−(1−y)log(1−σ(xw))

其梯度为:

现采用线性分类模型:

f(x)=σ(xw+b)f(\bold{x}) = \sigma(\bold{xw}+b)f(x)=σ(xw+b)

对分别采用Hinge loss和Cross Entropy Loss的线性分类器进行训练,使用的参数都为:

num_epochs = 360
learning_rate = 0.00001

这里学习率使用0.0001的原因是在cross-entropy loss 线性分类模型中,如果设置太大的学习率,在求解loss的时候因为梯度变化得太快,极容易出现上溢,因此这里调低了学习率,减小梯度变化的速度。

而对于W和B,采用了如下的方式来初始化:

W = np.random.normal(0, 0.01 ** 2, (in_feature,))  # Gaussian Distribution (一维数组,有1行,in_feature列)
B = 0

这里的W使用被广泛认为不错的初始化值即:均值为0,方差为0.01^2的高斯分布。

使用Hinge Loss的线性分类器所得到的准确率约为0.995745

使用Cross Entropy Loss的线性分类器所得到的准确率约为0.999527

  • 实验分析

    • 在同一参数下,我们发现,使用Cross Entropy Loss的线性分类器的准确率要相对高一些;
    • Hinge Loss会相对来说更关注那些被错误分类的样本,对于那些正确分类的样本的损失为0,而错误分类的样本,其损失呈线性增长;对于Cross Entropy Loss来说,我们可以从它的图像可以知道,它是一个凸函数,只存在一个最优点,没有局部最优解,便于优化。

4. 实验总结

在本次实验中,我总结了SVM的基本理论,并且针对SVM的不同核函数(包括线性核函数和高斯核函数)针对其性能进行⽐较和分析,之后又引入了线性分类模型(分别采用hinge loss 和cross-entropy loss)对不同的Loss的性能进行比较和分析。

综合来说,从我的实验结果来看,对于该数据集,在测试集上分类性能最好的是采用高斯核函数的SVM,达到了0.999921的分数,而在于两种线性分类器之间来比较的话,使用cross-entropy loss的线性分类模型性能最好,达到了0.999527的分数,其在较高的学习率时,容易使得梯度上溢,通过降低学习率后,能够有效地解决该问题;在采用线性核函数的SVM中,我发现了它在训练集上过拟合的问题,通过调整惩罚系数后,其在测试集上的表现有所提升。

这次实验给我提供了一次实践的机会,让我能够将学习到的知识运用到现实当中,我对SVM的理解又更进了一步,对SVM以及其他线性分类器的区别,以及不同损失函数的选择,超参数的调整都有了更深刻的理解。

【机器学习】SVM支持向量机在手写体数据集上进行二分类、采⽤ hinge loss 和 cross-entropy loss 的线性分类模型分析和对比、网格搜索相关推荐

  1. 详解SVM支持向量机算法(四:坐标上升和SMO算法)

    作者:RayChiu_Labloy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 目录 背景 坐标上升算法 定义 过程 举个求解的栗子 基于坐标上升的SMO算法 SMO ...

  2. 支持向量机python代码_Python机器学习SVM支持向量机算法理论 | kTWO-个人博客

    PS:这篇文章讲的是SVM的算法的基础理论知识,因为博主也是刚学习没多久,对SVM的数学思想了解的不是很深,所以这篇文章就简单介绍一下什么是SVM以及SVM是怎么工作的. 1.什么是支持向量机(SVM ...

  3. 几种机器学习常用调参方式对比(网格搜索,随机搜索,贝叶斯优化)

    网格搜索(GridSearchCV): grid search就是穷举,穷举所有得超参组合 Ex:当对决策树调参,若只对一个超参优化,如树的最大深度,尝试[3,5,7],则可表示为 若还想对分裂标准进 ...

  4. SVM支持向量机sklearn-wine红酒数据集代码V1

    import numpy as np import matplotlib.pyplot as plt from sklearn import svm from sklearn.datasets imp ...

  5. Lesson 6.5Lesson 6.6.1Lesson 6.6.2 机器学习调参基础理论与网格搜索多分类评估指标的macro与weighted过程GridSearchCV的进阶使用方法

    Lesson 6.5 机器学习调参基础理论与网格搜索 在上一小节执行完手动调参之后,接下来我们重点讨论关于机器学习调参的理论基础,并且介绍sklearn中调参的核心工具--GridSearchCV. ...

  6. CS231n 第一讲 线性分类:SVM,Softmax

    Linear classification: Support Vector Machine, Softmax 文章目录 [Linear classification: Support Vector M ...

  7. 机器学习代码实战——网格搜索和交叉验证(GridSearchCV)

    文章目录 1.实验目的 2.导入必要模块并读取数据 3.构建模型-参数字典 4.训练 5.打印不同模型.不同参数对应的结果 1.实验目的 (1)运用GridSearchCV比较不同的模型.不同的参数对 ...

  8. 【笔记】【机器学习基础】网格搜索

    通过调参来提升模型的泛化性能 网格搜索:尝试我们关心的参数的所有可能组合 一.简单网格搜索 在 2 个参数上使用 for 循环,对每种参数组合分别训练并评估一个分类器 # 简单的网格搜索实现 from ...

  9. 简单粗暴理解与实现机器学习之K-近邻算法(十):交叉验证,网格搜索(模型选择与调优)API、鸢尾花案例增加K值调优

    K-近邻算法 文章目录 K-近邻算法 学习目标 1.10 交叉验证,网格搜索 1 什么是交叉验证(cross validation) 1.1 分析 1.2 为什么需要交叉验证 **问题:那么这个只是对 ...

最新文章

  1. 算法了解:RCNN、SPP-Net、Fast-RCNN、Faster-RCNN
  2. Java基础-重写方法
  3. SAP Spartacus build error之后的retrigger方式
  4. spring react_使用Spring Cloud Gateway保护React式微服务
  5. Webpack 知识点总结
  6. POJ2955Brackets——dp
  7. 我是如何用CSS绘制各种形状的
  8. 机器学习5-支持向量机
  9. 力扣-724 寻找数组的中心索引
  10. MYSQL当前时间与数据库里数据时间做比较
  11. 制作python模块安装包[转载自刘天斯]
  12. 数据挖掘十大经典算法之——SVM 算法
  13. java判断日期是否是本月_Java写一个函数判断一个日期是否在本月之内
  14. 2021年房地产经纪行业发展研究报告
  15. matlab汽车牌的识别,matlab车牌号识别
  16. 微信小程序内置在线客服
  17. ffmpeg去除视频黑边命令
  18. php汽车保养oa,汽车行业oa管理系统
  19. CodeForces Round #554 Div.2
  20. Shiro登录的使用以及原理(一)

热门文章

  1. mysql开发cms_GitHub - johnsonzhu/yzmcms: YzmCMS是由袁志蒙独自开发的一款基于PHP+Mysql架构的轻量级开源内容管理系统。...
  2. 亲密关系科学(06)DISC性格优劣势分析
  3. 【5GC】开源5G核心网(Open5GS)架构详解
  4. 机器学习——时间序列(二)
  5. java上课听不懂怎么办_如何快速渡过上课听不懂阶段?
  6. 最新屈绍航博客官网怎么进?
  7. Java高频面试题汇总(2022)
  8. Firefox下载含空格的文件
  9. JavaSE-09 Thread 多线程
  10. 逐帧动画效果——简单篇