外观
神经网络的学习
损失函数
损失函数,英文loss function。
神经网络以损失函数这个指标为线索寻找最优权重参数。
损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等函数。
分类错误率
这是最为直接的损失函数。
均方误差
均方误差,英文mean squared error,缩写为MSE。
用python实现:
python
def mean_squared_error(y, t):
return 0.5 * np.sum((y - t) ** 2)
1
2
2
交叉熵误差
交叉熵函数,英文cross entropy error。
给定2个离散分布的概率分布p和q,p相对于q的交叉熵定义为:
用python实现:
python
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
1
2
3
2
3
这里,参数y和t是NumPy数组。函数内部在计算np.log时,加上了一个微小值delta。这是因为,当出现np.log(0)时,np.log(0)会变为负无限大的-inf,这样一来就会导致后续计算无法进行。作为保护性对策,添加一个微小值可以防止负无限大的发生。
mini-batch学习
前面介绍的损失函数的例子中考虑的都是针对单个数据的损失函数。
如果以全部数据为对象求损失函数的和,则计算过程需要花费较长的时间。再者,如果遇到大数据,数据量会有几百万、几千万之多,这种情况下以全部数据为对象计算损失函数是不现实的。因此,我们从全部数据中选出一部分,作为全部数据的“近似”。神经网络的学习也是从训练数据中选出一批数据(称为mini-batch,小批量),然后对每个mini-batch进行学习。比如,从60000个训练数据中随机选择100笔,再用这100笔数据进行学习。这种学习方式称为mini-batch学习。
mini-batch的损失函数是利用一部分样本数据来近似地计算整体。也就是说,用随机选择的小批量数据(mini-batch)作为全体训练数据的近似值。
mini-batch版交叉熵误差
python
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(t * np.log(y + 1e-7)) / batch_size
1
2
3
4
5
6
2
3
4
5
6
这里,y是神经网络的输出,t是监督数据。y的维度为1时,即求单个数据的交叉熵误差时,需要改变数据的形状。并且,当输入为mini-batch时,要用batch的个数进行正规化,计算单个数据的平均交叉熵误差。
此外,当监督数据是标签形式(非one-hot表示,而是像“2”“7”这样的标签)时,交叉熵误差可通过如下代码实现。
python
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size
1
2
3
4
5
6
2
3
4
5
6
实现的要点是,由于one-hot表示中t为0的元素的交叉熵误差也为0,因此针对这些元素的计算可以忽略。换言之,如果可以获得神经网络在正确解标签处的输出,就可以计算交叉熵误差。
为何要设定损失函数
假设有一个神经网络,现在我们来关注这个神经网络中的某一个权重参数。此时,对该权重参数的损失函数求导,表示的是“如果稍微改变这个权重参数的值,损失函数的值会如何变化”。如果导数的值为负,通过使该权重参数向正方向改变,可以减小损失函数的值;反过来,如果导数的值为正,则通过使该权重参数向负方向改变,可以减小损失函数的值。不过,当导数的值为0时,无论权重参数向哪个方向变化,损失函数的值都不会改变,此时该权重参数的更新会停在此处。
在进行神经网络的学习时,不能将识别精度作为指标。因为如果以识别精度为指标,则参数的导数在绝大多数地方都会变为0。这会导致参数无法更新。
为什么用识别精度作为指标时,参数的导数在绝大多数地方都会变成0呢?识别精度对微小的参数变化基本上没有什么反应,即便有反应,它的值也是不连续地、突然地变化。