
2.5 使用keras
实际的模型在训练过程中,尤其是在深度学习中,参数会达到几千万个,参数空间会变得非常庞大,为了更好帮助大家理解优化算法,我们先用一维的损失函数,因为一维的坐标下降和基于梯度的更新都是在同一个方向上进行搜索,更容易理解。我们假设损失对于参数是一个非常简单的二次函数:

它的一阶导数为:

根据梯度下降的方法,我们设定参数的初始值和较大的学习率,并将每一步的迭代用箭头表示出来,可以将代码写作:

如图2.5,我们设置学习率为0.87,迭代20次虽然可以迭代到最低点,但是每一次的迭代都是在最低点的震荡,这表明学习率仍然是很大的。

图2.5 学习率较大的时候,损失函数的迭代结果
所以我们可以将学习率设置得小一点:

如图2.6,学习率较小的时候,迅速迭代到了极小值。这一结果告诉我们,一个恰当的学习率对于基于梯度的优化算法是非常重要的。
我们接下来来尝试牛顿法,需要注意到此时的损失函数的二阶导数是一个常数,如果我们直接利用牛顿法的更新公式:

就会发现此时的牛顿法不过是另一个学习率下的梯度下降,学习率固定为二阶导数的倒数,如果我们还想要在牛顿法和梯度下降法中看到更多的差别,就需要更换损失函数,为达到此目的,我们在原来损失上添加一个小的三角函数项:

图2.6 学习率较小的时候,损失函数的迭代结果

三角函数的好处在于它的无穷阶不仅可导,而且不会成为常数,同时也不会对原来函数的形状有太大的影响,根据理论,牛顿法可以一步迭代到目标值。因为牛顿法需要利用二阶导数的信息,所以我们需要事先设定好一阶导函数和二阶导函数,在此基础上,我们延续上面的框架,可以写出:

如图2.7,牛顿法一步就到达了最优点,后续的迭代不会起到作用,因为最优点的一阶导数为零。

图2.7 牛顿法的迭代结果
但这并不意味着牛顿法是好的算法,在高维空间中计算海森矩阵的逆时间复杂度较高,更是因为牛顿法要执行下降到极小值,需要保证海森矩阵的正定,这一性质需要进行严格检验。我们只保留三角函数项作为损失:

我们需要将函数以及其一阶导数,二阶导数更改为:

同时我们注意到原来的初始点-20刚好是一个极值点,这意味着我们无法进行迭代,所以我们也更改初始参数值:

如图2.8,牛顿法在此时的损失和迭代初始值条件下,反而执行了上升的步骤,迭代至极大值就停止,这说明海森矩阵的性质对于牛顿法的具体执行有着绝对的影响。

图2.8 海森矩阵非正定时,牛顿法的迭代结果
而我们在这种情况下执行梯度下降的时候,如图2.9,梯度下降可以缓慢迭代至极小值点。从这个角度去理解牛顿法我们会发现,当海森矩阵为负定时,相当于梯度下降的学习率为负的,损失函数反而会上升,而梯度下降的学习率为事先指定为正值。

图2.9 海森矩阵非正定时,梯度下降的迭代结果
如果我们真的想使用牛顿法来作为优化算法,就可以在多设置几个初始值,或者检查初始值的海森矩阵。但我们还可以采用一种较为优雅的办法,既然海森矩阵的特征值存在为负的可能性,那么我们可以参考统计学习中的岭回归,它通过正则化项强行使样本矩阵满秩,那么我们也可以采用同样的办法使得海森矩阵强行正定:

我们在代码中,就将相应的迭代函数改为:

如图2.10,实行了正则化的牛顿法可以顺利地执行下降步骤,一个小的正则化项可以帮助算法逃离海森矩阵负定的参数点,并且在随后的步骤中起到加速优化的效果。

图2.10 正则化的牛顿法迭代结果