【深度学习】2-4 神经网络-手写数字识别

在实现对手写数字图像的分类,可以先假设学习已经全部结束,我们使用学习到的参数,先实现神经网络的“推理处理”。该处理也称为神经网络的前向传播

和求解机器学习问题的步骤(分成学习和推理两个阶段进行)一样
使用神经网络解决问题时,也需要首先使用训练数据(学习数据)进行权重参数的学习;进行推理时,使用刚才学习到的参数,对输入数据进行分类

MNIST数据集
MNIST是机器学习最有名的数据集之一,被应用于从简单的实验到发表的论文研究等各种场合,在阅读图像识别或机器学习的论文时,MNIST数据集经常作为实验用的数据出现。
MINIST数据集是由0到9的数字图像构成的,MNIST数据集的使用方法是,先用训练图像进行学习,再用学习到的模型度量能在多大程度上对测试图像进行正确的分类

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

这里通过Python的脚本mnist.py,从下载MNIST数集到将这些数据转换成NumPy数组等处理,使用mnistpy中的load_mnist()函数,就可以按下述方式轻松读入MNIST数据。

注意这里的mnist.py不具备通用性,只能用在学习项目中,做学习了解(具体可以参考网上知识,在此不详述)

Python有pickle这个功能,可以将程序运行中的对象保存为文件,如果加裁保存过的pickle文件,可以立刻复原之前程序运行中的对象。利用pickle功能,可以高效地完成MINIST数据的准备工作。pickle.load(f)

手写数字识别的例子

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
from dataset.mnist import load_mnist

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)

# 输出各个数据的形状
print(x_train.shape)   # (60000784)
print(t_train.shape)  # (60000,)
print(x test.shape)   #(10000784)
print(t_test.shape)   # (10000,)


上面的代码中,先导人dataset/mnist.py中的load_mnist函数。load mnist函数以“(训练图像,训练标签),(测试图像,测试标签)”的形式返回读人的MNIST数据。
然后想 load_mnist(normalize=True,flatten=True,one_hot_label=False)这样,设置3个参数。
normalize设置是否将输人图像正规化为0.0~1.0的值。
flatten设置是否展开输人图像(变成一维数组)。若设置为True,则输人图像会保存为由784个元素构成的一维数组。
one_hot_label设置是否将标签保存为one-hot表示。one-hot表示是仅正确解标签为1,其余皆为0的数组,就像[0,0,1,0,0,0,0,0,0,0]这样。当one_hot_label为True时,标签则保存为one-hot表示。

后面显示MINIST图像,同时也确认一下数据。图像的是使用PIL(Python Image Library)模块。执行下述代码后,训练图像的第一张就会显示出来

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
from dataset.mnist import load_mnist
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)

img = x_train[0]
label = t_train[0]
print(label)  # 5

print(img.shape)  # (784,)
img = img.reshape(28, 28)  # 把图像的形状变为原来的尺寸
print(img.shape)  # (28, 28)

img_show(img)

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

神经网络的推理处理
对这个MNIST数据集实现神经网络的推理处理。

神经网络的输人层有784个神经元,输出层有10个神经元。
输人层的784这个数字来源于图像大小的28x28=784,
输出层的10这个数字来源于10类别分类(数字0到9,共10类别)。
此外,这个神经网络有2个隐藏层,第1个隐藏层有50个神经元,第2个隐藏层有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 netwrok

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

	reutrn y

init_network()会读入保存在pickle文件 sample_weight.pkl 中的学习到的权重参数
现在,用这3个函数来实现神经网络的推理处理。然后,评价它的识别精度即能在多大程度上正确分类。

# 获取数据
x, t = get_data()
# 初始化network
network =init_network()

accuracy_cnt =0
for i in range(len(x)):
	y = predict(network,x[i]) # predict()函数以NumPy数组的形式输出各个标签对应的概率
	p=np.argmax(y)  # 获取概率最高的元素的索引
	if p == t[i]:
		accuracy_cnt += 1
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))  # 比较神经网络所测的答案和正确解标签,将回答正确的概率作为识别精度。

目前这个代码的精度还不是很高,后续会在神经网络的结构和学习方法上优化来提高这个精度

把load_mnist函数的参数normalize设置成了True。将normalize设置成True后,函数内部会进行转换,将图像的各个像素值除以255,使得数据的值在0.0~1.0的范围内。像这样把数据限定到某个范围内的处理称为正规化。这种对神经网络的输人数据进行某种既定的转换称为预处理

预处理在神经网络(深度学习)中非常实用,实际上,很多预处理都会考虑到数据的整体分布,比如,利用数据整体的均值或标准差,移动数据,使数据整体以0为中心分布。

猜你喜欢

转载自blog.csdn.net/loyd3/article/details/130595135