【深度学习】“复杂场景下基于深度学习的卷积神经网络在鸟类多类别识别中的模型设计与性能优化研究”(中)
大家好 我是寸铁👊
【深度学习】“复杂场景下基于深度学习的卷积神经网络在鸟类多类别识别中的模型设计与性能优化研究”(中)✨
喜欢的小伙伴可以点点关注 💝
前言
本次【深度学习】"复杂场景下基于深度学习的卷积神经网络在鸟类多类别识别中的模型设计与性能优化研究"分为上、中、下
三个部分,后续持续更新,感兴趣的朋友可以继续关注~
代码无偿,记得进入网站fork一下谢谢!
全部源代码地址:
github.com/Joyflower/Brid_CCN/tree/master/
随着科技的进步和深度学习技术的广泛应用,卷积神经网络(CNN)作为一种强大的图像识别工具,在复杂环境中的应用日益引起关注。特别是在鸟类多类别识别这一领域,CNN展现出了巨大的潜力和应用前景。然而,面对复杂场景下的挑战,如光照变化、背景噪声和鸟类姿态的多样性,如何设计和优化CNN模型以提高识别的准确性和鲁棒性仍然是一个重要的研究课题。
本研究旨在探索基于深度学习的卷积神经网络在鸟类多类别识别中的应用潜力,通过深入分析模型设计和性能优化的方法,以应对复杂环境带来的挑战。通过系统的实验验证和性能评估,本研究试图为解决实际应用中的识别难题提供创新的解决方案和理论支持。
模型构建
模型训练流程图
图17 模型构建、编译流程图
由上图17得,模型构建、编译流程如下:
(1) 先构建模型,堆叠卷积神经网络不同类型的层来逐步提取输入图像的特征。
(2) 再编译模型,保存模型的回调函数。
(3) 然后,传入训练集、测试集,进行模型的训练。
(4) 最后,绘制准确率、损失曲线、混淆矩阵,编写图像分类报告。保存到指定的文件夹。
设置机器参数
在创建训练模型之前可以先根据需求读取线程,设置模型的训练量和缓冲区的大小。
接下来,通过map方法配置数据集,在使用数据集时自动调用线程。
首先,使用AUTOTUNE = tf.data.experimental.AUTOTUNE
:这里设置了一个自动调整参数,用于自动选择最佳的并行处理线程数。
接着,使用map
函数应用了load_img
函数,将图像数据加载并进行预处理。load_img
函数的入参为原始图像数据,出参为经过预处理后的图像数据。num_parallel_calls
参数指定了并行处理的线程数,得到加载处理后的训练集、测试集。利用了TensorFlow
提供的并行处理机制,加速数据加载和预处理的过程。
最后,分别设置训练数据集的批量大小和缓冲区大小BATCH_SIZE = 24
和BUFFER_SIZE = 1000
,批量大小决定了每次训练时模型使用的样本数量,缓冲区大小用于在数据加载过程中进行样本打乱操作的缓冲。选择BATCH_SIZE = 24
和BUFFER_SIZE = 1000
的设置是在考虑了可用的硬件资源、数据集大小和分布情况后得出的一个合理选择,既能充分利用计算资源,又能保持数据加载和训练的高效率。如下图18所示。
图18 线程与缓冲区设置
测试集、训练集的预取、打乱
然后,继续对训练数据集和测试数据集的打乱、分批次和预取数据的操作。调用
shuffle
函数用于打乱数据集,batch
函数用于将数据集划分成批次,prefetch
函数用于提前从输入数据集中预取数据,以减少训练过程中的等待时间,使得模型在训练时能够更加高效地利用计算资源。对训练数据集和测试数据集进行预处理、构建数据加载和处理的管道,并使用TensorFlow
提供的并行处理机制加速数据处理过程,以及利用缓冲和预取机制提高数据加载和训练效率。如下图19所示。
图19 打乱、分批次、预取数据
构建CNN模型
输入图片规格
首先,定义输入图片的形状规格大小为256x256
像素,3
个颜色通道(RGB
)。如下图20所示:
图20 输入图片规格大小
接着,创建一个顺序模型,即一个由一系列层按顺序堆叠而成的模型。模型构建的原理是通过堆叠不同类型的层来逐步提取输入图像的特征,并最终输出对应的分类结果。这个模型中包含以下类型的层:
tf.keras.layers.Input(shape=input_shape)
: 输入层,用于指定输入数据的形状。如下图21所示:
图21 输入层搭建
构建卷积层
- 在使用
TensorFlow.keras.Sequential
方法构建模型时,我们建立了一个卷积神经网络(CNN
)。首先,模型堆叠了两层卷积层,每层都包含64
个通道,卷积核大小为3x3
,并使用ReLU
作为激活函数。ReLU作为激活函数有多个优势。在反向传播过程中,它有助于避免梯度消失问题。ReLU函数将一部分神经元的输出设为0
,从而增加了网络的稀疏性,减少了参数之间的依赖关系,有助于缓解过拟合问题。 - 与此同时,卷积神经网络
CNN
用relu函数作为激活函数有着不少优势,如反向传播时,可以避免梯度消失。Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。相对于sigmoid
激活函数,tanh
激活函数,求导简单。采用sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。 - 卷积层主要用于对输入数据进行特征提取。每个卷积层内部包含多个卷积核,这些卷积核由权重系数和偏差量组成,类似于前馈神经网络中的神经元。卷积核的每个元素都对应着一个权重系数和一个偏置值,这些元素在卷积运算过程中与输入数据进行相乘和累加,从而实现对输入数据的特征提取。
再构建批量归一化层,用于加速模型训练过程并提高模型的泛化能力。如下图22所示。
通过卷积操作,卷积层能够有效地捕获输入数据中的空间结构信息,从而识别和提取出有用的特征。
图22 卷积层的构建
构建池化层
- 在插入两层卷积层之中则是插入一层池化层。
池化层是夹在连续的卷积层中间,用于压缩数据和参数的量。模型使用池化层首先是因为池化层可以保证特征不变性,也就是我们在图像处理中经常提到的特征的尺度不变性,池化操作就是图像的resize
,平时一张狗的图像被缩小了一倍我们还能认出这是一张狗的照片,这说明这张图像中仍保留着狗最重要的特征,我们一看就能判断图像中画的是一只狗,图像压缩时去掉的信息只是一些无关紧要的信息,而留下的信息则是具有尺度不变性的特征,是最能表达图像的特征。还有一个是池化层可以使特征降维,我们知道一幅图像含有的信息是很大的,特征也很多,但是有些信息对于图像任务时没有太多用途或者有重复,可以将这类冗余信息去除,把最重要的特征抽取出来。
结合模型的最优型,选择最大池化层: 最大池化层,用于降低特征图的空间维度。如下图23所示:
图23 最大池化层的搭建
继续按照卷积层、批量归一化层、最大池化层逐层堆叠搭建模型,在插入一层池化层之后,堆叠两层包含
128个通道
,卷积核为3*3
,激活函数为relu函数的卷积层。然后又是一层池化层,然后堆叠两层包含256个通道,卷积核为3*3
,激活函数为relu函数
的卷积层。再堆叠一层池化层,接着堆叠两层包含512
个通道,卷积核为3*3
,激活函数为relu
函数的卷积层。然后是最后一层池化层,跟着堆叠三层包含512
个通道,卷积核为3*3
,激活函数为relu函数
的卷积层。如下图24所示:
图24 逐层堆叠搭建模型
构建全局平均池化层
图25 全局平均化池层构建
由上图25所示:创建了一个全局平均池化层,用于处理输入的特征图。在卷积神经网络中,卷积层生成的特征图(
feature map
)通常是一个多维数组,包含了通过卷积操作提取的特征信息。全局平均池化层的作用是对每个特征图中的所有元素进行求平均值的操作。
具体来说,对于每个特征图,全局平均池化层
会计算该特征图中所有元素的平均值。这个操作有助于减少特征图的空间尺寸
,同时保留重要的特征信息。通常,全局平均池化层用于在卷积神经网络的最后阶段,将多维特征图转换为一个固定长度的向量
,以便于连接到分类器或输出层
。
构建全连接层
图26 全连接层构建
由上图26所示:先创建了一个全连接层(
Dense层
),其中包含256
个神经元。全连接层的作用是将上一层的所有输入连接到这256个神经元上,并使用ReLU
作为激活函数。ReLU(Rectified Linear Unit)激活函数会将所有负的输入值变为0
,而正值则保持不变,这有助于网络学习非线性关系和特征。再添加了一个批量归一化层。批量归一化通过在每个小批量数据中标准化前一层的激活值,使得输出更加稳定和快速收敛。这有助于提高模型的训练速度,并且能够在一定程度上充当正则化器,减少过拟合问题。
最后,创建了另一个全连接层(Dense层),包含200个神经元。该层使用softmax
激活函数,适用于处理多分类问题,如图像分类。Softmax
函数会将神经网络的输出转换为一个概率分布
,即每个类别的预测概率。模型被设计为能够识别200
种不同的鸟类,因此输出层的神经元数为200
。
模型编译
在搭建完模型之后是输出模型的摘要信息,方便训练模型时在控制台查看模型的信息。如图27输出模型摘要所示:
图27输出模型摘要
输出模型摘要信息之后是指明训练参数,通过模型
model
调用compile
方法进行设置,compile方法之中包含了3
个参数,先是设置optimizer
参数的值,通过该参数设置优化器,该参数的值可以是字符串形式给出的优化器名字,也可以是函数形式,使用函数形式可以设置学习率、动量和超参数。接着是设置loss
参数的值,表示损失函数,该参数的值可以是字符串形式给出的损失函数的名字,也可以是函数形式。再然后是设置metrics
参数的值,该参数用于标注网络评价指标,例如"accuracy"
则代表y_
和y
都是数值,如y_=[1]y=[1]
,其中y_为真实值,y为预测值
。这里对参数的设置如图28编译模型所示。
图28 编译模型
编译模型之后,定义保存模型的回调函数,避免过拟合并确保模型在验证集上的最佳性能得到保留。
先指定filepath
参数,保存模型的文件路径为models/best_model.h5.keras
。.h5.keras
是文件的后缀名,表示这是一个Keras模型的HDF5格式的保存文件。
再将save_best_only
参数设置为True
,表示只有当在验证集上的性能比之前保存的模型好时,才会保存当前的模型。这样可以确保最终保存的是在验证集上表现最好的模型。
然后指定要监视的指标,monitor
参数是val_accuracy
,即验证集上的准确率。模型训练过程中会定期检查这个指标的值,并根据其变化决定是否保存模型。
设置mode
参数为max
,表示希望验证准确率的值越大越好。这与monitor
参数中的指标一致,指示了最佳模型的选择标准。
将verbose
参数设置为1
,表示输出一些保存模型时的提示信息,以便在训练过程中可以看到模型保存的进展情况。
通过以上设置,ModelCheckpoint
回调函数会在每次验证集上计算准确率时,检查当前模型的性能。如果发现当前模型比之前保存的最佳模型效果更好(根据val_accuracy指标),则会将当前模型保存到指定路径下的best_model.h5.keras
文件中。这种方法有助于避免过拟合并确保模型在验证集上的最佳性能得到保留。如下图29所示:
图29 定义保存模型的回调函数
模型训练
训练模型
-
再然后是通过
model
变量调用fit方法训练模型,
先调用model.fit
方法,这是Keras
模型对象的一个方法,用于训练模型。它会将训练数据输入模型,并根据指定的损失函数和优化器来优化模型参数,以使模型的预测结果与实际标签尽可能接近。 -
传入用于训练的数据集
train_ds
,通常是一个包含特征和标签的数据集对象。在训练过程中,模型将会使用这个数据集来学习特征和标签之间的关系。
再设置训练的轮数epochs
,即将整个训练数据集输入模型并进行一次参数更新的次数。在这里,将训练数据集循环训练30
次,每次称为一个epoch
。 -
传入用于验证模型性能的数据集
validation_data
。在每个epoch
结束时,模型会使用这个数据集来评估其在未见过的数据上的性能。 -
定义一个回调函数列表
callbacks=[checkpoint_callback]
,包含了在训练过程中要执行的回调函数。在这里,checkpoint_callback
是用来保存模型权重的回调函数,在每次验证准确率提升时,会将模型的权重保存下来。 -
这样的设置有助于有效地训练神经网络模型,并且及时保存在验证集上性能最好的模型。通过设定合适的训练轮数(
epochs
),我们可以让模型充分地学习训练数据集的特征,并且避免过拟合。通过在每个 epoch 结束时使用验证集来评估模型的性能,我们可以及时发现模型在未见过的数据上的表现,从而调整模型的参数或者停止训练以避免过拟合。同时,通过使用回调函数checkpoint_callback
,我们可以在训练过程中自动保存模型的权重,以便后续使用。这样的设置可以提高模型训练的效率和稳定性,同时也方便了模型的管理和部署。如下图30所示:
图30 训练模型
绘制图像
首先是绘制成功率与失败率
采用的是matplotlib.pyplot
模块的plot
方法,方法内的参数包括history
对象的epoch
属性来获取训练次数作为参数,还有history
属性获取对应的字典作为参数,这里字典主要包括四部分,'acc'
表示训练成功,'val_acc'
表示验证成功,'loss'
表示训练失败,'val_loss'
表示验证失败,然后再获取模型中对应的部分作为参数,分开的部分如字典一样分开。最后,将绘制的图像按照指定的文件夹路径,存入相应的文件夹。
具体绘制过程如图31、32所示。
图31绘制模型训练的成功率
图32 绘制模型训练的失败率
最后则是绘制分类报告和混淆矩阵,并按照指定路径存放绘制的分类报告和混淆矩阵到指定的文件夹位置。如下图33、34所示。
y_pred = model.predict(test_ds)
:对测试数据进行预测,得到每个样本属于各个类别的概率。
y_pred = np.argmax(y_pred, axis=1)
:将预测结果转换为类别序号,选择概率最高的类别作为预测结果。
print(classification_report(test_labels, y_pred, target_names=labels_names))
:输出分类报告,其中包括了每个类别的精确度(precision)、召回率(recall)、F1 值(F1-score)等评估指标。test_labels
是测试数据的真实标签,labels_names
是类别名称。
cm = confusion_matrix(test_labels, y_pred)
:计算混淆矩阵,混淆矩阵是一个 N × N 的矩阵(N 表示类别的数量),用于展示模型的预测结果与真实标签之间的差异。
可视化混淆矩阵:
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
:使用蓝色调色板(Blues)将混淆矩阵以图像形式显示。plt.title("Confusion Matrix")
:设置图像标题为"Confusion Matrix"。plt.colorbar()
:添加颜色图例。tick_marks = np.arange(len(labels_names))
:创建标签刻度。plt.xticks(tick_marks, labels_names, rotation=45)
和plt.yticks(tick_marks, labels_names)
:设置 x 轴和 y 轴的刻度标签。thresh = cm.max() / 2.
:计算阈值,用于将文本颜色设置为黑色或白色。for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1]))
:遍历混淆矩阵的每个元素。plt.text(j, i, cm[i, j], ...)
:在图像中的每个单元格中添加混淆矩阵的值。plt.tight_layout()
:自动调整子图参数,以确保图像内容适合图像区域。plt.ylabel('True label')
和plt.xlabel('Predicted label')
:设置 y 轴和 x 轴的标签。plt.show()
:显示图像。
通过打印分类报告和显示混淆矩阵,可以了解模型在测试数据上的分类性能、各类别之间的混淆情况以及模型的准确性。
图33 绘制分类报告
图34 绘制混淆矩阵
结语
本研究通过对复杂场景下鸟类多类别识别的深度学习卷积神经网络进行详尽的模型设计和性能优化研究,取得了一定的成果和深入的理论洞见。实验结果表明,所提出的优化策略和方法有效提升了识别系统在复杂环境中的稳定性和准确性。然而,未来的研究仍可进一步扩展到更广泛和更复杂的场景,如不同季节、地理位置和鸟类物种的多样性,以探索模型的泛化能力和适应性。
这项工作不仅为深度学习在生物多样性监测、环境保护和生态学研究中的应用提供了新的思路和方法,也为相关领域的进一步发展和应用奠定了坚实的基础。期望本研究能够为未来的技术创新和实际应用提供有益的参考和启示。
看到这里的小伙伴,恭喜你又掌握了一个技能👊
希望大家能取得胜利,坚持就是胜利💪
我是寸铁!我们下期再见💕
往期好文💕
保姆级教程
【保姆级教程】Windows11下go-zero的etcd安装与初步使用
【保姆级教程】Windows11安装go-zero代码生成工具goctl、protoc、go-zero
【Go-Zero】手把手带你在goland中创建api文件并设置高亮
报错解决
【Go-Zero】Error: user.api 27:9 syntax error: expected ‘:‘ | ‘IDENT‘ | ‘INT‘, got ‘(‘ 报错解决方案及api路由注意事项
【Go-Zero】Error: only one service expected goctl一键转换生成rpc服务错误解决方案
【Go-Zero】【error】 failed to initialize database, got error Error 1045 (28000):报错解决方案
【Go-Zero】Error 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)报错解决方案
【Go-Zero】type mismatch for field “Auth.AccessSecret“, expect “string“, actual “number“报错解决方案
【Go-Zero】Error: user.api 30:2 syntax error: expected ‘)‘ | ‘KEY‘, got ‘IDENT‘报错解决方案
【Go-Zero】Windows启动rpc服务报错panic:context deadline exceeded解决方案
Go面试向
【Go面试向】defer与time.sleep初探
【Go面试向】defer与return的执行顺序初探
【Go面试向】Go程序的执行顺序
【Go面试向】rune和byte类型的认识与使用
【Go面试向】实现map稳定的有序遍历的方式