深度学习——神经网络实例(手写数字识别)

手写数字识别

假设机器学习已经结束,我们使用学习到的参数,先实现神经网络的“推理处理”。这个推理处理也称为神经网络的前向传播(forward propagation)。
使用神经网络解决问题时,也需要首先使用训练数据(学习数据)进行权重参数的学习;进行推理时,使用刚才学习到的参数,对输入数据进行分类。
————————————————————————————————————————————

MNIST数据集

MNIST是机器学习领域最有名的数据集之一,被应用于从简单的实验到发表的论文研究等各种场合。MNIST数据集的一般使用方法是,先用训练图像进行学习,再用学习到的模型度量能在多大程度上对测试图像进行正确的分类。
在这里插入图片描述

MNIST的图像数据是28像素 × 28像素的灰度图像(1通道),各个像素的取值在0到255之间。每个图像数据都相应地标有“7”“2”“1”等标签。

load_mnist函数

load_mnist函数以“(训练图像 ,训练标签 ),(测试图像,测试标签 )”的形式返回读入的MNIST数据。此外,还可以像load_mnist(normalize=True, flatten=True, one_hot_label=False) 这 样,设 置 3 个 参 数。第 1 个参数normalize设置是否将输入图像正规化为0.0~1.0的值。如果将该参数设置为False,则输入图像的像素会保持原来的0~255。第2个参数flatten设置是否展开输入图像(变成一维数组)。如果将该参数设置为False,则输入图像为1 × 28 × 28的三维数组;若设置为True,则输入图像会保存为由784个元素构成的一维数组。第3个参数one_hot_label设置是否将标签保存为one-hot表示(one-hot representation)。one-hot表示是仅正确解标签为1,其余皆为0的数组,**就像[0,0,1,0,0,0,0,0,0,0]**这样。当one_hot_label为False时,只是像7、2这样简单保存正确解标签;当one_hot_label为True时,标签则保存为one-hot表示。
————————————————————————————————————————————
显示MNIST图像,同时也确认一下数据。图像的显示
使用PIL(Python Image Library)模块。
from PIL import Image
定义一个显示图像的函数:
def img_show(img):
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True,normalize=False)
print(img.shape) # (784,)
img = img.reshape(28, 28) # 把图像的形状变成原来的尺寸
print(img.shape)
flatten=True时读入的图像是以一列(一维)NumPy数组的形式保存的。因此,显示图像时,需要把它变为原来的28像素 × 28像素的形状。可以通过reshape()方法的参数指定期望的形状,更改NumPy
数组的形状。此外,还需要把保存为NumPy数组的图像数据转换为PIL用的数据对象,这个转换处理由Image.fromarray()来完成。

神经网络的推理处理

对这个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个函数。
``

def get_data():
 (x_train, t_train), (x_test, t_test) = \
 load_mnist(normalize=True, flatten=True, one_hot_label=False)
 return x_test, t_test
def init_network():
 with open("sample_weight.pkl", 'rb') as f:
 network = pickle.load(f)
 return network

init_network()会读入保存在pickle文件sample_weight.pkl中的学习到的权重参数A。这个文件中以字典变量的形式保存了权重和偏置参数

def predict(network, x):
 W1, W2, W3 = network['W1'], network['W2'], network['W3']
 b1, b2, b3 = network['b1'], network['b2'], network['b3']
 a1 = np.dot(x, W1) + b1
 z1 = sigmoid(a1)
 a2 = np.dot(z1, W2) + b2
 z2 = sigmoid(a2)
 a3 = np.dot(z2, W3) + b3
 y = softmax(a3)
 return y

现在,我们用这3个函数来实现神经网络的推理处理。然后,评价它的识别精度(accuracy)
首先获得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的数组中的最大值元素的索引。最后,比较神经网络所预测的答案和正确解标签,将回答正确的概率作为识别精度。
————————————————————————————————————————————
在这个例子中,我们把load_mnist函数的参数normalize设置成了True。将normalize设置成True后,函数内部会进行转换,将图像的各个像素值除以255,使得数据的值在0.0~1.0的范围内。像
这样把数据限定到某个范围内的处理称为正规化(normalization)
。此外,对神经网络的输入数据进行某种既定的转换称为预处理(pre-processing)。这里,作为对输入图像的一种预处理,我们进行了正规化。
预处理在神经网络(深度学习)中非常实用,其有效性已在提高识别性能和学习的效率等众多实验中得到证明。在刚才的例子中,作为一种预处理,我们将各个像素值除以 255,进行了简单的正规化。实际上,很多预处理都会考虑到数据的整体分布。比如,利用数据整体的均值或标准差,移动数据,使数据整体以 0为中心分布,或者进行正规化,把数据的延展控制在一定范围内。除此之外,还有将数据整体的分布形状均匀化的方法,即数据白化(whitening)等。
————————————————————————————————————————————
接下来的学习中,我们将致力于如何提高这个识别精度。

批处理

现在关注的是输入数据和权重参数的“形状”
在这里插入图片描述
从整体的处理流程来看,图3-26中,输入一个由784个元素(原本是一
个28 × 28的二维数组)构成的一维数组后,输出一个有10个元素的一维数组。
这是只输入一张图像数据时的处理流程。
现在我们来考虑打包输入多张图像的情形。比如,我们想用predict()函数一次性打包处理100张图像。为此,可以把x的形状改为100 × 784,将100张图像打包作为输入数据。
在这里插入图片描述
这种打包式的输入数据称为批(batch)。批处理一次性计算大型数组要比分开逐步计算各个小型数组速度更快。

下面我们进行基于批处理的代码实现。这里用粗体显示与之前的实现的不同之处。

x, t = get_data()
network = init_network()
batch_size = 100 # 批数量
accuracy_cnt = 0
for i in range(0, len(x), batch_size):
 x_batch = x[i:i+batch_size]
 y_batch = predict(network, x_batch)
 p = np.argmax(y_batch, axis=1)
 accuracy_cnt += np.sum(p == t[i:i+batch_size])
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

通过argmax()获取值最大的元素的索引。我们给定了参数axis=1。这指定了在100 × 10的数组中,沿着第1维方向找到值最大的元素的索引。
例如:

x = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6],
… [0.2, 0.5, 0.3], [0.8, 0.1, 0.1]])
y = np.argmax(x, axis=1)
print(y)
[1 2 1 0]
———————————————————————————
#比较一下以批为单位进行分类的结果和实际的答案。
y = np.array([1, 2, 1, 0])
t = np.array([1, 2, 0, 0])
print(yt)
[True True False True]
np.sum(y
t)
3

本章小结

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

参考:

《深度学习入门:基于Python的理论与实现 》斋藤康毅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值