5.2.2 平滑过程
通过在程序中添加S型函数,我们引入了一个比较棘手的问题,因为我们降低了梯度下降算法的可靠性。当更改系统中的loss()函数以便使用新的分类代码时,就会出现如下问题:
这个函数乍一看与我们之前得到的loss()函数几乎相同,输出的预测值与实际标签值之间的均方误差。这个函数与以前loss()函数唯一的区别就在于,对forward()的调用取代了对predict()函数的调用。
这个变化却有着深远的影响。forward()函数涉及S型函数的计算,正是由于这个S型函数,使得现在的损失函数与之前的损失函数有着很大的差别。下图是新的损失函数的图像:
看来我们有麻烦了。看到那些直通洞穴的峡谷了吗?我们在介绍梯度下降算法时曾提到过这些洞穴,它们是可怕的局部最小值。你还记得梯度下降算法的目标方向是下坡吗?现在考虑一下,如果梯度下降的迭代计算进入一个局部最小值会发生什么情况,因为一个洞穴的底部没有“下坡”,此时这个算法就停在洞穴的底部,错误地以为已经达到了它想要达到的全局最小值。
我们可以从上面的图像中得出这样的结论:如果同时使用均方误差和S型函数,那么所产生的损失函数图像就会是一个不均匀的表面,上面布满了局部最小值。显然,很难对这样的表面使用梯度下降算法。我们最好能够找到另外一个能够进行分类的损失函数,且具有更光滑、更有利于梯度下降算法的表面。
我们可以在统计学教科书中找到这样一个函数,通常称之为log损失函数,它的名称来源于对数函数,如下所示:
log损失函数的计算公式看起来可能会比较可怕,但是不要被它吓倒。你只需要知道它是一个不错的损失函数就行了,预测值越接近实际值y,损失就越低。同样,当你把公式转换成代码时,这个公式更容易懂了,如下所示:
如果你愿意尝试一下,就会发现log损失函数比看起来更加简单。记住,矩阵Y中每个标签值不是0就是1。对于等于0的标签值,第一项乘以0,所以它就消失了。对于等于1的标签值,第二项因为乘以(1-Y)就消失了,所以Y的每个元素只贡献了这两项中的一项。
让我们绘制出log损失函数的图像,看看它是什么样子的:
美观且平滑的图像!没有峡谷,没有平坦的地区,也没有洞穴。从现在开始,这就是我们的损失函数。