最优化基础:损失函数可视化、折页损失函数 & 梯度计算

来源:互联网 发布:鉴知往来的意思 编辑:程序博客网 时间:2024/05/16 04:42

  本文主要内容为 CS231n 课程的学习笔记,主要参考 学习视频 和对应的 课程笔记翻译 ,感谢各位前辈对于深度学习的辛苦付出。在这里我主要记录下自己觉得重要的内容以及一些相关的想法,希望能与大家多多交流~

1. 损失函数可视化

  在高维度的空间中(比如,在CIFAR-10中一个线性分类器的权重矩阵大小是[10x3073],就有30730个参数),这样要将其可视化就很困难。然而办法还是有的,在1个维度或者2个维度的方向上对高维空间进行切片,就能得到一些直观感受。例如,随机生成一个权重矩阵W,该矩阵就与高维空间中的一个点对应。然后沿着某个维度方向前进的同时记录损失函数值的变化。换句话说,就是生成一个随机的方向 W1 并且沿着此方向计算损失值,计算方法是根据不同的a值来计算 L(W+aW1) 。这个过程将生成一个图表,其x轴是a值,y轴是损失函数值。同样的方法还可以用在两个维度上,通过改变a,b来计算损失值 L(W+aW1+bW2) ,从而给出二维的图像。在图像中,a,b可以分别用x和y轴表示,而损失函数的值可以用颜色变化表示


图 1. 一个无正则化的多类SVM的损失函数的图示

左边和中间只有一个样本数据,右边是CIFAR-10中的100个数据。左:a值变化在某个维度方向上对应的的损失值变化。中和右:两个维度方向上的损失值切片图,蓝色部分是低损失值区域,红色部分是高损失值区域。注意损失函数的分段线性结构。多个样本的损失值是总体的平均值,所以右边的碗状结构是很多的分段线性结构的平均(比如中间这个就是其中之一)。

2. 折页损失函数的分段线性证明

  对于一个单独的数据,有损失函数的计算公式如下:

Li=jyi[max(0,wTjxiwTyixi+1)]

通过公式可见,每个样本的数据损失值是以W为参数的线性函数的总和(零阈值来源于max(0,-)函数)。W的每一行(即wj),有时候它前面是一个正号(比如当它对应错误分类的时候),有时候它前面是一个负号(比如当它是是正确分类的时候)。为进一步阐明,假设有一个简单的数据集,其中包含有3个只有1个维度的点,数据集数据点有3个类别。那么完整的无正则化SVM的损失值计算如下:

L0=max(0,wT1x0wT0x0+1)+max(0,wT2x0wT0x0+1)

L1=max(0,wT0x1wT1x1+1)+max(0,wT2x1wT1x1+1)

L2=max(0,wT0x2wT2x2+1)+max(0,wT1x2wT2x2+1)

L=(L0+L1+L2)/3

因为这些例子都是一维的,所以数据 xi 和权重 wj都是数字。观察 w0,可以看到上面的式子中一些项是 w0 的线性函数,且每一项都会与0比较,取两者的最大值。可作图如下


图 2. 从一个维度方向上对数据损失值的展示

  x轴方向就是一个权重,y轴就是损失值。数据损失是多个部分组合而成。其中每个部分要么是某个权重的独立部分,要么是该权重的线性函数与0阈值的比较。完整的SVM数据损失就是这个形状的30730维版本。

  需要多说一句的是,你可能根据SVM的损失函数的碗状外观猜出它是一个凸函数。但是一旦我们将f函数扩展到神经网络,目标函数就就不再是凸函数了,图像也不会像上面那样是个碗状,而是凹凸不平的复杂地形形状。

  不可导的损失函数。作为一个技术笔记,你要注意到:由于max操作,损失函数中存在一些不可导点(kinks),这些点使得损失函数不可微,因为在这些不可导点,梯度是没有定义的。但是次梯度(subgradient)依然存在且常常被使用。

3. 三个初始的最优化方法

  损失函数可以量化某个具体权重集W的质量。而最优化的目标就是找到能够最小化损失函数值的W 。我们现在就朝着这个目标前进,实现一个能够最优化损失函数的方法。

策略#1:一个差劲的初始方案:随机搜索

  尝试若干随机生成的权重矩阵W,其中某些的损失值较小,而另一些的损失值大些。我们可以把这次随机搜索中找到的最好的权重W取出,然后去跑测试集准确率是15.5%,而完全随机猜的准确率是10%,如此看来,这个准确率对于这样一个不经过大脑的策略来说,还算不错嘛!

策略#2:随机本地搜索

  第一个策略可以看做是每走一步都尝试几个随机方向,如果某个方向是向山下的,就向该方向走一步。这次我们从一个随机W开始,然后生成一个随机的扰动 δW,只有当 W+δW 的损失值变低,我们才会更新。使用同样的数据(1000),这个方法可以得到21.4%的分类准确率。这个比策略一好,但是依然过于浪费计算资源。

策略3:跟随梯度

  前两个策略中,我们是尝试在权重空间中找到一个方向,沿着该方向能降低损失函数的损失值。其实不需要随机寻找方向,因为可以直接计算出最好的方向,这就是从数学上计算出最陡峭的方向。这个方向就是损失函数的梯度(gradient)。在蒙眼徒步者的比喻中,这个方法就好比是感受我们脚下山体的倾斜程度,然后向着最陡峭的下降方向下山。

  在一维函数中,斜率是函数在某一点的瞬时变化率。梯度是函数的斜率的一般化表达,它不是一个值,而是一个向量。在输入空间中,梯度是各个维度的斜率组成的向量(或者称为导数derivatives)。对一维函数的求导公式如下:

df(x)dx=limh0f(x+h)f(x)h

当函数有多个参数的时候,我们称导数为偏导数。而梯度就是在每个维度上偏导数所形成的向量。

4. 梯度计算

  计算梯度有两种方法:一个是缓慢的近似方法(数值梯度法),但实现相对简单。另一个方法(分析梯度法)计算迅速,结果精确,但是实现时容易出错,且需要使用微分。现在对两种方法进行介绍

4.1 数值梯度法

  即通过使用差分公式来计算梯度。实际中用中心差值公式(centered difference formula)[f(x+h)f(xh)]/2h效果较好。但是计算数值梯度的复杂性和参数的量线性相关,现代神经网络很容易就有上千万的参数,因此这个问题只会越发严峻。显然这个策略不适合大规模数据,我们需要更好的策略。

4.2 分析梯度法

  使用有限差值近似计算梯度比较简单,但缺点在于终究只是近似,且耗费计算资源太多。第二个梯度计算方法是利用微分来分析,能得到计算梯度的公式(不是近似),用公式计算梯度速度很快,唯一不好的就是实现的时候容易出错。为了解决这个问题,在实际操作时常常将分析梯度法的结果和数值梯度法的结果作比较,以此来检查其实现的正确性,这个步骤叫做梯度检查

4.2.1 梯度下降

  单纯看梯度下降,其主要有使用全体数据进行训练的梯度下降法,使用数据中的每一个数据计算梯度的随机梯度下降法(SGD),以及一次使用数据中的一部分数据的小批量数据梯度下降法(Mini-batch grandient descent,有时也简称 SGD)。具体方法是如何实现的以及梯度下降法的各种变形,请参考《十一、改变神经网络的学习方法(5):随机梯度下降的变化形式(Adagrad、RMSProp、Adadelta、Momentum、NAG)》。

  为什么小批量随机下降的效果会好于梯度下降和随机梯度下降呢?这个方法之所以效果不错,是因为训练集中的数据都是相关的。要理解这一点,可以想象一个极端情况:在 ILSVRC 中的120万个图像是1000张不同图片的复制(每个类别1张图片,每张图片有1200张复制)。那么显然计算这1200张复制图像的梯度就应该是一样的。对比120万张图片的数据损失的均值与只计算1000张的子集的数据损失均值时,结果应该是一样的。实际情况中,数据集肯定不会包含重复图像,那么小批量数据的梯度就是对整个数据集梯度的一个近似。因此,在实践中通过计算小批量数据的梯度可以实现更快速地收敛,并以此来进行更频繁的参数更新。

  在我看来,上面的内容实际还包括另外一层含义。因为小批量数据的梯度就是对整个数据集梯度的一个近似,所以数据中的相似的数据比较多的话,那么近似梯度与实际梯度就会越相近。所以在实际应用中,我们常常将数据进行旋转平移等几何变换来增加数据的数量,从刚刚讲述的观点就可以很明显的解释着这样做的原因了。因为拓展数据后。不仅仅使得数据量增加,可以在一定程度上抑制过拟合,更重要的是被拓展的数据是高度相关的,这一点也使得它更适用于小批量随机梯度下降(近似梯度与实际的梯度更加相似)。