读书笔记《Deep Learning for Computer Vision with Python》- 第一卷 - 第20章 用于分类的开箱即用的CNN

读书笔记《Deep Learning for Computer Vision with Python》- 第一卷 - 第20章 用于分类的开箱即用的CNN,第1张

读书笔记《Deep Learning for Computer Vision with Python》- 第一卷 - 第20章 用于分类的开箱即用的CNN

下载地址

链接:https://pan.baidu.com/s/1hqtBQf6jRJINx4AgB8S2Tw 
提取码:zxkt 

        第一卷 第二十章 用于分类的开箱即用的CNN

        到目前为止,我们已经学会了如何从头开始训练我们自己的自定义卷积神经网络。这些CNN中的大多数都处于更浅的一面(并且在较小的数据集上),因此它们可以在我们的CPU上轻松训练,而无需求助于更多昂贵的GPU,它使我们能够掌握神经网络和深度学习的基础知识,而不必掏空口袋。

        然而,因为我们一直在处理更浅的网络和更小的数据集,所以我们无法充分利用深度学习为我们提供的分类能力。幸运的是,Keras库附带了五个经过预训练的CNN在ImageNet数据集上:

        ·VGG16

        ·VGG19

        ·ResNet50

        ·InceptionV3

        ·Xception

        正如我们在第5章中所讨论的,ImageNet大规模视觉识别挑战赛(ILSVRC)[42]的目标是训练一个模型,该模型可以将输入图像正确分类为1,000个单独的对象类别。这1,000个图像类别代表了我们在日常生活中遇到的对象类别,例如狗、猫、各种家用物品、车辆类型等等。

        这意味着,如果我们利用在ImageNet数据集上预先训练的CNN,我们可以立即识别所有这1,000个对象类别——无需训练!可以在此处找到可以使用预训练ImageNet模型识别的对象类别的完整列表ImageNet Large Scale Visual Recognition Competition 2014 (ILSVRC2014)。

        在本章中,我们将回顾Keras库中预先训练的最先进的ImageNet模型。然后,我将演示如何编写Python脚本来使用这些网络对我们自己的自定义图像进行分类,而无需从头开始训练这些模型。

        1、Keras中的CNN

        此时,您可能想知道:

        “我没有昂贵的GPU。我如何使用这些在比我们在本书中使用的数据集大得多的数据集上预先训练过的大规模深度学习网络?”

        要回答这个问题,请考虑关于参数化学习的第8章。回想一下,参数化学习的要点有两个:

        1.定义一个机器学习模型,它可以在训练期间从我们的输入数据中学习模式(需要我们在训练过程中花费更多时间),但测试过程要快得多。

        2.获得一个可以使用少量参数定义的模型,可以很容易地表示网络,而不管训练规模如何。

        因此,我们的实际模型大小是其参数的函数,而不是训练数据量。我们可以在100万张图像的数据集或100张图像的数据集上训练非常深的CNN(例如VGG或ResNet)——但是结果输出模型大小将相同,因为模型大小由我们选择的架构决定。

        其次,神经网络承担了绝大多数工作。我们将大部分时间花在实际训练CNN上,无论这是由于架构的深度、训练数据的数量,还是我们必须运行以调整超参数的实验数量。

        优化的硬件(例如GPU)使我们能够加快训练过程,因为我们需要在反向传播算法中执行前向传递和后向传递——正如我们已经知道的,这个过程就是我们的网络实际学习的方式。然而,一旦网络被训练,我们只需要执行前向传递来对给定的输入图像进行分类。前向传递速度要快得多,使我们能够在CPU上使用深度神经网络对输入图像进行分类。

        在大多数情况下,本章介绍的网络架构无法在CPU上实现真正的实时性能(为此我们需要GPU)——但这没关系;您仍然可以在自己的应用程序中使用这些预先训练好的网络。如果您有兴趣学习如何在具有挑战性的ImageNet数据集上从头开始训练最先进的卷积神经网络,请务必参考本书的ImageNet篇,我在其中演示了这一点。

        1.1VGG16、VGG19
VGG架构的可视化。将2242243个维度的图像输入到网络中。然后,在架构更深层次的最大池化 *** 作之前,仅应用33个卷积滤波器,并在彼此之上堆叠更多卷积。

 

        VGG网络系列的特点是仅使用3×3卷积层以增加深度相互堆叠。减少卷大小由最大池处理。两个完全连接的层,每个层都有4,096个节点,然后是一个softmax分类器。

        在2014年,16层和19层网络被认为非常深,尽管我们现在拥有ResNet架构,可以在50-200的深度上成功训练ImageNet及以上CIFAR-10为1,000。不幸的是,VGG有两个主要缺点:

        1.训练非常缓慢(幸运的是我们在本章中只测试输入图像)。

        2.网络权重本身相当大(就磁盘空间/带宽而言)。由于其深度和全连接节点的数量,VGG16的序列化权重文件为533MB,而VGG19为574MB。

        幸运的是,这些权重只需下载一次——从那里我们可以将它们缓存到磁盘。

        1.2RestNet
左:原始残差模块。右:使用预激活更新的残差模块

 

        由He等人首先介绍。在他们2015年的论文中,ResNet架构已成为深度学习文献中的一项开创性工作,表明可以使用标准SGD(和合理的初始化函数)通过使用残差模块。

        通过更新残差模块以使用身份映射(图20.2)可以获得进一步的准确性,如他们2016年的后续出版物《深度残差网络中的身份映射》[130]所示。

        也就是说,请记住,Keras核心库中的ResNet50(如50个权重层)实现是基于2015年的前一篇论文。尽管ResNet比VGG16和VGG19深得多,但由于使用了全局平均池化而不是全连接层,模型大小实际上要小得多,这将ResNet50的模型大小减少到102MB。

        如果您有兴趣了解有关ResNet架构的更多信息,包括残差模块及其工作原理,请参阅深入介绍ResNet的Practitioner篇和ImageNet篇。

        1.3Inception-V3
GoogLeNet中使用的原始Inception模块。Inception模块通过在网络的同一模块内计算1×1、3×3和5×5卷积来充当“多级特征提取器”。

        “Inception”模块(以及由此产生的Inception架构)是由Szegedy等人引入的。他们在2014年发表的论文。Inception模块(图20.3)的目标是通过在网络的同一模块内计算1×1、3×3和5×5卷积来充当“多级特征提取器”——这些过滤器的输出是然后沿着通道维度堆叠,然后被馈送到网络中的下一层。

        这种架构的最初版本被称为GoogLeNet,但后来的表现形式被简单地命名为InceptionvN,其中N指的是谷歌发布的版本号。包含在Keras核心中的InceptionV3架构来自Szegedy等人后来发表的RethinkingtheInceptionArchitectureforComputerVision(2015)[131],其中提出了对Inception模块的更新,以进一步提高ImageNet分类精度。InceptionV3的权重小于VGG和ResNet,为96MB。

        有关Inception模块如何工作(以及如何从头开始训练GoogLeNet)的更多信息,请参阅Practitioner篇和ImageNet篇。

        1.4Xception

        Xception是由Keras库的创建者和首席维护者FrançoisChollet本人在他2016年的论文Xception中提出的。Xception是对Inception架构的扩展,它用深度可分离卷积代替了标准的Inception模块。Xception权重是Keras库中最小的预训练网络,91MB。

        1.5可以做的更小么?

        虽然它没有包含在Keras库中,但我想提一下,当我们需要很小的空间时,经常使用SqueezeNet架构。SqueezeNet非常小,只有4.9MB,通常在需要训练网络然后部署到网络和/或资源受限设备时使用。

        同样,SqueezeNet不包含在Keras核心中,但我确实演示了如何在ImageNet篇内的ImageNet数据集上从头开始训练它。

SqueezeNet中的“fire”模块,由“squeeze”和“expand”组成
         2、使用预训练的ImageNet对图像进行分类

        让我们学习如何使用Keras库通过预训练的卷积神经网络对图像进行分类。我们不必更新我们迄今为止一直在开发的核心pyimagesearch模块,因为预训练模型已经是Keras库的一部分。

        只需打开一个新文件,将其命名为imagenet_pretrained.py,并插入以下代码:

        第2-13行导入我们所需的Python包。如您所见,大多数包都是Keras库的一部分。具体来说,第2-6行分别处理导入ResNet50、InceptionV3、Xception、VGG16和VGG19的Keras实现。请注意,Xception网络仅与TensorFlow后端兼容(如果您在使用Theano后端时尝试实例化该类将引发错误)。

        第7行让我们可以访问imagenet_utils子模块,这是一组方便的函数,可以让我们更轻松地预处理我们的输入图像和解码输出分类。

        其余的导入是其他辅助函数,然后是用于数值运算的NumPy和用于OpenCV绑定的cv2。

        接下来,让我们解析我们的命令行参数:

 

        我们只需要一个命令行参数--image,它是我们希望分类的输入图像的路径。我们还将接受一个可选的命令行参数--model,这是一个字符串,用于指定我们要使用哪个预训练的CNN——对于VGG16架构,该值默认为vgg16。

        鉴于我们通过命令行参数接受预训练网络的名称,我们需要定义一个Python字典,将模型名称(字符串)映射到它们的实际Keras类:

        第25-31行定义了我们的MODELS字典,它将模型名称字符串映射到相应的类。如果在MODELS中找不到--model名称,我们将引发AssertionError(第34-36行)。

        众所周知,CNN将图像作为输入,然后返回与类别标签对应的一组概率作为输出。在ImageNet上训练的CNN的典型输入图像大小是224×224、227×227、256×256和299×299;但是,您也可能会看到其他维度。

        VGG16、VGG19和ResNet都接受224×224个输入图像,而InceptionV3和Xception需要229×229个像素输入,如以下代码块所示:

 

        这里我们将inputShape初始化为224224像素。我们还将预处理函数初始化为Keras的标准preprocess_input(它执行均值减法,这是我们在PractitionerBundle中介绍的一种归一化技术)。但是,如果我们使用Inception或Xception,则需要将inputShape设置为299299像素,然后更新预处理以使用执行不同类型缩放的单独预处理函数。

        下一步是从磁盘加载我们预先训练好的网络架构权重并实例化我们的模型:

        第58行使用MODELS字典和--model命令行参数来获取正确的网络类。然后使用预训练的ImageNet权重在第59行实例化CNN。

        再次记住,VGG16和VGG19的权重是500MB。ResNet权重为100MB,而Inception和Xception权重在90-100MB之间。如果这是您第一次为给定的网络架构运行此脚本,这些权重将(自动)下载并缓存到您的本地磁盘。根据您的互联网速度,这可能需要一段时间。但是,一旦下载了权重,就不需要再次下载,从而使后续运行的imagenet_pretrained.py运行得更快。

        我们的网络现在已加载并准备好对图像进行分类——我们只需要通过预处理图像来准备用于分类的图像:

 

         第65行使用提供的inputShape从磁盘加载我们的输入图像以调整图像的宽度和高度。假设我们使用“通道最后”排序,我们的输入图像现在表示为一个形状为(inputShape[0],inputShape[1],3)的NumPy数组。

        但是,我们使用CNN批量训练/分类图像,因此我们需要通过第72行的np.expand_dims函数向数组添加一个额外的维度。调用np.expand_dims后,我们的图像现在将具有形状(1,inputShape[0],inputShape[1],3),再次假设通道最后排序。忘记添加这个额外的维度会导致调用模型的.predict方法时出错。

        最后,第76行调用适当的预处理函数来执行均值减法和/或缩放。

        我们现在准备通过网络传递我们的图像并获得输出分类:

 

         在第80行调用.predict会返回来自CNN的预测。鉴于这些预测,我们将它们传递到ImageNet实用程序函数.decode_predictions中,为我们提供ImageNet类标签ID、“人类可读”标签以及与每个类标签相关联的概率的列表。然后在第85和86行将前5个预测(即具有最大概率的标签)打印到我们的终端。

        我们的最终代码块将处理通过OpenCV从磁盘加载我们的图像图像,在图像上绘制#1预测,最后将其显示到我们的屏幕上:

         2.1分类结果

         要使用预先训练的网络和Keras对图像进行分类,只需使用我们的imagenet_pretrained.py脚本,然后提供(1)您希望分类的输入图像的路径以及(2)您希望分类的网络架构的名称用。

        我在下面的Keras中包含了每个可用的预训练网络的示例命令:

        下面的图显示了为各种输入图像生成的结果。在每种情况下,给定网络架构预测的标签都准确地反映了图像的内容。

将各种预训练的ImageNet网络应用于输入图像的结果。在每个示例中,预训练网络返回正确的分类。
         3、小结

        在本章中,我们回顾了在Keras库中的ImageNet数据集上预训练的五个卷积神经网络:

        1.VGG16

        2.VGG19

        3.ResNet50

        4.InceptionV3

        5.Xception

        然后我们学习了如何使用这些架构中的每一个来对您自己的输入图像进行分类。鉴于ImageNet数据集包含您在日常生活中可能会遇到的1,000个流行对象类别,这些模型构成了出色的“通用”分类器。根据您自己学习深度学习的动机和最终目标,仅这些网络就足以构建您想要的应用程序。

        但是,对于有兴趣学习更高级技术以在更大数据集上训练更深网络的读者,我绝对建议您通读Practitioner篇。对于想要完整体验并了解如何在具有挑战性的ImageNet数据集上训练这些最先进网络的读者,请参阅ImageNet篇。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5443211.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存