使用 PyTorch 进行高效图像分割:第 2 部分

一、说明

        这是由 4 部分组成的系列的第二部分,旨在使用 PyTorch 中的深度学习技术从头开始逐步实现图像分割。本部分将重点介绍如何实现基线图像分割卷积神经网络(CNN)模型。

图 1:使用 CNN 运行图像分割的结果。按从上到下的顺序,输入图像、地面实况分割掩码、预测分割掩码。

二、文章大纲

        在本文中,我们将实现一个名为SegNet的基于卷积神经网络(CNN)的架构,它将输入图像中的每个像素分配给相应的宠物,如猫或狗。不属于任何宠物的像素将被归类为背景像素。我们将使用 PyTorch 在牛津宠物数据集上构建和训练此模型,以了解交付成功的图像分割任务所需的条件。模型构建过程将是动手操作的,我们将详细讨论模型中每一层的作用。本文将包含大量对研究论文和文章的参考,以供进一步学习。

        在本文中,我们将引用此笔记本中的代码和结果。如果要重现结果,则需要 GPU 来确保笔记本在合理的时间内完成运行。

三、本系列文章

        本系列面向所有深度学习经验水平的读者。如果您想了解深度学习和视觉AI的实践以及一些扎实的理论和实践经验,那么您来对地方了!这将是一个由 4 部分组成的系列,包含以下文章:

  1. 概念和想法
  2. 基于 CNN 的模型(本文)
  3. 深度可分离卷积
  4. 基于视觉变压器的模型

让我们从对卷积层和其他一些通常一起用作卷积块的层的简短介绍开始讨论。

四、Conv-BatchNorm-ReLU 和 Max Pooling/Unpooling

        卷积、批量归一化、ReLU 块是视觉 AI 的三位一体。你会看到它经常与基于 CNN 的视觉 AI 模型一起使用。这些术语中的每一个都代表在 PyTorch 中实现的不同层。卷积层负责对输入张量执行学习过滤器的互相关操作。批量归一化将批次中的元素居中为零均值和单位方差,ReLU 是一种非线性激活函数,仅保留输入中的正值。

        典型的CNN随着层的堆叠而逐渐减小输入空间维度。下一节将讨论缩小空间维度背后的动机。这种减少是通过使用简单的函数(如最大值或平均值)汇集相邻值来实现的。我们将在最大池化部分进一步讨论这个问题。在分类问题中,转换-BN-ReLU-池块堆栈后跟一个分类头,用于预测输入属于目标类之一的概率。某些问题集(如语义分割)需要按像素进行预测。对于这种情况,在下采样块之后附加一堆上采样块,以将其输出投影到所需的空间维度。上采样块只不过是 Conv-BN-ReLU-Unpool 块,它们用非池化层替换池化层。我们将在最大池化部分详细讨论取消池化。

现在,让我们进一步阐述卷积层背后的动机。

五、卷积

        卷积是视觉 AI 模型的基本构建块。它们在计算机视觉中大量使用,历史上一直用于实现视觉转换,例如:

  1. 边缘检测
  2. 图像模糊和锐化
  3. 凹凸
  4. 强化

卷积运算是两个矩阵的元素乘法和聚合。卷积操作示例如图 2 所示。

图 2:卷积操作的图示。来源:作者

        在深度学习上下文中,卷积是在称为过滤器的 n 维参数矩阵或较大输入上的内核之间进行的。这是通过在输入上滑动滤波器并将卷积应用于相应部分来实现的。幻灯片的范围是使用步幅参数配置的。一步意味着内核滑过一步以执行下一部分。与使用固定滤波器的传统方法相反,深度学习使用反向传播从数据中学习过滤器。

那么卷积如何帮助深度学习呢?

在深度学习中,卷积层用于检测视觉特征。典型的CNN模型包含一堆这样的层。堆栈中的底层检测简单的特征,例如线条和边缘。当我们在堆栈中向上移动时,这些层会检测到越来越复杂的特征。堆栈中的中间层检测线条和边缘的组合,顶层检测复杂的形状,如汽车、面部或飞机。图 3 直观地显示了经过训练的模型的顶层和底层的输出。

图 3:卷积过滤器学习识别的内容。来源:卷积深度信念网络,用于分层表示的可扩展无监督学习

        卷积层具有一组可学习的过滤器,这些过滤器作用于输入中的小区域,以为每个区域生成具有代表性的输出值。例如,3x3 筛选器在 3x3 大小的区域上运行,并生成代表该区域的值。在输入区域重复应用滤波器会产生一个输出,该输出成为堆栈中下一层的输入。直观地说,较高的层可以“看到”输入的更大区域。例如,第二个卷积层中的 3x3 滤波器对第一个卷积层的输出进行操作,其中每个单元都包含有关输入中 3x3 大小区域的信息。如果我们假设 stride=1 的卷积操作,那么第二层中的过滤器将“看到”原始输入的 5x5 大小区域。这称为卷积的感受野。卷积层的重复应用逐渐减小了输入图像的空间维度,并增加了滤波器的视野,使它们能够“看到”复杂的形状。图 4 显示了卷积网络对一维输入的处理。输出层中的元素代表相对较大的输入块。

图 4:内核大小 = 1 的一维卷积的感受野,应用 3 次。假设步幅=3 且没有填充。在卷积核连续第三次应用后,单个像素能够在原始输入图像中看到 1 个像素。来源:作者

        一旦卷积层可以检测到这些对象并能够生成它们的表示,我们就可以使用这些表示进行图像分类、图像分割以及对象检测和定位。从广义上讲,CNN遵循以下一般原则:

  1. 卷积层要么保持输出通道©的数量不变,要么将其加倍。
  2. 它使用 步幅=1 保持空间维度不变,或使用步幅=2 将其减少到一半。
  3. 通常将卷积块的输出池化以更改图像的空间维度。

        卷积层将内核独立地应用于每个输入。这可能会导致其输出因不同的输入而异。批处理规范化层通常遵循卷积层来解决此问题。让我们在下一节中详细了解它的作用。

六、批量规范化

        批次归一化图层将批次输入中的通道值归一化为零均值和单位方差。此归一化对批处理中的每个通道独立执行,以确保输入的通道值具有相同的分布。批量规范化具有以下优点:

  1. 它通过防止梯度变得太小时来稳定训练过程。
  2. 它在我们的任务上实现了更快的收敛。

        如果我们所拥有的只是一堆卷积层,由于线性变换的级联效应,它基本上等同于单个卷积层网络。换句话说,一系列线性变换可以替换为具有相同效果的单个线性变换。直观地说,如果我们将一个常数 k₁ 的向量乘以另一个常数 k₂,则相当于单次乘以常数 k₁k₂。因此,为了使网络具有现实深度,它们必须具有非线性以防止其崩溃。我们将在下一节中讨论经常用作非线性的ReLU。

七、激活函数Qdot

        ReLU是一个简单的非线性激活函数,它削波最低输入值以大于或等于0。它还有助于解决将输出限制为大于或等于 0 的梯度消失问题。ReLU 图层后通常跟一个池化层,用于缩小缩小子网中的空间维度,或一个非池化层,用于提升子网中的空间维度。下一节将提供详细信息。

八、池化

        池化层用于缩小输入的空间维度。步幅 = 2 的池化会将空间维度为 (H, W) 的输入转换为 (H/2, W/2)。最大池化是深度 CNN 中最常用的池化技术。它将网格中的最大值(例如)2x2 投影到输出上。然后,我们根据类似于卷积的步幅将 2x2 池化窗口滑动到下一部分。使用 step=2 重复执行此操作会导致输出高度的一半和宽度的一半。另一个常用的池化层是平均池化层,它计算平均值而不是最大值。

        池化层的反面称为非池化层。它采用 (H, W) 尺寸输入并将其转换为 (2H, 2W) 尺寸输出,步幅 = 2。此转换的必要组成部分是在输出的 2x2 部分中选择位置以投影输入值。为此,我们需要一个最大解池索引映射,它告诉我们输出部分中的目标位置。此取消池化映射由之前的最大池化操作生成。图 5 显示了池化和取消池化操作的示例。

图 5:最大池化和取消池化。来源:DeepPainter:使用深度卷积自动编码器的Painter分类

我们可以将最大池化视为一种非线性激活函数。但是,据报道,使用它来替换诸如ReLU之类的非线性会影响网络的性能。相反,平均池化不能被视为非线性函数,因为它使用其所有输入来产生其输入的线性组合输出。

这涵盖了深度CNN的所有基本构建块。现在,让我们将它们放在一起以创建一个模型。我们为本练习选择的模型称为SegNet。我们接下来会讨论它。

九、SegNet:基于CNN的模型

      SegNet是一个基于我们在本文中讨论的基本块的深度CNN模型。它有两个不同的部分。底部(也称为编码器)对输入进行下采样,以生成代表输入的特征。顶部解码器部分对特征进行上采样,以创建每像素分类。每个部分由一系列 Conv-BN-ReLU 块组成。这些模块还分别在下采样和上采样路径中包含池化或取消池化层。图 6 更详细地显示了各层的排列。SegNet 使用编码器中最大池化操作中的池化索引来确定在解码器中的最大池化操作期间要复制哪些值。虽然激活张量的每个元素都是 4 字节(32 位),但 2x2 正方形内的偏移量可以仅使用 2 位存储。这在使用内存方面更有效,因为这些激活(或 SegNet 中的索引)需要在模型运行时存储。

图 6:用于图像分割的 SegNet 模型架构。来源:SegNet:用于图像分割的深度卷积编码器-解码器架构

        此笔记本包含此部分的所有代码。

        此模型具有 15.27M 的可训练参数。

        在模型训练和验证期间使用了以下配置。

  1. 随机水平翻转颜色抖动数据增强应用于训练集以防止过度拟合
  2. 在非宽高比保留调整大小操作中将图像大小调整为 128x128 像素
  3. 不会对图像应用输入规范化;而是使用批量归一化层作为模型的第一层
  4. 该模型使用 LR 为 20.0 的 Adam 优化器和每 001 个 epoch 将学习率衰减 0.7 的 StepLR 调度器训练 7 个 epoch
  5. 交叉熵损失函数用于将像素分类为属于宠物、背景或宠物边框

该模型在 88 个训练周期后实现了 28.20% 的验证准确率。

我们绘制了一个 gif,显示了模型如何学习预测验证集中 21 张图像的分割掩码。

 

图 6:一个 gif,显示了 SegNet 模型如何学习预测验证集中 21 张图像的分割掩码。来源:作者

本系列的第 1 部分介绍了所有验证指标的定义。

如果你想看到一个使用Tensorflow实现的用于分割宠物图像的全卷积模型,请参阅第4章:高效深度学习的高效架构一书。

十、模型学习的观察结果

        基于训练模型在每个纪元之后做出的预测的发展,我们可以观察到以下内容。

  1. 该模型能够学习足够的知识,使输出看起来在图像中宠物的正确球场上,甚至早在 1 个训练时期
  2. 边框像素更难分割,因为我们使用的是未加权损失函数,该函数平等地对待每个成功(或失败),因此弄错边框像素不会使模型在损失方面付出太多代价。我们鼓励您对此进行调查,并检查您可以尝试哪些策略来解决此问题。尝试使用焦点损失,看看它的表现如何
  3. 即使在 20 个训练时期之后,该模型似乎仍在学习。这表明,如果我们训练模型的时间更长,我们可以提高验证准确性。
  4. 有些真实标签本身很难搞清楚——比如中间一排狗的面具,最后一列在狗的身体被植物遮挡的区域有很多未知像素。这对于模型来说很难弄清楚,因此人们应该始终期望此类示例的准确性下降。但是,这并不意味着该模型表现不佳。除了查看整体验证指标外,还应始终抽查预测以了解模型的行为。

图 7:包含大量未知像素的地面实况分割掩码示例。对于任何 ML 模型来说,这都是非常困难的输入。来源:作者

十一、结论

        在本系列的第 2 部分中,我们了解了用于视觉 AI 的深度 CNN 的基本构建块。我们看到了如何在 PyTorch 中从头开始实现 SegNet 模型,并可视化了在连续时期训练的模型如何在 21 张验证图像上执行。这应该可以帮助您了解模型可以多快地学习到足以使输出看起来在正确的球场上。在这种情况下,我们可以看到分割掩码,它早在第一个训练时期就与实际分割掩码大致相似!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/78467.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【无标题】QT应用编程: QtCreator配置Git版本控制(码云)

QT应用编程: QtCreator配置Git版本控制(码云) 感谢:DS小龙哥的文章,这篇主要参考小龙哥的内容。 https://cloud.tencent.com/developer/article/1930531?areaSource102001.15&traceIdW2mKALltGu5f8-HOI8fsN Qt Creater 自带了git支持。但是一直没…

Github下载任意版本的VsCode

下载历史版本VsCode(zip) 下载链接由三部分组成: 固定部分commit idVSCode-win32-x64-版本号.zip 固定部分: https://vscode.cdn.azure.cn/stable/ Commit id: 打开 vscode的GitHub:[https://github.com/microsoft/vscode/r…

echarts 柱状图-折线图-饼图的基础使用

上图示例图表展示相关配置: var myChart echarts.init(this.$refs.firstMain);myChart.setOption({legend: { // 图例设置top: "15%",type: "scroll",orient: "vertical",//图例列表的布局朝向。left: "right",pageIconCo…

记录一个编译TubeTK时的报错:at_check问题

在使用如下命令安装TubeTK的cuda_nms时,报了一个错误,记录一下这个错误和解决办法 (base) redmeryredmery:~/Desktop/MOT/TubeTK/post_processing/nms$ python setup.py build_ext --inplace因为这个命令是在/home/redmery/Desktop/MOT/TubeTK/install/…

泛微 E-Office文件上传漏洞复现

声明 本文仅用于技术交流,请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 文章作者拥有对此文章的修改和解释权。如欲转载或传播此文章&#xff0c…

回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测

回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测 目录 回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测&#x…

【刷题笔记8.17】LeetCode:最长公共前缀

LeetCode:最长公共前缀 (一)题目描述 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 (二)分析 纵向扫描时,从前往后遍历所有字符串的每一列&am…

【面试高频题】难度 3/5,字典树热门运用题

题目描述 这是 LeetCode 上的 「745. 前缀和后缀搜索」 ,难度为 「困难」。 Tag : 「字典树」 设计一个包含一些单词的特殊词典,并能够通过前缀和后缀来检索单词。 实现 WordFilter 类: WordFilter(string[] words) 使用词典中的单词 words 初…

Appium-移动端自动测试框架,如何入门?

Appium是一个开源跨平台移动应用自动化测试框架。 既然只是想学习下Appium如何入门,那么我们就直奔主题。文章结构如下: 1、为什么要使用Appium? 2、如何搭建Appium工具环境?(超详细) 3、通过demo演示Appium的使用 4、Appium如何…

《计算机网络:自顶向下方法》第五章--网络层:控制平面

控制平面作为一种网络范围的逻辑,不仅控制沿着从源主机到目的主机的端到端路径间的路由器如何转发数据报,而且控制网络层组件和服务如何配置和管理 传统上,控制平面功能与数据平面的转发功能在一起实现,在路由器中作为统一的整体…

手机技巧:推荐一款手机省电、提升流畅度APP

目录 软件详情 基本介绍 软件功能 软件特色 使用方法 软件对比 结论 今天给大家推荐一款手机省电、提升流畅度APP,感兴趣的朋友可以下载一下! 软件详情 黑阈app是一款非常实用的系统优化类手机APP。使用它能够禁止软件后台运行耗电,既…

【仿写tomcat】四、解析http请求信息,响应给前端,HttpServletRequest、HttpServletResponse的简单实现

思考 在解析请求之前我们要思考一个问题,我们解析的是其中的哪些内容? 对于最基本的实现,当然是请求类型,请求的url以及请求参数,我们可以根据请求的类型作出对应的处理,通过url在我们的mapstore中找到se…

【视频笔记】解密RWKV线性注意力的进化过程

from: https://www.bilibili.com/video/BV1zW4y1D7Qg/?spm_id_from333.999.0.0&vd_source21cce77bb69d40a81e0d37999f2da0c2 文章目录 向量版 Self-attentionAFT 的线性AttentionRWKV的线性Attention 向量版 Self-attention 手动实现,可以看出 时间…

C++ 网络编程项目fastDFS分布式文件系统(三)-Nginx部分

目录 1. 一些基本概念 1.1 Nginx初步认识 1.2 正向/反向代理 1.3 域名和IP 2. Nginx 安装和配置 2.1 安装 2.2 配置 3. Nginx的使用 3.1 部署静态网页 3.2 反向代理和负载均衡 4 课外知识导读 1. URL和URI ​编辑 2. DNS解析过程 1. 一些基本概念 1.1 Nginx初步认…

go es实例

go es实例 1、下载第三方库 go get github.com/olivere/elastic下载过程中出现如下报错: 解决方案: 2、示例 import package mainimport ("context""encoding/json""fmt""reflect""time""…

Kotlin 基础教程二

constructor 构造器一般情况下可以简化为主构造器 即: class A constructor(参数) : 父类 (参数) 也可以在构造器上直接声明属性constructor ( var name) 这样可以全局访问 init { } 将和成员变量一起初始化 data class 可以简化一些bean类 比如get / set ,自动生成copy 函数…

QT实现天气预报

1. MainWindow类设计的成员变量和方法 public: MainWindow(QWidget* parent nullptr); ~MainWindow(); protected: 形成文本菜单来用来右键关闭窗口 void contextMenuEvent(QContextMenuEvent* event); 鼠标被点击之后此事件被调用 void mousePressEvent(QMouseEv…

win10系统docker创建ubuntu容器解决开发环境问题

一、win10系统使用docker的原因 最近啊,在学习人工智能-深度学习,用的win10系统进行开发,老是出现一些莫名其妙的问题,无法解决,每天都在为环境问题搞得伤透了脑筋。 说到底还是要使用Linux系统进行开发比较合适。 …

NodeJs导出PDF

(优于别人,并不高贵,真正的高贵应该是优于过去的自己。——海明威) 场景 根据订单参数生成账单PDF 结果 示例代码 /* eslint-disable no-unused-vars */ /* eslint-disable no-undef */ /* eslint-disable complexity */ const…

【bug】Unity无法创建项目

bug UnityHub无法创建项目 UnityHub无法创建项目 出现的问题:在创建新项目时弹出来一个 无法创建项目 尝试的方法: 刷新许可证 ❌没用退出账号重新登陆 ❌没用重启电脑 ❌没用 最后发现是什么问题呢? 2021.3.3这个版本我之前在资源管理器中…
最新文章