使用 Python 和 TensorFlow 创建一个神经网络

神经网络是许多现代人工智能 (AI) 应用的核心。人工神经网络 (ANN) 是一个松散地基于大脑结构的模型:它由称为神经元的连接元素组成,每个连接都有一个数值权重。卷积神经网络 (CNN) 是一种特殊类型的人工神经网络,可以解决计算机视觉 (CV) 问题,例如图像分类、对象检测和一般识别。

CNN 的主要构建块是卷积层。这些层由提取图像中相关特征的小过滤器组成,每一层都根据前一层的输入提取更多抽象特征——一直到最终结果。这种方法非常有效,以至于最先进的 CNN 在准确识别大集合中不同人的面部方面可以胜过人类。

在本文中,我们将向您展示如何从头开始创建一个非常简单的 CNN 用于图像分类。我们将使用以下工具:

  • Anaconda* Navigator来管理我们的项目
  • 用于开发基础代码的英特尔® Distribution for Python *
  • 英特尔® TensorFlow *优化,用于构建和训练我们的神经网络

我们假设您熟悉 Python 并具备神经网络的基本知识来遵循本指南。

您可以使用以下 Anaconda 命令安装软件包的 Intel 发行版:

Python
<span style="color:#000000"><span style="background-color:#fbedbb">conda install -c intel intelpython
conda install -c intel tensorflow</span></span>

我们建议您在工作机器上使用这些工具设置深度学习 (DL) 环境,如 使用 Python 和 Anaconda 构建深度学习环境一文中所述。

你的第一个神经网络

我们将使用 Python 和 TensorFlow 创建一个 CNN,该 CNN 获取一个从 0 到 9 的输入数字的小图像,并输出它是什么数字。这是一个很好的开始用例,将为您理解 TensorFlow 框架的关键原理奠定良好的基础。

我们将使用 Intel Optimization for TensorFlow,它优化了在 Intel ®架构上运行时的 TensorFlow 性能。此优化的核心是英特尔® oneAPI 深度神经网络库 (oneDNN),它是一组用于 DL 应用程序的构建块,其中包括卷积层和池化层——任何 CNN 模型的基本组件。该库是英特尔® oneAPI Base Toolkit的一部分,后者是一组库,用于跨不同架构开发高性能 AI、机器学习 (ML) 和其他应用程序。

所有 oneAPI 组件的编程模型是统一的,因此它可以使用相同的代码部署在 CPU、GPU 或 FPGA 上。英特尔继续开发 oneAPI 组件以支持新的处理器并通过利用新的指令集扩展来优化性能。

使用 oneDNN 原语作为核心 TensorFlow 算法的后端实现,可为 DNN 模型提供更高的性能,并确保针对更新的处理器架构优化性能。

让我们开始编码

让我们从简单的 CNN 开始。该神经网络对带有输入数字的图像进行分类。网络的输入将是一个 28 × 28 像素的小灰度图像,输出将是从 0 到 9 的每个数字的概率数组。第一步是构建 CNN 的 TensorFlow 模型。我们将使用Keras API 来完成这项任务,因为在创建您的第一个神经网络时它更容易理解。

在您的 DL 环境中编写并运行以下代码:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">导入</span>操作系统
os.environ[ <span style="color:#800080">' </span><span style="color:#800080">TF_ENABLE_ONEDNN_OPTS'</span> ]= <span style="color:#800080">' </span><span style="color:#800080">1'</span>

<span style="color:#0000ff">导入</span>张量流
张量流.__版本__</span></span>

代码的前两行为会话开启oneDNN优化,最后两行检查 TensorFlow 框架的版本。请注意,从TensorFlow 2.9开始,oneDNN 优化默认开启,如果您希望在没有这些优化的情况下测试性能,则必须将其设置为 0。

接下来,使用输入层初始化 CNN 模型:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.models<span style="color:#0000ff">导入</span>顺序
<span style="color:#0000ff">从</span>tensorflow.keras.layers<span style="color:#0000ff">导入</span>输入

模型=顺序()
inp = 输入(形状=(28 , 28 , 1))
模型.add(inp)</span></span>

我们为我们的 CNN 使用了“顺序”模型。该模型具有最简单的结构,具有顺序层,其中一层的输出是下一层的输入。然后,我们将输入层添加到模型中。所有 TensorFlow 模型都需要知道输入数据的类型。在我们的例子中,这是一个具有 28、28 和 1 三个维度的张量。该输入对应于具有一个颜色通道的 28 × 28 像素的图像(灰度图像)。

卷积层

让我们继续编写以下代码:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.layers<span style="color:#0000ff">导入</span>Conv2D
conv = Conv2D( 32 , ( 5 , 5 ), padding= <span style="color:#800080">"</span><span style="color:#800080">相同"</span> , strides=( 1 , 1 ))
模型.add(conv)</span></span>

该代码初始化一个卷积层“Conv2D”并将其放在第一个输入层之后。这个卷积层是我们神经网络的关键元素。它负责从输入图像中提取几何特征,然后由下一层使用。我们创建了具有 32 个大小为 (5, 5) 的内核(或过滤器)的层。接下来的两个参数指定如何将这些过滤器应用于输入图像:strides 指定垂直和水平移动,而 padding 指定是否必须用额外的像素填充输入图像以处理输入数据。

激活层

任何卷积层后面都应该有一个激活层。该层向模型引入了一个激活函数,该函数根据其权重和输入来控制神经元是否会“触发”(提供输出)。近期深度神经网络 (DNN) 最流行的激活函数是整流线性单元(ReLU)。以下代码将激活层添加到我们的模型中:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.layers<span style="color:#0000ff">导入</span>激活
conv_act = 激活(<span style="color:#800080">“ </span><span style="color:#800080">relu”</span>)
model.add(conv_act)</span></span>

池化层

DNN 的另一个重要元素是池化操作。该操作的目标是减少将馈送到下一层的数据的空间维度。我们将使用最大池化操作,因为它已被证明在 CNN 模型中对特征图进行下采样是有效的。

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.layers<span style="color:#0000ff">导入</span>MaxPooling2D

池 = MaxPooling2D(( 4 , 4 ))
模型。添加(池)</span></span>

添加的 MaxPooling2D 层使用 (4, 4) 的池大小进行初始化。这意味着图层数据输出的空间维度在垂直轴和水平轴上都减少了四倍。因此,最初的 28 × 28 像素图像在第一层之后被缩小为 7 × 7 数字输出,依此类推。

池化操作有两个目的。一是使模型独立于提取的特征位置的微小差异,二是减少后续处理层的数据量,从而使模型更快。

到目前为止可视化我们的模型

现在,我们的模型由四层组成:输入、卷积、激活和池化。在模型构建的任何阶段,我们都可以通过调用 model.summary 方法查看其结构信息。该方法的输出如下图所示:

我们可以看到关于每一层的输出形状的信息。例如,在池化层之后,我们可以看到输出的空间维度从 28 到 7 减少了四倍,正如预期的那样。另一个重要的信息是每一层中可训练参数的数量。我们模型中的卷积层有 832 个这样的参数。可训练参数是层的系数(权重),其值随训练过程调整。它们的数量直接影响训练时间:数量越大,训练过程越长。

扁平和密集层

让我们继续使用以下代码构建模型:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.layers<span style="color:#0000ff">导入</span>Flatten
<span style="color:#0000ff">从</span>tensorflow.keras.layers<span style="color:#0000ff">导入</span>密集

扁平=扁平化()
模型.add(平面)
   	
密集=密集(128)
model.add(密集)

dense_act = 激活(<span style="color:#800080">“ </span><span style="color:#800080">sigmoid”</span>)
model.add(dense_act)</span></span>

在此之后,我们的模型输出以下摘要:

上面的代码添加了一个“扁平化”层,它将池化层的三维张量(7、7、32)转换为具有 1568 个分量的扁平向量。然后它在模型中添加一个具有 128 个神经元和一个 sigmoid 激活函数的“密集”层。这就是所谓的隐藏全连接层。它位于最后一个分类层之前,其目标是在神经模型的最后部分构建多层感知器 (MLP),因为 MLP 通常是分类神经网络中的最后一个块。

分类层

我们模型的最后一层必须是具有 10 个输出值的分类层:每个数字的概率。我们将使用具有 10 个神经元的密集层和 Softmax 激活函数作为现代分类器模型的常见选择。

Python
<span style="color:#000000"><span style="background-color:#fbedbb">出=密集(10)
模型.add(out)

out_act = 激活(<span style="color:#800080">“ </span><span style="color:#800080">softmax”</span>)
model.add(out_act)</span></span>

我们模型的最终总结如下图所示:

训练模型

模型创建的下一阶段是加载训练和验证数据集。我们将使用一个小型数据集1  ,其中训练数据中的每个数字都有 100 个图像,验证数据中的每个数字有 10 个图像。下载数据集并将其提取到您的工作文件夹。我们使用ImageDataGenerator类,它是一个实用类,提供数据集加载、图像预处理和数据增强等功能。要加载数据集,请在模型创建后立即运行以下代码:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.preprocessing.image<span style="color:#0000ff">导入</span>ImageDataGenerator
datagen = ImageDataGenerator(rescale=1.0/255. 0 )

train_dataset = datagen.flow_from_directory( <span style="color:#800080">" </span><span style="color:#800080"><your-train-data-file-path-here>"</span> , color_mode= <span style="color:#800080">'</span><span style="color:#800080">灰度'</span> , target_size=( 28 , 28 ), class_mode= <span style="color:#800080">" </span><span style="color:#800080">categorical"</span> )
val_dataset = datagen.flow_from_directory( <span style="color:#800080">" </span><span style="color:#800080"><your-validation-data-file-path-here>"</span> , color_mode= <span style="color:#800080">' </span><span style="color:#800080">grayscale'</span> , target_size=( 28 , 28 ), class_mode= <span style="color:#800080">" </span><span style="color:#800080">categorical"</span> )</span></span>

这将使用 rescale 参数初始化生成器,以将图像数据归一化为 [0, 1.0] 的区间。加载数据时,我们将类模式指定为分类模式,以便为我们的分类问题生成适当的数据。

最后一步是使用数据集训练我们的模型

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.optimizers<span style="color:#0000ff">导入</span>SGD

opt_method = SGD(learning_rate=0. 1 )
模型。<span style="color:#339999">编译</span>(优化器=opt_method,损失= <span style="color:#800080">“</span><span style="color:#800080">分类交叉熵”</span>,指标=[ <span style="color:#800080">“</span><span style="color:#800080">准确性”</span> ])

历史 = model.fit(train_dataset,validation_data=val_dataset,epochs=10)</span></span>

我们使用 SGD 优化器,它应该是训练新模型时的默认选择。是多类分类问题的categorical_crossentropy推荐损失函数。对于我们的简单模型和小数据集来说,10 个训练 epoch 的数量就足够了。这是训练过程的输出:

该模型的最终准确率为 96.6% 的训练数据和 94% 的验证数据。请注意,由于过程的不确定性,使用相同数据训练相同模​​型可能会产生略有不同的结果。

测试它

现在我们可以测试模型并针对单个图像运行它:

Python
<span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">从</span>tensorflow.keras.preprocessing.image<span style="color:#0000ff">导入</span>load_img
<span style="color:#0000ff">从</span>tensorflow.keras.preprocessing.image<span style="color:#0000ff">导入</span>img_to_array

img_file = <span style="color:#800080">" </span><span style="color:#800080"><your-test-data-file-path-here>\\7.png"</span> 
img = load_img(img_file, color_mode = <span style="color:#800080">" </span><span style="color:#800080">grayscale"</span> )
img_array = img_to_array(img)
in_data = img_array.reshape(( 1 , 28 , 28 , 1 ))/255。0

prob = model.predict(in_data)[ 0 ]
数字 = prob.argmax()
digit_prob = 概率[数字]

<span style="color:#0000ff">print</span> (prob)
 <span style="color:#0000ff">print</span> ( <span style="color:#800080">"</span><span style="color:#800080">预测数字 = "</span> + <span style="color:#339999">str</span> (digit))
 <span style="color:#0000ff">print</span> ( <span style="color:#800080">"</span><span style="color:#800080">数字概率 = "</span> + <span style="color:#339999">str</span> (digit_prob))</span></span>

我们得到以下输出:

Python
<span style="color:#000000"><span style="background-color:#fbedbb">[ 7 .85533484e- 05  1 .45643018e- 03  1 .24442745e- 02  1 .29656109e- 03 
 1 .41729815e- 05  4 .06741965e- 05  4 .37598487e- 07  9 .83559847e- 01 
 3 .04310001e- 04  8 .04647047e- 04 ]
预测数字 = 7
数字概率 = 0。98355985</span></span>

该模型正确预测图像包含数字 7 的概率约为 98%。

恭喜!你已经创建了你的第一个神经网络。如果您希望保存训练好的模型,可以使用以下命令:

Python
<span style="color:#000000"><span style="background-color:#fbedbb">model.save( <span style="color:#800080">" </span><span style="color:#800080"><your-model-file-path-here>"</span> )</span></span>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值