手把手带你建一个识别手写数字的神经网络,这是入门人工智能技术的基础

文摘   2024-11-22 21:51   广东  

用 Tensorflow 框架搭建识别手写数字的神经网络模型,需要用到python,未安装先点击查看 安装python

可以把 TensorFlow 想成一个机器学习的魔法工具箱。它提供了一整套工具,可以用来创建、训练和优化各种“聪明”的模型,比如能识别图片、预测趋势、聊天对话等。

TensorFlow 的核心就是帮助你设计和训练一种“思考”的程序。你把数据交给它,它就会像学徒一样学习、调整,直到变得越来越好用,最后能够自己去判断和预测。
安装Tensorflow
打开命令行,输入下面这条命令开始安装,可能需要花费几分钟,耐心等待安装完成。
命令 pip install tensorflow
注意,tensorflow可能会对python的版本和pip的版本有要求,如果安装失败,请检查网络问题或版本问题。

该怎么写这个代码?不知道写什么那就对了。接下来一步一步来构建一个能识别手写数字神经网络。先看完整代码

新建一个文件夹比如叫number,新建一个文件比如main.py,用代码编辑器打开这个py文件,比如程序员最常用的vscode。

第一行代码:

import tensorflow as tf


这段代码是导入我们安装好的tensorflow工具包,我们就可以用这个工具包来构建一个计算机神经网络。由于这个包名太长了不方便输入,我们用tf来代替它,所以有了上面这条语句。

第二行代码:

mnist tf.keras.datasets.mnist


这行代码很简单,就是取出tensorflow里的一个数据集工具,命名为mnist,keras是tf里面一个高级的工具库,所谓高级就像一台空调,你不需要知道制冷的原理是什么,你只要拿遥控器一按,空调就吹出你指定温度的空气。

同理,你也不需要知道keras里的工具具体是怎么实现的,你只需要知道怎么使用它就行。

我们都知道,训练神经网络时需要使用大量的数据,称为数据集datasets,这些数据需要按照一定的格式要求,所以在计算机神经网络中,对数据集的处理是第一步。而mnist就是一份用来训练识别手写数字的数据集。

第三行代码:

(x_trainy_train)(x_testy_test) = mnist.load_data()


这行代码有意思了,需要一点python代码基础,从右往左看,mnist.load_data()会下载这份数据集,最后会返回两个元组,元组是python中的一种数据结构,这两个元组我们对应用(x_trainy_train)(x_testy_test)来接收。


如果你想知道x_train具体是什么,可以print(x_train),你会发现这是一个三维数组,它有600028*28的数据,这个6000张好理解,那这个28*28的数组为什么是图片?

28*28的数据就能代表一个正方形图片了,只不过是以数据的格式存储,这个过程需要在脑海中进行理解,这是一张大部分地方是0,有灰度值的地方就用0-255的数字表示。如果我们把大于0的数值当作1,逐行输出这个28*28的二维数组,就能大概看到一个数字,所以使用数字代表一张图片是可行的,计算机可以更好地处理这种数据结构。

y_train 是六千张图片对应的数,比如上面这份数据是对应的y_train就是8,这就能告诉计算机神经网络这个数是什么数了。

x_test, y_test就是用来做验证时候用,在训练好模型之后,使用测试数据集可以快速地对已经训练好的模型进行评估,这一点在后面的代码会提到。

第四行代码:

x_trainx_test = x_train / 255.0x_test / 255.0


这个过程是把原本数据集所有数值(0-255)变成0-1之间的浮点数,比如原本值是255,那么255/255就是1.0,如果原本值是232232/255就会是0.9098039215686274。有时候就很感慨python语法的简洁,语句简单却功能强大。

这个过程有个专业的说法叫做归一化,实际经验告诉告诉我们,归一化后的数据可以提升我们的训练效果,做这个识别手写数值的项目把数据归一化会更好。

第五行开始我们要构造一个四层神经网络模型:

model = tf.keras.models.Sequential([  tf.keras.layers.Flatten(input_shape=(28, 28)),  tf.keras.layers.Dense(128, activation='relu'),  tf.keras.layers.Dropout(0.2),  tf.keras.layers.Dense(10)])

这段代码看起来就有难度了,实际上这也很简单,Sequential是构造顺序模型的函数,这个函数的参数是一个层的列表,上面这个模型包含四层。我们暂时不进行探究每个层究竟是什么东西,我们现在只需要知道每个层的作用。

第一层:

tf.keras.layers.Flatten(input_shape=(28, 28))的作用是将28*28的二维数组展平成一个784维的数组。


这个理解很简单,我们轻轻松松地对输入的数据结构进行改变,这就是使用高级工具的魅力。

第二层:

tf.keras.layers.Dense(128, activation='relu'),Dense的意思是稠密的,这个层又叫全连接层,这个Dense函数的第一个参数128,代表有128个输出维度,activation='relu'表示激活函数是ReLU,激活函数对计算机神经网络来说非常重要,它决定了每一个神经元的输出,有许多种常见的激活函数我们先不说。这里用到的ReLU是Rectified Linear Unit的简写,翻译为修正线性单元。


其实这个ReUL很简单,就是把负数变成0,在这个案例中为什么要用ReUL这种激活函数不用其他激活函数?这是个好问题但不在这篇文章的讨论范围,激活函数的种类的教程以及如何选择激活函数会另外的篇幅中介绍。

第三层:

tf.keras.layers.Dropout(0.2),这是一个Dropout层,这会随机丢弃掉一些神经元,参数0.2代表每个输出的维度数据有20%的概率被丢弃(变成0),随机丢弃一些维度可以防止过拟合。


什么是过拟合,这就好像考试,你考试之前把题目和答案都背了,那你肯定能全对,但你不是真正的懂了题。过拟合就是防止模型过分关注数据集与答案的关系而忽略了识别学习数字的特征,其中的一种方法就是随机丢弃一些神经元,这简单有效,还有其他防止过拟合的方法但不在本文的教学范围。

第四层:

tf.keras.layers.Dense(10),这个层和第二层一样,是一个全连接层,但因为这是最后一层了,所以不需要激活函数,其中的10就是说明有10个维度的输出,最后得到的是一个10维的数组,数组中不同的位置代表不同的数字的概率。


这样就完成了神经网络结构的搭建,接下来的目标,就是让这个四层的计算机神经网络模型进行训练。在训练之前我们需要定义损失函数,损失函数会告诉我们模型的预测错的有多离谱,损失函数返回的数值越小,说明模型预测更准确。

第十一行开始,我们定义一个损失函数。

loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(  from_logits=True  )

上面这是稀疏类别交叉熵损失,现在看不懂就对了,我们可以把识别手写数字0-9的这个问题看作是一个分类问题,稀疏类别交叉熵损失函数就是一种评估分类问题的损失函数。from_logits=True 表示输入是未经 softmax 转换的原始 logits,这句话你一会儿就理解了。

第十四行到十六行,我们配置这个模型,做训练前的最后准备训练,代码如下。

model.compile(optimizer='adam',              loss=loss_fn,              metrics=['accuracy'])

指定了优化器、损失函数以及评估指标。优化器optimizer='adam',在机器学习中,优化器有很多种,会在专门的篇幅讲解优化器,现在只需要知道优化器是用来更新模型参数以最小化损失函数的算法,是一种让模型预测能力变得越来越好的算法,metrics=['accuracy']指定指标为正确率,不设置指标并不会影响模型的训练结果,设置指标会在每一轮训练时显示这个指标,比如'accuracy'就是正确率,会在每一轮训练时显示,我们能看到正确率在变化。

第十七行代码:

model.fit(x_train, y_train, epochs=5)

开始训练,训练轮次为5轮,我们可以在控制台上看到训练的进度条。

第十八行代码:

model.evaluate(x_test,  y_test, verbose=2)

这是用来评估模型性能的一条语句,用数据集里提取的x_text和y_text来评估这个模型,verbose表示输出信息的详细程度,值为0表示不显示,1表示只显示进度条,2(也有进度条)表示在每个轮输出一行信息,通常包括损失值和任何设置的评估指标,反正大部分时候你用2就对了,最后会得到评估结果。

第十九到二十二行:

probability_model = tf.keras.Sequential([  model,  tf.keras.layers.Softmax()])

这段代码就是把之前的模型model加上一层Softmax层,变成一个最后输出为概率的概率模型。


Softmax 层是一个常用的激活函数,这个层让每一个预测变成和为一的概率分布,没有经过Softmax层之前的概率值之和不是1,也不知道具体是多少,通过Softmax层之后,就能变成概率分布了,这个计算的原理很简单,比如数组[5, 8, 7],这三个数字之和等于20,那么把5/20得到0.258/20得到0.47/20得到0.35,这不就有了一个和为1的概率分布了,结果是[0.25, 0.4, 0.35],这就是概率模型的原理。

回到十一行说的:from_logits=True 表示输入值是未经 softmax 转换的原始 logits。在深度学习中,logits模型输出的未经Softmax转化为概率分布的值,这应该不难理解。学习嘛,最重要的就是搞清楚什么是什么。

最后一行:

远远Faraway
互联网原住民,每日冲浪,让我们一起思考、一起成长
 最新文章