科技匠|从理论到实践分析分类问题中为什么不使用均方误差损失函数

导读在神经网络中 , 回归问题通常都是使用均方误差(meansquareerro)MSE作为代价函数 , 而在分类问题中通常都是选择最大似然函数或softmax作为代价函数 , 最大似然函数用于二分类 , softmax用于多分类 , softmax是最大似然函数对于多分类的推广 。
不知道大家有没有想过 , 为什么在分类问题中不使用MSE作为代价函数呢?那么这篇文章就让我们来分析一下为什么在分类问题中不使用MSE作为代价函数 。 本篇文章的结构形式以理论+代码实践的方式来证明 。 代码实践以MXNet来实现 , 所以需要一点基础 。
明确讨论的问题为了帮助大家更好的理解 , 先简单介绍一下分类问题是如何实现的 , 为了简化分析问题我们使用一个单层的二分类模型来分析问题 , 一个单层的二分类模型结构图如下
其实分类问题和回归问题最主要的区别在于 , 对回归问题来说通过全连接层之后就可以直接通过MSE损失函数来计算模型预测值与实际值之间的误差 , 然后通过计算梯度来更新参数 。
而分类问题 , 在全连接层之后还需要通过sigmoid函数 , 目的是将输出归一化到(0,1)范围内 , 然后通过最大似然函数来计算预测值与实际值的误差 , 从而计算梯度更新参数 。 所以 , 模型最终输出是一个(0,1)范围内的概率值 。 sigmoid函数图像如下
通过分析sigmoid函数图像 , 我们可以发现sigmoid函数属于单调递增有界的非凸函数 , 取值范围在(0,1)范围内 。
我们本篇文章讨论的问题是 , 通常对于分类问题而言在sigmoid后是通过最大似然函数损失来作为代价函数 , 而我们能不能将最大似然函数替换为均方误差 。
理论分析在分析一个函数是否能作为代价函数的时候 , 我们主要考虑的是代价函数是不是连续可导 , 从而通过计算梯度来更新参数 , 最小化代价函数 。 除此之外 , 还需要考虑一些代价函数是否具有一些其他的特性 , 如更新参数的速度 , 误差大更新的速度快 , 误差小更新的速度小 。 所以 , 我们主要是通过分析参数的更新来判断代价函数是否合适 , 在推导参数更新的时候需要知道下面几个公式
MSE代价函数参数更新
为了便于分析 , 下面我们绘制一下MSE代价函数的函数图像 , x轴表示z的取值 , y轴表示代价函数f(x) , 因为对于而分类问题来说 , 数据的真实标签y只能是0或1 , 不过为了让大家能够更好的观察出f(x)随z的变化 , 我们将y的取值为0.5
通过MSE代价函数图像可以发现 , 它是一个凹函数最小值为0 , 不过大家仔细观察可以发现当z小于-2.5或z大于2.5时 , 代价函数的梯度(斜率)几乎接近于0(直线) , 所以如果在这个区间参数的更新会将会非常慢 。
接下来我们来看看参数的梯度变化 , 然后再计算绝对误差A与参数梯度之间的关系
接下来我们分析当真实值y取1时 , 绘制误差与参数梯度之间的关系如下图 , 因为误差范围在[0,1]之间所以只需要考虑误差在[0,1]区间内 , 参数梯度的变化
通过观察误差与参数梯度之间的关系可以发现 , 当误差大于0.7以后 , 为了最小化误差A , 参数的梯度需要先由大到小 , 然后再变大才能使得误差A最小化 , 这样显然不利于模型的训练而且会导致需要更多的时间来迭代 , 造成更多的硬件资源的浪费 。 对于真实值y为0的情况大家可以自己
最大似然代价函数参数的更新
为了让大家能够更好的观察出y轴f(x)随x轴z的变化 , 我们将真实值y取0.5 , 观察f(x)随z的变化如下图所示
通过上图可以发现 , 最大似然函数作为代价函数时相对于均方误差函数而言 , 它的梯度区间更广 , 当均方误差函数在z大于2.5或小于-2.5时 , 梯度接近于0 , 而最大似然函数的梯度明显不为0 。
接下来我们分析最大似然函数代价函数的梯度随误差的变化
通过上图可以发现 , 当误差越大时 , 参数的梯度越大 , 参数的更新步伐越大 , 从而使得模型能够更快收敛 。
代码实践上面我们通过理论分析了当代价函数分别为均方误差函数和最大似然函数时 , 损失值随着输入的变化和梯度与误差之间的变化关系 。
接下来 , 我们通过一个二分类来实践一下 。 代码主要是基于mxnet来实现的
首先我们随机生成1000个样本 , 每个样本包含两个特征 , 样本服从均值为0方差为0.5的正态分布 。 然后 , 通过定义边界 , 将1000个样本分为两个不同的类别 , 对于不满足条件的样本直接剔除 。 然后 , 分别定义了最大似然代价函数和均方误差代价函数 。
通过最大似然函数作为代价函数 , 经过10个epoch之后 , 我们可以绘制出数据的分类边界如下图
大家可以尝试着将loss改为square_loss , 然后再跑一下模型 , 可以发现其实模型还是能够收敛 。 准确率和以最大似然函数为边界时毫无差别 。
在理论分析中 , 我们发现当z值过大时 , 以均方误差为代价函数的参数的梯度会接近于0 , 从而会导致模型难以收敛 , 所以接下来我们将w参数的初始化改为均值为10 , 代码如下
w=mx.nd.random.normal(loc=10,scale=0.1,shape=(input_x.shape[1],1),dtype=np.float64)可以发现 , 当以均方误差为代价函数时 , 经过10个epoch之后模型在测试集上的准确率只有19% , 而且模型的收敛速度很慢 。 当以最大似然函数为代价函数时 , 经过大约6个epoch模型在测试集上的准确率就可以达到100% , 而且模型的收敛速度非常快 。