目录
前言
SVM(支持向量机)算法属于机器学习的监督学习类算法,需要用已知数据训练模型并且用模型来预测未知数据,而SVM主要是对数据进行非线性或者线性分类,你可以从本篇文章中了解全向量化损失函数的实现,解析梯度的全矢量化表达式,如何用数值梯度检查实施,如何用验证集调整学习率和正则化强度,以及用SGD来刷新参数来降低损失函数,最后可视化学习权重。
一、基本概念介绍
二次规划是一种特殊的数学优化问题,它的目标函数是一个二次函数,而约束条件是一些线性方程或者不等式。二次规划可以用来求解一些最小化或者最大化的问题,比如最小二乘法、支持向量机、投资组合优化等。二次规划有很多种求解方法,比如内点法、梯度投影法、序列二次规划法等。
线性可分的数据,线性SVM通过在特征空间中寻找一个超平面来对数据进行分类。这个超平面能够最大化两个类别之间的边界,从而实现对数据的分类。
非线性数据,我们可以使用非线性SVM来处理。非线性SVM通过使用核函数将原始特征空间映射到一个更高维度的空间,在这个新的空间中,原本不可分的数据可能变得线性可分
简单来说,线性SVM适用于线性可分的数据,而非线性SVM适用于非线性数据。非线性SVM通过使用核函数将数据映射到更高维度的空间,使得原本不可分的数据变得可分。
核函数是一种用于将数据从原始特征空间映射到更高维度空间的数学工具。常用的核函数包括线性核、多项式核、径向基函数(RBF)核和Sigmoid核等。
下面是这些常用核函数的公式:
- 线性核:$K(x,y) = x^Ty + c$
- 多项式核:$K(x,y) = (x^Ty + c)^d$
- 径向基函数(RBF)核:$K(x,y) = exp(-\gamma||x-y||^2)$
- Sigmoid 核:$K(x,y) = tanh(\alpha x^Ty + c)$
其中,$x$ 和 $y$ 是两个数据点,$c$, $d$, $\gamma$, 和 $\alpha$ 是参数。
选择合适的核函数对于支持向量机模型的性能至关重要。
向量化损失函数是指使用矩阵运算来计算损失函数,而不是逐个样本进行计算。这样可以大大提高计算效率。
正则化是一种用于防止过拟合的技术。在机器学习中,过拟合指的是模型在训练数据上表现得很好,但在测试数据上表现不佳的情况。
为了防止过拟合,我们可以在损失函数中加入一个正则化项。这个正则化项会惩罚模型的复杂度,使得模型更倾向于选择简单的解决方案。
常用的正则化方法包括 L1 正则化和 L2 正则化。L1 正则化通过惩罚权重矩阵 $W$ 的 L1 范数来实现正则化;而 L2 正则化通过惩罚权重矩阵 $W$ 的 L2 范数来实现正则化。
选择合适的正则化系数对于模型性能至关重要。通常,我们可以使用交叉验证来确定最佳的正则化系数。
四种数据集的关系
- 训练集:用于训练模型的参数,使模型能够拟合数据。
- 验证集:用于评估模型的效果,调整模型的超参数,选择最优的模型。
- 测试集:用于最终检验模型的泛化能力,评估模型在未知数据上的表现。
- 开发集:也叫做交叉验证集,是从训练集中划分出来的一部分数据,用于在训练过程中多次验证模型的性能,避免过拟合或欠拟合。
一般来说,数据集可以按照0.6:0.2:0.2或者0.8:0.1:0.1的比例划分为训练集、验证集和测试集。开发集可以根据需要从训练集中抽取一定比例(如10%)作为交叉验证。
测试集是用来评估模型在未知数据上的泛化能力的数据集。测试集通常有两种划分方式,一种是X,一种是Y。X表示输入特征,如图像、文本、音频等;Y表示输出标签,如分类、回归、聚类等。测试集的划分要保证X和Y之间的对应关系,即每个输入特征都有一个正确的输出标签。例如,如果要测试一个图像分类模型,那么测试集就要包含一些图像(X)和它们对应的类别(Y)。划分测试集的目的是为了检验模型是否能够正确地预测出未见过的数据的标签。
数据的预处理是指在主要的分析或挖掘之前对数据进行的一些处理,以保证数据质量能满足任务的要求数据预处理包括数据清洗、数据集成、数据变换和数据规约等步骤
去均值化的作用是:
·使得输入数据各个维度都中心化为0,减少数据的偏移降低数据的方差,避免某些维度对模型的影响过大加快模型的收敛速度,避免出现′Z型更新"的情况。
数值计算方法和分析计算方法是两种求解数学问题的不同方式。
分析计算方法是利用公式分解或化简,直接得到问题的精确解或符号解。
数值计算方法是利用数值近似或迭代,得到问题的沂似解或数值解。数值计算方法通常用于那些无法用分析计算方法求解或求解困难的问题,例如微分方程、积分方程、非线性方程等。
dot()函数是nump库的一个函数,王要用于矩阵的乘法运算,包沽向量内积量、多维向量相乘和矩阵与向量的乘法
·当两个参数都是一维数组时,dot()函数计算它们的内积(点积)。413·当两个参数都是二维数组时,dot()函数计算它们的矩阵乘积。
当一个参数是二维数组,另一个参数是一维数组时,dot()函数计算它们的矩阵与向量的乘积。
二、使用步骤
1.导入数据集和相应的库函数
(第一张图利用plt绘图准备画布大小背景颜色并且利用jupytor的魔术工具在每次运行前自动的导入数据,第二张图是将下载好的cs231n的图片数据集导入,建立训练测试集,显示相匹配的数目即大小,比如说训练集是50000张图片按照32*32*3大小构建的array,利用的shape函数)
2.可视化数据集,每一类随机选取7张图片
(创建classes的集合,列入10种类别,每种类别随机选取对应特征的7张图片然后利用enumerate枚举函数将列表的元素和索引循环出,利用flatnonzero函数将找到训练集中对应的y的序列,函数如果括号里面条件成立则为1,否为0,因此plt_idx=(1/0)*10一行10个,
这个代码是用于绘制多个子图的,plt_idx是每个子图的位置。plt.subplot()函数需要三个参数,分别是行数、列数和位置。例如,plt.subplot(2,3,4)表示在一个2行3列的画布上绘制第4个子图。
plt_idx = i * num_classes + y + 1是一种计算每个子图位置的公式,其中i是样本编号,y是类别编号,num_classes是类别总数。+1是因为Python中的索引从0开始,而plt.subplot()函数中的位置从1开始。所以要加上1来对齐。
得到7张随机元素组成的列表,再来一层循环从而实现用plt.subplot(行,列,图片位置)利用imshow显示二值函数的同时将其格式利用astype转化为uint8的格式便于之后文件夹图片的导出,关闭轴线和标签,当i=0时候首先显示名称,最后在同一show出处理的图片)
3.对数据库进行划分
(取训练集49000,验证集1000张,测试集1000张,开发集500张,mask是在训练集随机抽取一部分不重复的索引来创建开发集,range是返回0到999的整数索引,由此创建xy对应的测试集,x是特征,y放标签,训练集的创建与其原理相同,最后再显示矩阵的形状看是否对应统一)
(将训练集和测试集以及开发集进行数据的预处理,这段代码的意思是将X_train这个数组重新调整为一个新的形状,不改变它的数据。np.reshape是一个numpy函数,它接受三个参数:数组、新的形状和顺序。在这段代码中,新的形状是(X_train.shape[0],-1),表示将X_train变成一个有X_train.shape[0]行的二维数组,列数由数组元素总数自动计算出来。顺序默认为’C’,表示按行优先的方式展开和填充元素)
(·首先,计算x_train数组沿着第0个轴(即行方向)的平均值,得到一个一维数组mean_image 1 2。打印前10个元素,然后将mean_image重新调整为(32,32,3)的形状,并转换为无符号整数类型,用plt.imshow函数显示出来。·其次,将mean_image从X_train、X_val、X_test和X_dev中减去,得到去均值化后的数据1。最后,将一个全为1的列向量拼接到X_train、X_val、X_test和X_dev的右边,得到增加了偏置项的数据1。打印出它们的形状。
)
4.计算训练集的损失和数值梯度
(该部分代码已经提供了损失函数,我们需要补充的是损失梯度,如图,W代表的是模型的权重矩阵,xi代表的是样本的特征向量,S是模型对样本的预测分数,L1计算的是损失函数,求导得到的是解析梯度,若有N个样本,则总损失要除N,留意1(条件)xi是指示函数,+1是一种偏置,本身取值对实验没有太大影响,一般取1,。
上面题目的代码是在循环里面做了改动,j是类别之一,如果j=y[i],说明对应的正确标签,其损失为零,所以直接continue,相对如果不等,就是对应的其他标签,计算损失和梯度,之后对总体度要除训练集的总数,另外,最后加正则化的求导,reg就是正则化的系数。)
(这里通过数值计算方法和分析计算方法来计算梯度的差,有一部分误差大是分析计算对分段函数节点处求导导致的误差取了左边的导数。
1.定义了一个匿名函数f,它接受一个参数w,表示权重矩阵,并返回svm_loss_naive函数在w和一些开发数据上计算的损失值(不包括正则化项)2 第二行定义了一个匿名函数f,它接受一个参数w,表示权重矩阵,并返回svm_它接受一个参数_函数在w和一些开发数据上计算的损失值(不包括正则化项)
第三行调用了grad_check_sparse函数,传入了f、W和grad三个参数,分别表示要检查的函数、权重矩阵和分析方法计算的梯度。该函数会返回数值方法计算的梯度,并打印出与分析方法计算的梯度之间的差异。
)
5.用矢量化的方法求解loss和gradient
(依旧以这张原理图为例子,S是得到的分数,由此代表loss,我们假设红色的是标签值,损失是0,所以带入指示函数计算之后要全部清0,这段代码就是先找到标签对应的位置,再对非标签进行指示化的计算,最后计算loss并且加上正则化损失,经过比较我们发现与之前分析法计算的结果一致,但是矢量化的效率更高)
(这里用矢量化求梯度运用了导数的链式法则结构,S是10*N的矩阵,W是10*D的矩阵,X是D*N的矩阵,两边同时求偏导,上面就是三者相互转换的基本思路,运用了线代的知识)
6.利用LinearSVM模型进行数据的更新
( 这段代码的目的是使用LinearSVM模型来对数据进行分类,并选择最佳的学习率和正则化强度。LinearSVM是一种线性支持向量机,它可以用于处理线性可分或近似线性可分的数据。学习率和正则化强度是两个重要的超参数,它们影响模型的训练效果和泛化能力。代码中使用了两层for循环,分别遍历不同的学习率和正则化强度,对每一组参数,创建一个新的LinearSVM模型,并用train方法训练它,返回过去损失,然后用predict方法对验证集和训练集进行预测,并计算预测准确率,将每一组参数及其对应的训练集和验证集准确率存储在results字典中。如果某一组参数的验证集准确率高于当前最佳值,就更新最佳值,并将该模型赋给best_svm变量。)
代码如下(示例):
总结:
svm算法对比上篇的knn算法,能明显感觉到其中的差异,knn算法是依据欧氏距离来计算测试样本和训练样本的距离,根据k个训练样本的标签来决定测试的类别,svm算法是基于间隔,适合处理多维度的的数据分类,找到一个超平面将不同类别分开,knn只有一个参数k,并且没有训练过程,需要大量的计算消耗资源,相对比之下,svm有更多的参数,提高自身的性能同时拥有训练过程预测会更为快速。然而svm对大规模处理训练样本难以实现,它解决的是一个二次规划问题,对参数和核函数的选择通过交叉验证会增加计算量,svm不会有概率输出(显示结果的可信度),只能输出类别标签。
SVM算法本身是一个二值分类器,最初是为二分类问题设计的。当处理多分类问题时,就需要构造合适的多类分类器。目前,构造SVM多类分类器的方法主要有两类:
·一类是直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题”─次性"实现多类分类。
另一类是间接法,利用二值分类器组合成多类分类器,常见的有"一对一”、"一对其余"、“层次树"等方法。