除了得到最小的W之外,如何节省这个探索最优W的过程,也是很重要的一点。假如把这个过程比作从山上的顶点开始下山,把图中必定游玩的经典比作最优权重,那么节省的过程,就是找到下山的最短路径的过程。而在下山的过程中,我们通常会根据脚传来的感觉去判断地面凹凸不平的情况,从而选择地势更矮的部分去下山,我们所走的每一步都是往更低的方向走,且由于每次我们都是选择往最矮的方向走,可以节省很多不必要的力气。
像这种一步一步去判断当前最优的方法,就是我们常说的梯度下降法,而每次选择更低的方向就好比我们在每个x点上,将前后的值作差,并令这个步长接近于0,求得的斜率就是我们每一步要选择的梯度。不过与一维函数不同的是,由于输入的x可能是向量的形式,所以求得的梯度一般都是由偏导数组成的向量,也就能看到在当前向量下的各个方向的最优斜率,从而让模型明确该如何优化。
一般在计算机中,用有限差分法从传统的意义上,通过逼近极限来计算梯度,如下图:
对于每一步的梯度,对计算方向上的数据加0.0001,然后计算改变前后的损失值差除以0.0001来作为这个偏导数。但这个方法相当于要对向量的每一项都进行计算,如果我们在实际应用时,用到的卷积网络很大,向量W可能不只有10个类别,那么要一步步去迭代计算每一项会让我们的函数计算变得非常的缓慢。我们一般采用的方式是直接对梯度的公式进行微分运算,这就相当于我们只需要计算一个公式表达式,剩下的直接带入值即可。不过这并不是说有限差分法不好,用它来计算可以保证结果的准确性(因为其是从定义出发),所以我们会用它来进行调试,在模型训练前选取一些数据分别用微分法和有限差分法计算去对比,从而确认代码的方向无误,我们把前者叫解析梯度,后者叫做数值梯度。
所以在实际使用中,步骤通常是先随机分配权重,去计算当前的损失值、梯度以及梯度相反的方向(从梯度计算公式出发,x是向量时,方向导数是梯度和向量的点积,公式里是取夹角的cos值,也就能知道夹角为0度时其取最大值1,所以梯度的方向是增加函数值的方向),从而确定要怎么更新权重,再重复这一步骤知道损失为0。但在计算梯度时的步长是我们人为设定的(又叫学习率),是每经过多少就要更新权重。为了谨慎,我想很多人都会习惯性往小的参数设置,但并不是说设置一个很小的步长,就一定能获得最优解,因为这很可能会因为步长过小,导致在很小的一段数据里,模型被后续大的梯度误导以为已经求得了最优的权重,类似于在山上到达了一个较小的山谷,但由于四周看不到更矮的地方,就以为自己到了山脚。
不过如果数据集比较大,尽管我们用了很好的优化算法和函数表达,由于梯度下降是计算梯度和,那么每次梯度下降,其实都是相当于做了N次计算,而损失和也需要做N次运算,会使计算过程变得非常缓慢,所以一般我们会取数据集的一小部分取计算梯度来估算整个数据集的梯度,这叫做随机梯度下降,所取得数据集叫minibatch,一般是2的n次幂。
不过在现在的普遍处理中,我们在进行线性分类时,一般都会先进行特征处理,即先对图片的像素做处理,提取出某类特征的数字作为输入,而不是直接把像素转换为向量输入进去。因为线性分类的本质是可以看做在平面图中用直线作为决策边界去划分不同类别,但如果图片的两个类别在平面图中是以圆的形式存在,直线是无法区分的,而转换成特征的形式其实就是把他们变成在平面图上按照类直线排列的形式,这样有助于模型区分。
学习来自于斯坦福教程:Stanford University CS231n: Deep Learning for Computer Vision