会飞的鱼

2020
Godam
首页 » 人工智能 » 深度学习入门--手写数字识别

深度学习入门--手写数字识别

本篇博文用到的数据集以及源代码:
链接:https://pan.baidu.com/s/1lsvb89TJVK2QMZwANCDbTw

加载数据

load_mnist函数以“(训练图像,训练标签),(测试图像,测试标签)”的形式返回读入的MNIST数据。此外,还可以像load_mnist(normalize=True, flatten=True, one_hot_label=False)这样,设置三个参数。第一个,normalize设置是否将输入图像正规化为0.0~1.0这样的值。第2个参数flatten设置是否展开输入图像(变成一维数组)。如果将参数设置为False,则输入图像为1 x 28 x 28的三维数组;若设置为True,则输入图像会保存为由784个元素构成的一维数组。第三个参数one_hot_label设置是否将标签保存为one-hot表示,one-hot表示是仅正确标签为1,其余皆为0的数组。当one_hot_label为False时,只是像7、2这样简单的保存正确解标签。

# 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数组形式保存,显示时通过reshape()方法指定期望28x28像素的形状。此外,还需把保存为numpy数组的图像数据通过Image.fromarray()转换为PIL的数据对象。

神经网络的推理处理

神经网络的输入层有784个神经元,输出层有10个神经元。输入层的784这个数字来自图像大小的28x28=784,输出层的10来源于10类别分类。此外,神经元还有两个隐藏层,第1个隐藏层有50个神经元,第二个有100个神经元。50和100均可以设置为任意值。下面是代码(ch03/neural_mnist.py)中:

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

init_network()会读入保存在pickle文件中的学习权重参数。我们通过这个函数来实现神经网络的推理处理,然后评价它的识别精度

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循环依次取出,然后用predict()函数进行分类,用np.argmax(x)函数取出其中概率最大值的索引,作为预测结果。最后,比较神经网络预测的答案和正确解标签,将回答正确的概率作为识别精度。
这个例子中,我们把load_mnist函数的参数normalize设置成了True,函数内部进行转换,将图像各个像素值除以255,使数据的值在0.0~1.0的范围内,像这样把数据限定在某个范围内的处理称为正规化,此外,对神经网络的输入数据进行某种既定的转换成为预处理,这里作为对输入图像的预处理,我们进行了正规化。

批处理

我们通过输出神经网络各层的权重形状可以发现,多维数组的对应维度的元素是一致的,我们将打包输入多张图像后,仍可以保持这样的一致性,这种打包的输入数据成为,下面我们通过代码来实现:

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)))

通过range函数按批次大小获取数据,注意argmax()函数获取最大值的索引时添加参数axis=1,这就指定了在100x10的数组中,沿第1维方向找到最大值的索引。

文章如无特别注明均为原创! 作者: 果果, 转载或复制请以 超链接形式 并注明出处 GODAM|博客|godam
原文地址《 深度学习入门--手写数字识别》发布于2021-1-11

分享到:
打赏

评论

游客

切换注册

登录

您也可以使用第三方帐号快捷登录

切换登录

注册

sitemap