神经网络的学习通过某个指标表示现在的状态,然后以这个指标为基准,寻找最优权重参数,这个指标就是损失函数(loss function)。
如上介绍,神经网络损失函数(loss function)也叫目标函数(objective function)的作用:衡量神经网络的输出与预期值之间的距离,以便控制、调节参数。这个损失函数可以使用任意函数,但一般使用均方误差 和 交叉熵误差。
0. 定义
后续公式中需要使用到的定义:
- y k y_k yk 表示神经网络的输出,即 output
- t k t_k tk 表示监督数据,也就是label
- k k k 表示数据的维数
1. 均方误差
-
均方误差公式:
E = 1 2 ∑ k ( y k − t k ) 2 E=\frac{1}{2} \sum_{k}\left(y_{k}-t_{k}\right)^{2} E=21k∑(yk−tk)2 -
代码实现:
import numpy as np def mean_squared_error(y, t): return 0.5 * np.sum((y-t) ** 2)
-
举例
MNIST手写数字识别程序中中,一张图片的label为2,进行one-hot编码后,可以获得t,其中t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
,假设该图像经过cnn的输出为y:y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
,使用
mean_squared_error(np.array(y), np.array(t))
,经过计算,可以获得:loss = 0.09750000000000003。
2. 交叉熵误差
- 公式
E = − ∑ k t k log y k E=-\sum_{k} t_{k} \log y_{k} E=−k∑tklogyk
其中log表示以e为底数的自然对数( l o g e log_e loge, 即 l n ln ln), l n x ln x lnx函数图像为:
- 通过上图可以看出来:当x介于0 ~ 1时,对应的函数值为负数。在神经网络中,输出值 y k y_k yk介于 0 ~ 1之间,所以公式中有一个负号,使得loss为正。
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
上面实现代码,加上了一个微小的delta,是因为当出现np.log(0)时,np.log(0)会变为负无穷大,添加一个微小值可以防止负无穷大的发生。
使用「均方误差」中的y、t作为参数,调用 cross_entropy_error(np.array(y), np.array(t))
,获得结果 0.510825457099338。
3. mini-batch中的损失函数
为了提高训练效率一般都会在每次迭代中使用小批量进行训练,因此计算损失函数时必须将所有的训练数据作为对象。即,如果训练数据有100个,我们就需要将这100个损失函数的总和作为学习的指标。
计算公式为: E = − 1 N ∑ n ∑ k t n k log y n k E=-\frac{1}{N} \sum_{n} \sum_{k} t_{n k} \log y_{n k} E=−N1∑n∑ktnklogynk,也就是把每一个输出loss进行加总求和。
4. 损失函数选择方法
在 Python深度学习-u3.1:神经网络入门-理论 已经介绍了常见问题中损失函数的选择方法,现摘录如下:
- 对于二分类问题,可以使用二元交叉熵(binary crossentropy)损失函数;
- 对于多分类问题,可以用分类交叉熵(categorical crossentropy)损失函数;
- 对于回归问题, 可以用均方误差(mean-squared error)损失函数;
- 对于序列学习问题,可以用联结主义时序分类(CTC,connectionist temporal classification)损失函数,等等。
- eg:imdb电影评论二分类问题
面对的是一个二分类问题, 网络输出是一个概率值(网络最后一层使用 sigmoid 激活函数, 仅包含一个单元),那么最好使用 binary_ crossentropy(二元交叉熵)损失。 这并不是唯一可行的选择, 比如你还可以使用 mean_ squared_error(均方误差)。但对于输出概率值的模型,交叉熵(crossentropy)往往是最好的选择。
- 对于分类、回归、序列预测等常见问题,你可以遵循一些简单的指导原则来选择正确的损失函数。参考方案如下:
注:- 具有多个输出的神经网络可能具有多个损失函数(每个输出对应一个损失函数)。但是,梯度下降过程必须基于单个标量损失值。因此,对于具有多个损失函数的网络,需要将所有损失函数取平均,变为一个标量值。
- 只有在面对真正全新的研究问题时,你才需要自主开发目标函数。