神经网络--深度学习(2)

3.3.3 神经网络的内积
下面我们使用 NumPy 矩阵来实现神经网络。这里我们以图 3-14 中的简
单神经网络为对象。这个神经网络省略了偏置和激活函数,只有权重。

这里需要注意的是,flatten=True 时读入的图像是以一列(一维)NumPy
数组的形式保存的。因此,显示图像时,需要把它变为原来的 28 像素 × 28
像素的形状。可以通过 reshape() 方法的参数指定期望的形状,更改 NumPy
数组的形状。此外,还需要把保存为 NumPy 数组的图像数据转换为 PIL 用
的数据对象,这个转换处理由 Image.fromarray() 来完成。

3.6.2 神经网络的推理处理
下面,我们对这个 MNIST 数据集实现神经网络的推理处理。神经网络
的输入层有 784 个神经元,输出层有 10 个神经元。输入层的 784 这个数字来
源于图像大小的 28 × 28 = 784,输出层的 10 这个数字来源于 10 类别分类(数
字 0 到 9,共 10 类别)。此外,这个神经网络有 2 个隐藏层,第 1 个隐藏层有
50 个神经元,第 2 个隐藏层有 100 个神经元。这个 50 和 100 可以设置为任何值。
下面我们先定义 get_data()、init_network()、predict() 这 3 个函数(代码在
ch03/neuralnet_mnist.py 中)。

init_network() 会读入保存在 pickle 文件 sample_weight.pkl 中的学习到的
权重参数 A。这个文件中以字典变量的形式保存了权重和偏置参数。剩余的 2
个函数,和前面介绍的代码实现基本相同,无需再解释。现在,我们用这 3
个函数来实现神经网络的推理处理。然后,评价它的识别精度(accuracy),
即能在多大程度上正确分类。
x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
y = predict(network, x[i])
p = np.argmax(y) # 获取概率最高的元素的索引
if p == t[i]:
accuracy_cnt += 1
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
首先获得 MNIST 数据集,生成网络。接着,用 for 语句逐一取出保存
在 x 中的图像数据,用 predict() 函数进行分类。predict() 函数以 NumPy 数
组的形式输出各个标签对应的概率。比如输出 [0.1, 0.3, 0.2, ..., 0.04] 的
数组,该数组表示“0”的概率为 0.1,“1”的概率为 0.3,等等。然后,我们
取出这个概率列表中的最大值的索引(第几个元素的概率最高),作为预测结
果。可以用 np.argmax(x) 函数取出数组中的最大值的索引,np.argmax(x) 将
获取被赋给参数 x 的数组中的最大值元素的索引。最后,比较神经网络所预
测的答案和正确解标签,将回答正确的概率作为识别精度。
A 因为之前我们假设学习已经完成,所以学习到的参数被保存下来。假设保存在 sample_weight.pkl
文件中,在推理阶段,我们直接加载这些已经学习到的参数。——译者注

执行上面的代码后,会显示“Accuracy:0.9352”。这表示有 93.52 % 的数
据被正确分类了。目前我们的目标是运行学习到的神经网络,所以不讨论识
别精度本身,不过以后我们会花精力在神经网络的结构和学习方法上,思考
如何进一步提高这个精度。实际上,我们打算把精度提高到 99 % 以上。
另外,在这个例子中,我们把 load_mnist 函数的参数 normalize 设置成了
True。将 normalize 设置成 True 后,函数内部会进行转换,将图像的各个像
素值除以 255,使得数据的值在 0.0~1.0 的范围内。像这样把数据限定到某
个范围内的处理称为正规化(normalization)。此外,对神经网络的输入数据
进行某种既定的转换称为预处理(pre-processing)。这里,作为对输入图像的
一种预处理,我们进行了正规化。

预处理在神经网络(深度学习)中非常实用,其有效性已在提高识别
性能和学习的效率等众多实验中得到证明。在刚才的例子中,作为
一种预处理,我们将各个像素值除以 255,进行了简单的正规化。
实际上,很多预处理都会考虑到数据的整体分布。比如,利用数据
整体的均值或标准差,移动数据,使数据整体以 0 为中心分布,或
者进行正规化,把数据的延展控制在一定范围内。除此之外,还有
将数据整体的分布形状均匀化的方法,即数据白化(whitening)等。

批处理
以上就是处理 MNIST 数据集的神经网络的实现,现在我们来关注输入
数据和权重参数的“形状”。再看一下刚才的代码实现。
下面我们使用 Python 解释器,输出刚才的神经网络的各层的权重的形状

我们通过上述结果来确认一下多维数组的对应维度的元素个数是否一致
(省略了偏置)。用图表示的话,如图 3-26 所示。可以发现,多维数组的对应
维度的元素个数确实是一致的。此外,我们还可以确认最终的结果是输出了
元素个数为 10 的一维数组。

从整体的处理流程来看,图 3-26 中,输入一个由 784 个元素(原本是一
个 28 × 28 的二维数组)构成的一维数组后,输出一个有 10 个元素的一维数组。
这是只输入一张图像数据时的处理流程。
现在我们来考虑打包输入多张图像的情形。比如,我们想用 predict()
函数一次性打包处理 100 张图像。为此,可以把 x 的形状改为 100 × 784,将
100 张图像打包作为输入数据。用图表示的话,如图 3-27 所示。

批处理对计算机的运算大有利处,可以大幅缩短每张图像的处理时
间。那么为什么批处理可以缩短处理时间呢?这是因为大多数处理
数值计算的库都进行了能够高效处理大型数组运算的最优化。并且,
在神经网络的运算中,当数据传送成为瓶颈时,批处理可以减轻数
据总线的负荷(严格地讲,相对于数据读入,可以将更多的时间用在
计算上)。也就是说,批处理一次性计算大型数组要比分开逐步计算
各个小型数组速度更快。

我们来逐个解释粗体的代码部分。首先是 range() 函数。range() 函数若
指定为 range(start, end),则会生成一个由 start 到 end-1 之间的整数构成的
列表。若像 range(start, end, step) 这样指定 3 个整数,则生成的列表中的
下一个元素会增加 step 指定的值。我们来看一个例子。

在 range() 函数生成的列表的基础上,通过 x[i:i+batch_size] 从输入数
据中抽出批数据。x[i:i+batch_n] 会取出从第 i 个到第 i+batch_n 个之间的数据。
本例中是像 x[0:100]、x[100:200]......这样,从头开始以 100 为单位将数据提
取为批数据。
然后,通过 argmax() 获取值最大的元素的索引。不过这里需要注意的是,
我们给定了参数 axis=1。这指定了在 100 × 10 的数组中,沿着第 1 维方向(以
第 1 维为轴)找到值最大的元素的索引(第 0 维对应第 1 个维度)A。这里也来
看一个例子。

最后,我们比较一下以批为单位进行分类的结果和实际的答案。为此,
需要在 NumPy 数组之间使用比较运算符(==)生成由 True/False 构成的布尔
型数组,并计算 True 的个数。我们通过下面的例子进行确认。
>>> y = np.array([1, 2, 1, 0])
>>> t = np.array([1, 2, 0, 0])
>>> print(y==t)
[True True False True]
>>> np.sum(y==t)
3
至此,基于批处理的代码实现就介绍完了。使用批处理,可以实现高速
且高效的运算。下一章介绍神经网络的学习时,我们将把图像数据作为打包
的批数据进行学习,届时也将进行和这里的批处理一样的代码实现。
A 矩阵的第 0 维是列方向,第 1 维是行方向。——译者注

本章介绍了神经网络的前向传播。本章介绍的神经网络和上一章的感知
机在信号的按层传递这一点上是相同的,但是,向下一个神经元发送信号时,
改变信号的激活函数有很大差异。神经网络中使用的是平滑变化的 sigmoid
函数,而感知机中使用的是信号急剧变化的阶跃函数。这个差异对于神经网
络的学习非常重要,我们将在下一章介绍。

• 神经网络中的激活函数使用平滑变化的 sigmoid 函数或 ReLU 函数。
• 通过巧妙地使用 NumPy 多维数组,可以高效地实现神经网络。
• 机器学习的问题大体上可以分为回归问题和分类问题。
• 关于输出层的激活函数,回归问题中一般用恒等函数,分类问题中
一般用 softmax 函数。
• 分类问题中,输出层的神经元的数量设置为要分类的类别数。
• 输入数据的集合称为批。通过以批为单位进行推理处理,能够实现
高速的运算。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值