深度学习理论基础12-手写数字识别

本节实践一下'前向传播'.即将使用真正的数据和模型了(虽然这个模型不是自己训练的),

想想还是有点小激动嗯。(马上就能发明机器人,推翻人类暴政,走向人生巅峰了。)

本节大体分为3个内容

想办法搞到图片数据

一次处理一张

一次处理100张(批量且高效率的)

--------MNIST数据集--------

这是机器学习领域最出名的数据集之一。

MNIST数据集是由0到9的数字图像构成的。图像数据是28像素 × 28像素的灰度图像。

像素的取值在0到255之间。每个图像数据都相应地标有“7”“2”“1”等标签

训练图像有6万张,测试图像有1万张

下面开始把这些数据下载下来。这里提供获取数据的代码。获取的细节不再展开讨论。

大约就是用urllib请求了一些网站,下载了一些数据。以下是获取这些数据的代码(以及其他章节的所有代码)

https://share.weiyun.com/5HteQuq

 

根据网速情况,下载或许耗时几分钟或更久。

因为Python有pickle功能,把对象转化为一个文件。所以在第二次及以后读入数据的时候速度会很快。

如果对Python的pickle功能有兴趣,可以询问可爱的度娘。

--------显示一副图像以验证这个数据集--------

现在写一个程序,显示一张图片,以证明这个数据集下载成功并且是有效的。

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):
    #把img数组转化成Image可以读取的对象
    pil_img = Image.fromarray(np.uint8(img))
    #显示这个图片对象
    pil_img.show()


#得到数据集
#flatten=True代表需要得到1维的数据,normalize=False代表不要正规化(0-1之间)
(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,)
#因为数据被1维化了,所以此处需要把维度转化为28*28的图像尺寸
img = img.reshape(28, 28) # 把图像的形状变成原来的尺寸
print(img.shape) # (28, 28)
img_show(img)

 

这是存放这个代码的位置:

运行成功之后:

数据的获取及验证部分就这样完成了。下面进行神经网络的推理处理。

--------神经网络的推理--------

介绍下这个神经网络的构成:

输入层:28*28=784个神经元

输出层:0-9一共10个分类。所以有10个神经元。

此外,这个神经网络有2个隐藏层,第1个隐藏层有50个神经元,

第2个隐藏层有100个神经元。这个50和100可以设置为任何值。

推理过程与《深度学习理论基础10-实现一个3层神经网络》的区别在于,

之前的权重是乱写的,而本节的权重是训练出来的(当然,不是我们训练的,这节只负责直接拿来用),

因为这些权重是有效的,所以我们可以在本节看到效果,要想看到效果,也就是正确率,

就需要写一个这个神经网络预测的结果与实际结果的差距,这也是本节需要完成的程序。

下面梳理一下需要做的事情:

1.准备一个获取数据集的函数

2.准备一个获取权重信息的函数

3.准备一个通过数据集及权重信息进行推理的神经网络函数

4.准备一个统计真实结果与预测结果相同数量的函数

5.运行主函数,查看效果

做这些之前,先导入必要的模块

from yuan.dataset.mnist import load_mnist
import pickle
import numpy as np

为了方便操作,yuan文件夹已被制作成模块(在此文件夹加一个空的__init__.py文件即可)

另外,神经网络的推理需要激活函数,之前的章节已经实现过:

#隐藏层激活函数
def sigmoid_function(x):
    return 1/(1+np.exp(-x))


#输出层激活函数
def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

做完这些,开始我们的计划

第一步,准备一个获取数据集的函数

# 1.准备一个获取数据集的函数
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

第二步,准备一个获取权重信息的函数

# 2.准备一个获取权重信息的函数
def get_weight():
    #你应该保证sample_weight.pkl文件的路径是正确的
    #这个文件就是实例经过pickle模块的dumps打包之后的文件(这里我们直接拿来用)
    sample_weight_path='./yuan/ch03/sample_weight.pkl'
    with open(sample_weight_path, 'rb') as f:
        #把这个文件重新还原成了实例
        network = pickle.load(f)
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']
    #返回了各层的权重和偏置
    return W1, W2, W3, b1, b2, b3

第三步,准备一个通过数据集及权重信息进行推理的神经网络函数

# 3.准备一个通过数据集及权重信息进行推理的神经网络函数
# 这个过程也叫前向传播(forward propagation)
def forward_propagation(x,network):
    W1, W2, W3, b1, b2, b3=network
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid_function(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid_function(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)
    return y

第四步,准备一个统计真实结果与预测结果相同数量的函数

# 4.准备一个统计真实结果与预测结果相同数量的函数
def get_accuracy():
    network=get_weight()
    x, t = get_data()
    #这个变量用于记录正确的预测数量
    accuracy_cnt = 0
    for i in range(len(x)):
        #逐个预测结果
        y = forward_propagation(x[i],network)
        p = np.argmax(y)  # 获取概率最高的元素的索引
        #对预测结果与真实结果对比
        if p == t[i]:
            accuracy_cnt += 1
    #返回正确比例
    return str(float(accuracy_cnt) / len(x))

第五步,运行主函数,查看效果

# 5.运行主函数,查看效果
def main():
    Accuracy=get_accuracy()
    print(Accuracy) #输出0.9352


if __name__=='__main__':
    main()

 

最后的0.9352就是这个模型的正确率。每1000个数字图片它能认识935个。

不错不错。这个成绩甚至超过幼儿园小朋友了。

前几年神经网络刚出现的时候,我在果壳看到图像识别的报道简直吓尿了。这太强大了。

没想到此刻我也写出了这样的程序(实际情况是直接拿别人数据和模型来用----->吹牛从来不脸红)。

为了榨干numpy的最后一滴血,接下来进行图片的批处理。

(因为np有一些强大的算法很适合批量处理,比用循环一张一张的处理快很多。)

--------批处理--------

预警:矩阵积乘没学好的,请回炉重造。批处理正是通过矩阵积乘的方法进行的。

上图是刚才进行单张图片推理的示意图。

输入其实可以看做1行,784列的矩形。最终输出一个1行10列的矩阵。

批处理,我们要做的部分就是把输入变成多行784列。这样,输出也会变成多行10列。

就像下面这样:

这样在第四步,有了一个替代方案:

#4_2.批处理图像结果
def batch_get_accuracy():
    network=get_weight()
    x, t = get_data()
    #这个变量用于记录正确的预测数量
    batch_size = 100  # 批数量
    accuracy_cnt = 0
    for i in range(0, len(x), batch_size):
        x_batch = x[i:i + batch_size]
        y_batch = forward_propagation(x_batch,network )
        p = np.argmax(y_batch, axis=1)
        accuracy_cnt += np.sum(p == t[i:i + batch_size])
    #返回正确比例
    return str(float(accuracy_cnt) / len(x))

可以看到,循环次数减少了100倍(因为步长变成了100)

forward_propagation(x_batch,network ) 这一步,就像上面的图片所描述的一样,会返回100*10的形状
np.argmax(y_batch, axis=1)则负责把每一行的最大值的索引取出来(也就是最大概率所在的索引位置,即预测结果)
t[i:i + batch_size]则是从正确的答案中截取一截。

所以p == t[i:i + batch_size]的实质是一串预测值与一串真实值比较。其bool结果之和就是正确数量。

至此,本节的内容就结束了。下一节开始神经网络的学习。

---------结语--------

本节除了获取数据及权重环节,其余部分都是之前知识的应用。不理解的地方完全可以在前面的章节找到答案。

下一节见。

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值