it|从零开始构建并编写神经网络---Keras【学习笔记】[1/2]

优质资源分享

学习路线指引(点击解锁) 知识定位 人群定位
Python实战微信订餐小程序 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
Python量化交易实战 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统
Keras简介: Keras是由纯python编写的基于theano/tensorflow的深度学习框架。
??Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需求,可以优先选择Keras:
  1. 简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)
  2. 支持CNN和RNN,或二者的结合
  3. 无缝CPU和GPU切换
Keras官网首页
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WnKSC4p9-1654449650750)(https://img2022.cnblogs.com/blog/2745075/202206/2745075-20220601225945507-629925755.png “Keras官网首页logo”)]
一、背景 本次构建神经网络最终目的:输入一张手写数字图片后,网络输出该图片对应的数字。
二、Keras代码实现 2.1 导入Keras库
import tensorflow as tf from tensorflow.keras.datasets import mnist

如果没有安装TensorFlow,那么可以参考我之前的文章:重装CUDA和cuDNN(目的是装TensorFlow和pytorch)【个人梳理总结】
2.2 加载数据集(训练集和测试集) 我们使用Keras下的MNIST手写字符数据集,可以使用如下命令下载数据集:
(train_images, train_labels), (test_images, test_labels) = keras.datasets.mnist.load_data() ''' load\_data() returns tuple of NumPy arrays: (x\_train, y\_train), (x\_test, y\_test). train\_images: uint8 NumPy array of grayscale image data with shapes (60000, 28, 28), containing the training data. Pixel values range from 0 to 255. train\_labels: uint8 NumPy array of digit labels (integers in range 0-9) with shape (60000,) for the training data. test\_images: uint8 NumPy array of grayscale image data with shapes (10000, 28, 28), containing the test data. Pixel values range from 0 to 255. test\_labels: uint8 NumPy array of digit labels (integers in range 0-9) with shape (10000,) for the test data. '''

下面是选做步骤~
如果想验证一下各个变量的shape可以使用python中的断言关键字:
assert train_images.shape == (60000, 28, 28) assert train_labels.shape == (10000, 28, 28) assert test_images.shape == (60000,) assert test_labels.shape == (10000,)

我们可以使用matplotlib先为我们显示一下测试集第一张图片,请记住它:
digit = test_images[0] import matplotlib.pyplot as pltplt.imshow(digit, cmap=plt.cm.binary)# 输出二值化图像 plt.show()

需要安装matplotlib,请移步至Matplotlib 3.5.2 documentation
或者可以打印test_labels,记住第一个元素的label是什么。
print('test\_labels', test_labels)

不出意外的话结果是“7”。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bXlIYdhg-1654449650755)(https://img2022.cnblogs.com/blog/2745075/202206/2745075-20220605123023429-560745067.png “7”)]
2.3 搭建神经网络 Sequential序贯模型是多个网络层的线性堆叠,也就是“一条路走到黑”。
??可以通过向Sequential模型传递一个layer的list来构造该模型,也可以像本文使用的通过.add()方法一个个的将layer加入模型中:
from tensorflow.keras import models from tensorflow.keras import layersnetwork = models.Sequential()# 创建实例命名为network。Sequential意为顺序的,即序贯模型。 network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))# 第一层需要加一个input\_shape关键字参数 network.add(layers.Dense(10, activation='softmax'))# ①输出层的units=10,意味着存在10个类别,实际意义为输出的结果是从0~10这是个数字。②我们想要将结果的分类数值范围限定在[0,1]之间,理论上activation也可以换成其他能够将结果限定在[0,1]的激活函数

关于Dense层的理解,可以阅读深入理解 KERAS 中 DENSE 层参数
此时,我们可以通过一些命令整体查看搭建的神经网络(可任选其一):
network.summary()# 输出一下搭建的神经网络框架总结 tf.keras.utils.plot_model(network, "my\_first\_network.png")# 图形化输出 keras.utils.plot_model(network, "my\_first\_network\_with\_shape\_info.png", show_shapes=True)# 带有输入shape和输出shape的图形化输出

输出结果省略,各位可在实践中自行感受。
完成模型的搭建后,我们需要使用.compile()方法来编译模型:
  • 优化器optimizer:该参数可指定为已预定义的优化器名,如rmspropadagrad,或一个Optimizer类的对象;
  • 损失函数loss:该参数为模型试图最小化的目标函数,它可为预定义的损失函数名,如categorical\_crossentropymse,也可以为一个损失函数;
  • 指标列表metrics:对分类问题,我们一般将该列表设置为metrics=['accuracy']。指标可以是一个预定义指标的名字,也可以是一个用户定制的函数。指标函数应该返回单个张量,或一个完成metric\_name - > metric\_value映射的字典。
network.compile(optimizer='rmsprop', loss='categorical\_crossentropy', metrics=['accuracy'])

2.4 数据预处理 2.4.1 对训练集和测试集的数据部分预处理
  • 将每张图片数据由(28, 28)的二维数组变成(28 * 28)的一维数组
  • 将灰度图中[0, 255]的整数灰度值归一化为[0, 1]的浮点数
train_images = train_images.reshape((60000, 28 * 28)) train_images = train_images.astype('float32') / 255 test_images = test_images.reshape((10000, 28 * 28)) test_images = test_images.astype('float32') / 255

2.4.2 对训练集和测试集的标签部分预处理
【it|从零开始构建并编写神经网络---Keras【学习笔记】[1/2]】对应输出层的units=10,将标签做one-hot编码,用一个拥有10个元素的一位数组替换标签。我们需要把数值7变成一个含有10个元素的数组,然后在第8个元素设置为1,其他元素设置为0,即[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.]
from tensorflow.keras.utils import to_categoricalprint("before change:", test_labels[0]) train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels) print("after change: ", test_labels[0])

你一定发现了我们使用了to\_categorical函数。它是将类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵, 用于应用到以categorical\_crossentropy为目标函数的模型中.
??而我们在使用.compile()方法来编译模型参数中损失函数loss=‘categorical_crossentropy’,这符合多分类的要求。
2.5 开始对神经网络进行训练
network.fit(train_images, train_labels, epochs=5, batch_size=128) """ 传入fit()各变量的含义: train\_images:用于训练的手写数字图片; train\_labels:对应的是图片的标记; batch\_size=128:每次网络从输入的图片数组中随机选取128个作为一组进行计算。 epochs=5: 每次计算训练数据将会被遍历5次。 fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况。 """

2.6 测试神经网络的训练效果 测试数据输入,检验网络学习后的图片识别效果。
??P.S. 识别效果与硬件有关(CPU/GPU)
本人使用的TensorFlow 2.5搭配GPU为:NVIDIA GeForce GTX 1660 Ti with Max-Q Design computeCapability: 7.5(辣鸡啊!多么想要一个3080!!!)
test_loss, test_acc = network.evaluate(test_images, test_labels, verbose=1) # verbose: 日志记录——0:静默不显示任何信息,1(default):输出进度条记录 print('test\_loss', test_loss)# 打印loss print('test\_acc', test_acc)# 打印accuracy

展示训练过程输出信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gMxCXLsR-1654449650756)(https://img2022.cnblogs.com/blog/2745075/202206/2745075-20220605131159686-1867568715.png “训练过程截图”)]
2.7 神经网络的预测能力 随机输入一张手写数字图片到网络中,看看它的识别效果
(train_images, train_labels), (test_images, test_labels) = mnist.load_data() digit = test_images[1]# 挑选测试集第2张图片,是数字2plt.imshow(digit, cmap=plt.cm.binary) plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yazx62Tf-1654449650757)(https://img2022.cnblogs.com/blog/2745075/202206/2745075-20220605131523972-665138977.png “2”)]
test_images = test_images.reshape((10000, 28*28)) res = network.predict(test_images)# 应用已经训练好的模型进行预测for i in range(res[1].shape[0]):# 提取第二个预测结果,即对数字2的预测结果 if res[1][i] == 1:# 看结果中10个元素的数组中第几位是1 print("the number for the picture is : ", i)# 第几位是1就输出这个数字的预测结果是几 break

展示预测结果输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbbfbF9K-1654449650758)(https://img2022.cnblogs.com/blog/2745075/202206/2745075-20220605131616227-70854464.png “预测结果”)]
结尾 至此,我们完成了借助Keras编写出一个简单的预测手写数字的神经网络并完成了训练、测试和预测过程,实现了我们最初的目的。
??当然Keras的功能强大远不止于本文所展示的内容,更多丰富且便利的功能请各位继续参考附录学习探索。
??接下来我们还将继续学习,尝试不借助Keras而是依托numpy等库,更加贴近“从零开始”构建一个神经网络。
??最最重要的,本文一定存在错误和不足,恳请各位不吝赐教,不吝赐教!谢谢~!
附录一:有帮助的文档 1. 【官方】The Functional API
2. 【官方】The Model class
3. 【官方】The Sequential class
4. 【官方】Layer activation functions
5. Keras中文文档
附录二:网络上的好文分享 1. 深度学习笔记 目标函数的总结与整理 model.compile(loss=‘categorical_crossentropy’

    推荐阅读