神经网络的学习

从数据中学习

神经网络的学习指的是从数据参数中自动获取最优权重参数的值。在实际的神经网络之中,权重的数量成千上万,随着层数的递进,这个数量还在继续增加。想要人工决定这些数值的大小是不可能的。我们需要让神经网络来根据数值自动决定参数值。通过引入损失函数能够有效的获取最有的权重参数。<!-- more -->

比如如何用算法实现数字“5”图像的识别?。人可以简单的识别出5,但也没法明确说出是基于何种规律——同时每个人书写5的方式还可能不同,想要找出规律是非常难的。预期从零开始想出识别5的算法,不如通过已有的数据来解决,一种方案是,先从图像中提取特征量,在用机器学习的技术学习特征量的模式(如计算机视觉领域的SIFT.SURF,HOG等)。在机器学习的方法中,由机械搜集到的数据中找出规律性能更高效的解决问题。但将图像转换为特征量的算法仍然是人设计的,对于不同的问题,需要设计不同的特征量,才能有效解决。而神经网络(深度学习)则会直接学习图像本身,深度学习中连特征量都是由机器来学习的。

神经网络的优点在于对于所有的问题都可以用同一个流程来解决,不管是识别数字5还是识别红绿灯,都可以通过不断学习提供的数据来尝试得到研究问题的模式。

在深度学习中,一般是把数据分为训练数据和测试数据,先用训练数据寻找最优参数,再用测试数据来得到模型的实际能力,这能正确的评估模型的泛化能力。

损失函数

神经网络的学习通过某个指标来寻找最优权重参数,而这个指标通常是损失函数,理论上这个函数可以使用任意的,但通常采用均方误差和交叉熵误差。

均方误差

均方误差如下式所示:

$$
E = \frac{1}{2} \sum_{k}(y_k \,-\, t_k) ^2
$$

yk表示神经网络的输出,tk表示监督数据,k为数据的维数。这会求出神经网络的输出和监督数据之差的平方和再相加,用python实现如下

def mean_squared_error(y,t):
    return 0.5* np.sum((y-t) ** 2)

交叉熵误差

交叉熵误差如下所示:

$$
E = -\sum_{k} t_k\,\, log \,\,y_k
$$

其中yk表示神经网络的输出,tk表示监督数据,k为数据的维数,log为以e为底数的自然对数。并且可以看出,交叉熵误差的值,是由正确解标签所对应的输出结果所决定的。

python实现如下:

def cross_entropy_error(y,t):
    delta = 1e -7
    return -np.sum(t * np.log(y + delta ))

这里的y和t是NumPy数组。函数内部在计算np.log时,加上了一个极小量,这可以避免当np.log(0)时导致的计算错误。

mini-batch学习

机器学习使用数据进行学习。使用数据进行学习的本质是通过训练数据来计算损失函数的值,通过选择参数来使这个值不断减小来获得最优参数。所以计算损失函数时必须计算所有的训练数据作为对象。

但仅以MNIST数据集为例,内涵60000多个训练数据,假如以所有的数据作为训练对象,那花费的时间将是巨大的,况且有些训练数据的数量上百万甚至千万,将他们全部放入损失函数内进行计算是不现实的,因此,我们应当从全部数据中选出一部分作为训练数据,作为全体数据的近似。神经网络通常也是从所有数据中选出一批数据,分别对每个mini-batch进行学习。

为何要设定损失函数

可能有人要问:“为什么要导入损失函数呢?”以数字识别任务为例,我们想获得的是能提高识别精度的参数,特意再导入一个损失函数不是有些重复劳动吗?也就是说,既然我们的目标是获得使识别精度尽可能高的神经网络,那不是应该把识别精度作为指标吗? 对于这一疑问,我们可以根据“导数”在神经网络学习中的作用来回答。下一节中会详细说到,在神经网络的学习中,寻找最优参数(权重和偏置)时,要寻找使损失函数的值尽可能小的参数。为了找到使损失函数的值尽可能小的地方,需要计算参数的导数(确切地讲是梯度),然后以这个导数为指引,逐步更新参数的值。 假设有一个神经网络,现在我们来关注这个神经网络中的某一个权重参数。此时,对该权重参数的损失函数求导,表示的是“如果稍微改变这个权重参数的值,损失函数的值会如何变化”。如果导数的值为负,通过使该权重参数向正方向改变,可以减小损失函数的值;反过来,如果导数的值为正,则通过使该权重参数向负方向改变,可以减小损失函数的值。不过,当导数的值为0时,无论权重参数向哪个方向变化,损失函数的值都不会改变,此时该权重参数的更新会停在此处。 之所以不能用识别精度作为指标,是因为这样一来绝大多数地方的导数 都会变为0,导致参数无法更新。话说得有点多了,我们来总结一下上面的内容。

在进行神经网络的学习时,不能将识别精度作为指标。因为如果以识别精度为指标,则参数的导数在绝大多数地方都会变为0。

为什么用识别精度作为指标时,参数的导数在绝大多数地方都会变成0呢?为了回答这个问题,我们来思考另一个具体例子。假设某个神经网络正确识别出了100笔训练数据中的32笔,此时识别精度为32%。如果以识别精度为指标,即使稍微改变权重参数的值,识别精度也仍将保持在32%,不会出现变化。也就是说,仅仅微调参数,是无法改善识别精度的。即便识别精度有所改善,它的值也不会像32.0123….%这样连续变化,而是变为33%、34%这样的不连续的、离散的值。而如果把损失函数作为指标,则当前损失函数的值可以表示为0.92543…··这样的值。并且,如果稍微改变一下参数的值,对应的损失函数也会像0.93432···这样发生连续性的变化。 识别精度对微小的参数变化基本上没有什么反应,即便有反应,它的值也是不连续地、突然地变化。作为激活函数的阶跃函数也有同样的情况。出于相同的原因,如果使用阶跃函数作为激活函数,神经网络的学习将无法进行。阶跃函数的导数在绝大多数地方(除了0以外的地方)均为0。也就是说,如果使用了阶跃函数,那么即便将损失函数作为指标,参数的微小变化也会被阶跃函数抹杀,导致损失函数的值不会产生任何变化。 阶跃函数就像“竹筒敲石”一样,只在某个瞬间产生变化。而sigmoid函数,不仅函数的输出(竖轴的值)是连续变化的,曲线的斜率(导数)也是连续变化的。也就是说,sigmoid函数的导数在任何地方都不为0。这对神经网络的学习非常重要。得益于这个斜率不会为0的性质,神经网络的学习得以正确进行。

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值