深度学习入门学习--第四章 神经网络的学习

7.13
第四章 神经网络的的学习
学习:指从训练数据中自动获取最优权重参数的过程。

1.从数据中学习
神经网络的特征就是可以从数据中学习。所谓“从数据中学习”,是指可以由数据自动决定权重参数的值。
(1)数据驱动
神经网络或深度学习比以往的机器学习方法更能避免人为介入。
深度学习有时也称为端到端机器学习。这里所说的端到端是指从一端到另一端的意思,也就是从原始数据(输入)中获得目标结果(输出)的意思。
神经网络的优点是对所有的问题都可以用同样的流程来解决。也就是说,与待处理的问题无关,神经网络可以将数据直接作为原始数据,进行“端对端”的学习。
(2)训练数据和测试数据
机器学习中,一般将数据分为训练数据测试数据两部分来进行学习和实验等。首先,使用训练数据进行学习,寻找最优的参数;然后,使用测试数据评价训练得到的模型的实际能力。
将数据分为训练数据和测试数据,是因为我们追求的是模型的泛化能力,为了正确评价模型的泛化能力,就必须划分训练数据和测试数据。另外,训练数据也可以称为监督数据。
泛化能力是指处理未被观察过的数据(不包括在训练数据中的数据)的能力。获得泛化能力是机器学习的最终目标。
过拟合:只对某个数据集过度拟合的状态称为过拟合。避免过拟合也是机器学习的一个重要课题。

2.损失函数
神经网络的学习通过某个指标表示现在的状态,然后,以这个指标为基准,寻找最优权重参数。
神经网络的学习中所用的指标称为损失函数。这个损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等。
损失函数:表示神经网络性能的“恶劣程度”的指标,即当前的神经网络对训练数据(监督数据)在多大程度上不拟合,在多大程度上不一致。以“性能的恶劣程度”为指标可能会使人感到不太自然,但是如果给损失函数乘上一个负值,就可以解释为“在多大程度上不坏”,即“性能有多好”。

(1)均方误差
可以作为损失函数的函数很多,其中最有名的是均方误差。了解其公式,以及公式中字母所表示的含义。
监督数据中将正确标签设为1,其他均设为0,这种表示方法称为one-hot表示
均方误差会计算神经网络的输出和正确解监督数据的各个元素之差的平方,再求和。Python实现如下:
def mean_squared_error(y,t):
return 0.5 * np.sum((y-t)**2)
这里参数y和t是NumPy数组。

(2)交叉熵误差
除了均方误差之外,交叉熵误差也经常被用作损失函数。
交叉熵误差的值是由正确解标签所对应的输出结果决定的。正确解标签对应的输出较小,则交叉熵误差值较大。代码实现交叉熵误差:
def cross_entropy_error(y,t):
delta=le-7
return -np.sum(t*np.log(y+delta))
这里,参数y和t是NumPy数组。函数内部在计算np.log时,加上了一个微小值delta。这是因为,当出现np.log(0)时,np.log(0)会变为负无限大的-inf,这样一来就会导致后续计算无法进行。作为保护性对策,添加一个微小值可以 防止负无限大的发生。

(3)mini-batch学习
机器学习使用训练数据进行学习。使用训练数据进行学习,严格来说,就是针对训练数据计算损失函数的值,找出使该值尽可能小的参数。因此,计算损失函数时必须将所有的训练数据作为对象。也就是说,如果训练数据有100个的话,我们就要把这100个损失函数的总和作为学习的指标。
前面介绍的损失函数的例子中考虑的都是针对单个数据的损失函数。
如果遇到大数据,这种情况下以全部数据为对象计算损失函数是不现实的。因此,我们从全部数据中选出一部分,作为全部数据的额“近似”。神经网络的学习也是从训练数据中选出一批数据(成为mini-batch,小批量),然后对每个mini-batch进行学习。这种学习方式称为mini-batch学习
从训练数据中随机抽取10笔数据,可以使用NumPy的np.random.choice(),
用随机选取的小批量数据(mini-batch)作为全体训练数据的近似值。

(4)mini-batch版交叉熵误差的实现
实现一个可以同时处理单个数据和批量数据(数据作为batch集中输入)两种情况的函数。
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+le-7)) / batch_size #正规化

这里,y是神经网络的输出,t是监督数据。y的维度为1时,即求单个数据的交叉熵误差时,需要改变数据的形状。并且,当输入为mini-batch时,要用batch的个数进行正规化,计算单个数据的平均交叉熵误差。
当监督数据是标签形式(非one-hot(0,1)表示,而是像“2”“7”这样的标签)时,实现代码如下:

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.sum(np.log(y[np.arange(batch_size),t] +le-7))/ batch_size #正规化

实现要点是,由于one-hot表示中t为0的元素的交叉熵误差也为0,因此针对这些元素的计算可以忽略。换言之,如果可以获得神经网络在正确解标签处的输出,就可以计算交叉熵误差。因此,t为one-hot表示时通过t * np.log(y)计算的地方,在t为标签形式时,可用np.log(y[np.arange(batch_size),t])实现相同的处理。

np.log(y[np.arange(batch_size),t]):np.arange(batch_size)会生成一个从0到batch_size-1的数组。比如当batch_size为5时,np.arrange(batch_size)会生成一个NumPy数组[0,1,2,3,4]。因为t中标签是以[2,7,0,9,4]的形式存储的,所以y[np.arange(batch_size),t]能抽出各个数据的正确解标签对应的神经网络的输出(在这个例子中,y[np.arange(batch_size),t]会生成NumPy数组[y[0,2],y[1,7],y[2,0],y[3,9]y[4,4]]).

(5)为何要设定损失函数
在神经网络的学习中,寻找最优参数(权重和配置)时,要寻找使损失函数的值尽可能小的参数。为了找到使损失函数的值尽可能小的地方,需要计算参数的导数(确切地讲是梯度),然后以这个导数为指引,逐步更新参数的值。
在进行神经网络的学习时,不能将识别精度作为指标。因为如果以识别精度为指标,则参数的导数在绝大多数的地方都会变为0.
原因:假设某个神经网络正确识别出了100笔训练数据中的32 笔,此时识别精度为32%。如果以识别精度为指标,及时稍微改变权重参数的值,识别精度也仍将保持在32%,不会出现变化。也就是说,仅仅微调参数,是无法改善识别精度的。即便识别精度有所改善,它的值也不会像32.0123%这样连续的变化,而是变为33%、34%这样的不连续的、离散的值。而如果把损失函数作为指标,则当前损失函数的值可以表示为0.93432…这样发生连续性的变化。
阶跃函数也只在某个瞬间产生变化。如果用阶跃函数作为激活函数,神经网络的学习将无法进行。而sigmoid函数,不仅函数的输出是连续变化的,曲线斜率也是连续变化的。也就是说,sigmoid函数的导数在任何地方都不为0。这对神经网络的学习非常重要。

3.数值微分(numerical differentiation)
所谓数值微分就是用数值方法近似求解函数的导数的过程。
梯度法使用梯度的信息决定前进的方向。本节主要学习梯度是什么、有什么性质等内容。
(1)导数
导数就是表示 某个瞬间的变化量。
**舍入误差:**指因省略小数的精细部分的数值(比如,小数点后第8位以后的数值)而造成最终的计算结果上的误差。(不好)
**前向差分:**函数f在(x+h)和x之间的差分。(不好)
中心差分:函数在(x+h)和(x-h)之间的差分。这种计算方法以x为中心,计算它左右两边的差分。
改进后的数值微分(数值梯度):
def numerical_diff(f,x):
h=le-4 # 0.0001
return (f(x+h)-f(x-h)) / (2*h)
如上所示,利用微小的差分求导数的过程称为数值微分。而基于数学式的推导求导数的过程,则用“解析性”一词,称为“解析性求解”或者“解析性求导”。解析性求导得到的导数是不含误差的“真的导数”。
(2)数值微分的例子
(3)偏导数
有多个变量的函数的导数称为
偏导数

偏导数和单变量的导数一样,都是求某个地方的斜率。不过,偏导数需要将多个变量中的某一个变量定为目标变量,并将其他变量固定为某个值。
偏导数2x1+x2的平方???

4. 梯度
由全部变量的偏导数汇总而成的向量称为梯度
梯度的实现:
def numerical_gradient(f,x):
h=le-4 #0.0001
grad=np.zeros_like(x) #生成和x形状相同、所有元素都为0的数组

for idx in range(x.size):
tmp_val=x[idx]
# f(x+h)的计算
x[idx]=tmp_val+h
fxh1=f(x)

#f(x-h)的计算
x[idx]=tmp_val-h
fxh2=f(x)

grad[idx]=(fxh1-fxh2) / (2*h)
x[idx]=tmp_val #还原值

return grad

函数numerical_gradient(f,x)中,参数f为函数,x为NumPy数组,该函数对NumPy数组x的各个元素求数值微分。

从梯度图像(其中元素值为负梯度的向量)上可以发现,梯度指向函数f(x0,x1)的“最低处”(最小值),就像指南针一样,所有的箭头都指向同一点。其次,我们发现离“最低点”越远,箭头越大。
实际上,梯度会指向各点处的函数值降低的方向。更严格的讲,梯度指示的方向是各点处的函数值减小最多的方向。

(1)梯度法
机器学习的主要任务是在学习时寻找最优参数。同样的,神经网络也必须在学习时找到最优参数(权重和偏置)。这里所说的最优参数是指损失函数取最小值时的参数。但是,一般而言,损失函数很复杂,参数空间庞大,我们不知道它在何处能取得最小值。而是通过巧妙地的使用梯度来寻找函数最小值(或者尽可能小的值)的方法就是梯度法。
梯度表示的是各点处的函数值减小最多的方向。因此,无法保证梯度所指的方向就是函数的最小值或者真正应该前进的方向。实际上,在复杂的函数中,梯度指示的方向基本上都不是函数值最小处。
函数的极小值、最小值以及被称为鞍点的地方,梯度为0。 极小值是局部最小值,也就是限定在某个范围内的最小值。鞍点是从某个方向上看是极大值,从另一个方向上看则是极小值的点。虽然梯度法是要寻找梯度为0 的地方,但是那个地方不一定就是最小值(也有可能是极小值或者鞍点)。此外,当函数很复杂且呈扁平状时,学习可能会进入一个(几乎)平坦的地区,陷入被称为“学习高原”的无法前进的停滞期。
虽然梯度党的方向并不一定指向最小值,但沿着它的方向能够最大限度的减小函数的值。因此,在寻找函数的最小值(或者尽可能小的值)的位置的任务中,要以梯度的信息为线索,决定前进的方向。此时梯度法就派上用场了。
在梯度法中,函数的取值从当前位置沿着梯度方向前进一定的距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断地沿梯度方向前进。
像这样,通过不断地沿梯度方向前进,逐渐减小函数值的过程就是梯度法。梯度法是解决机器学习中最优化问题的常用方法,特别是在神经网络的学习中经常被使用。
一般来说,神经网络(深度学习)中,梯度法主要是指
梯度下降法

在用数学式表示梯度法时引入了学习率这个概念。
学习率:学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数。
学习率需要事先确定为某个值,比如0.01或0.001.一般而言,这个值过大或过小,都无法抵达一个“好的位置”。在神经网络的学习中,一般会一边改变学习率的值,一边确认学习是否正确进行了。
梯度下降法也可用Python代码实现。
实验结果表明,学习率过大的话,会发散成一个很大的值;反过来,学习率国小的话,基本上没怎么更新就结束了。也就是说,设定合适的学习率是一个很重要的问题。
像学习率这样的参数称为超参数。这是一种和神经网络的参数(权重和偏置)性质不同的参数。相对于神经网络的权重参数是通过训练数据和学习算法自动获得的,学习率这样的超参数则是人工设定的。一般来说,超参数需要尝试多个值,以便找到一种可以使学习顺利进行的设定。

(2)神经网络的梯度
神经网络的学习也要求梯度。这里所说的梯度是指损失函数关于权重参数的梯度。

5.学习算法的实现
神经网络的学习步骤如下所示:
前提:神经网络存在合适的权重和偏置,调整权重和偏置以便拟合训练数据的过程称为“学习”。神经网络的学习分成下面4个步骤。
步骤一(mini-batch):从训练数据中随机选出一部分数据,这部分数据称为mini-batch。我们的目标是减小mini-batch的损失函数的值。
步骤二(计算梯度):为了减小mini-batch的损失函数的值,需要求出各个权重参数的梯度。梯度表示损失函数的值减小最多的方向。
步骤三(更新参数):将权重参数沿梯度方向进行微小更新。
步骤四(重复):重复前面三个步骤。
神经网络的学习按照上面四个步骤进行。这个方法通过梯度下降法更新参数,不过因为这里使用的数据是随机选择的mini-batch数据,所以又称为随机梯度下降法。随机梯度下降法是“对随机选择的数据进行的梯度下降法”。深度学习的很多框架中,随机梯度下降法一般由一个名为SGD的函数来实现。

(1)2层神经网络的类
本节实现了TwoLayerNet类,有五个方法:
intit__(self,input_size,hidden_size,output_size)方法,它是类的初始化方法(所谓初始化方法,就是生成TwoLayerNet实例时被调用的方法)。从第一个参数开始,依次表示输入层的神经元数、隐藏层的神经元数、输出层的神经元数。此外,这个初始化方法会对权重参数进行初始化。如何设置权重参数的初始值这个问题是关系到神经网络能否成功学习的重要问题。 权重使用符合高斯分布的随机数进行初始化偏置使用0进行初始化
**predict(self,x)accuracy(self,x,t)**的实现和上一章的神经网络的推理处理基本一样。
**loss(self,x,t)**是计算损失函数值的方法。这个方法会基于predict()的结果和正确解标签,计算交叉熵误差。
**numerical_gradient(self,x,t)**方法会计算各个参数的梯度。根据数值微分,计算各个参数相对于损失函数的梯度。
**gradient(self,x,t)**下一章会实现,该方法使用误差反向传播法高效的计算梯度。用误差反向传播法求到的梯度和数值微分的结果一致,但是可以高速的进行处理。

(2)mini-batch的实现
神经网络的学习的实现使用的是前面介绍过的mini-batch学习。所谓mini-batch学习就是从训练数据中随机选择一部分数据(称为mini-batch),再以这些mini-batch为对象,使用梯度法更新参数的过程。
本节,我们以TwoLayerNet类为对象,使用MNIST数据集进行学习。代码中定义mini-batch的大小为100,需要每次从60000个训练数据中随机取出100个数据(图像数据和正确解标签数据)。然后,对这个包含100笔数据的mini-batch求梯度,使用随机梯度下降法(SGD)更新参数。这里,梯度法的更新次数(循环的次数)为10000。每更新一次,都对训练数据计算损失函数的值,并把该值添加到数组中。

根据损失函数的值的图像可以发现,随着学习的进行,损失函数的值在不断减小。这是学习正常进行的信号,表示神经网络的权重参数在逐渐拟合数据。也就是说,神经网络的确在学习。通过反复的向它浇灌(输入)数据,神经网络正在逐渐向最优参数靠近。

(3)基于测试数据的评价
神经网络的学习中,必须确认是否能够正确识别训练数据以外的其他数据,即确认是否会发生过拟合过拟合是指,虽然训练数据中的数字图像能被正确辨别,但是不在训练数据中的数字图像却无法被识别的现象。
神经网络学习的最初目标是掌握泛化能力,因此,要评价神经网络的泛化能力,就必须使用不包含在训练数据中的数据。本节代码在进行学习的过程中,会定期地对训练数据和测试数据记录识别精度。这里,每经过一个epoch,我们都会记录下训练数据和测试数据的识别精度。
epoch是一个单位。一个epoch表示学习中所有训练数据均被使用过一次时的更新次数。
在本节中,每经过一个epoch,就对所有的训练数据和测试数据计算识别精度,并记录结果。之所以要计算每一个epoch的识别精度,是因为如果在for语句的循环中一直计算识别精度,会花费太多时间。并且,也没有必要那么频繁的记录识别精度(只要从大方向把握识别精度的推移就可以了)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值