在之前神经网络的学习基础上,来试着解决实际问题。 进行手写数字图像的分类。假设学习已经全部结束,我们使用学习到的参数,先实现神经网络的"推理处理"。这个推理处理也称为神经网络的前向传播。
一,MNIST数据集
MNIST是机器学习领域最有名的数据集之一,这里我们也使用它。
一般使用方法是,先用训练图像进行学习,再用学习到的模型度量能在多大程度上对测试图像进行正确的分类。
图像数据是28像素 × 28像素的灰度图像(1通道),各个像素的取值在0到255之间。
借用一个案例中提供的下载脚本,能将数据集转换成Numpy数组。
scss
import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
from dataset.mnist import load_mnist
# 第一次调用会花费几分钟 ......
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
# 输出各个数据的形状
print(x_train.shape) # (60000, 784)
print(t_train.shape) # (60000,)
print(x_test.shape) # (10000, 784)
print(t_test.shape) # (10000,)
load_mnist函数以"(训练图像 ,训练标签 ),(测试图像,测试标签 )"的形式返回读入的MNIST数据
二,神经网络的推理处理
我们来确定一些这个神经网络,神经网络的输入层有784个神经元(来源于图像大小的28 × 28 = 784),输出层有10个神经元(数字0到9,共10类别)。此外这个神经网络有2个隐藏层,第1个隐藏层有50个神经元,第2个隐藏层有100个神经元。
另外,假设已经经过训练得到了参数,保存在sample_weight.pkl文件中。
代码如下:
ini
import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
from dataset.mnist import load_mnist
import numpy as np
import pickle #训练得到的参数
from common.functions import sigmoid, softmax
#定义获取数据的函数
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
#定义推理过程函数
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
## 具体实现##
##1,获取数据
x, t = get_data()
##2,读入权重参数
network = init_network()
##3,设定关键参数
accuracy_cnt = 0
##4,预测、比较、计算预测正确数
for i in range(len(x)):
y = predict(network, x[i])
p = np.argmax(y) # 获取概率最高的元素的索引
if p == t[i]:
accuracy_cnt += 1
##5,输出精确率
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
输出结果为,Accuracy:0.9352,表示有93.52 %的数据被正确分类。
在这个例子中,把load_mnist函数的参数normalize设置成了True,这个的意思是,将图像的各个像素值除以255,使得数据的值在0.0~1.0的范围内,这种处理叫正规化 。另外,对神经网络的输入数据进行某种既定的转换称为预处理。
三,批处理
将上述例子中的各层的形状写出来研究一下过程中数组形状的变化,如下:
可以看出来,输出的是一个784元素的一维数组,最后输出的是10个元素的一维数组,这也是输入一张图像数据时的处理流程
那假如我们将X的形状改为100×784,也就是说,一次性传入传入100张图像,用图来表示的话,如下所示
可以发现输出的形状变成了100×10,代表着100张图像的结果一次性输出。这种打包式的输入数据称为批
改一下之前的代码,实现如下:
ini
##3,设定关键参数
batch_size = 100 # 批数量
accuracy_cnt = 0
##4,预测、比较、计算预测正确数
for i in range(0, len(x), batch_size): #取100个样本
x_batch = x[i:i+batch_size] #将取出的样本组成数组
y_batch = predict(network, x_batch) #得到预测出来的结果数组
p = np.argmax(y_batch, axis=1) #取出1轴上各个结果最大值元素的索引
accuracy_cnt += np.sum(p == t[i:i+batch_size]) #计算预测结果=标签的数量
##5,输出精确率
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))