使用 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.mzph.cn/news/48189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HCIP】04.VRRP与BFD

VRRP VRRP基本概念 VRRP路由器 运行VRRP协议的路由器,VRRP是配置在路由器的接口上的,而且也是基于接口来工作的。 VRID 一个VRRP组由多台协同工作的路由器(的接口)组成,使用相同的VRID(Virtual Router…

VR数字工厂多元化展现,打造数字企业工厂名片

5G时代,各种营销都在走数字化的路子,VR数字工厂用VR赋能工厂数字升级,将企业环境、工厂生产、产品研发、质检运输等流程,无死角720度的展示在客户面前,不仅可以提升自身企业的实力,还可以提高客户的信任感。…

如何在Java实现TCP方式发送和接收Socket消息(多线程模式)

目录 导言:正文:1. 创建Server端:2. 创建Client端:3. 多线程模式: 代码示例Server端代码示例:Client端代码示例:同步模式发送TCP消息异步模式 结论: 导言: 在Java编程中…

SpringBoot 的 RedisTemplate、Redisson

一、Jedis、Lettuce、Redisson的简介 优先使用Lettuce, 需要分布式锁,分布式集合等分布式的高级特性,添加Redisson结合使用。 对于高并发,1000/s的并发,数据库可能由行锁变成表锁,性能下降会厉害。 1.1、…

再JAVA中如何使用qsort对类进行排序?

目录 结论&#xff1a; 解析&#xff1a; 结论&#xff1a; import java.util.Arrays;class Person implements Comparable<Person>{public String name;public int age;public Person(String name, int age) {this.name name;this.age age;}Overridepublic Stri…

[保研/考研机试] KY11 二叉树遍历 清华大学复试上机题 C++实现

题目链接&#xff1a; 二叉树遍历_牛客题霸_牛客网编一个程序&#xff0c;读入用户输入的一串先序遍历字符串&#xff0c;根据此字符串建立一个二叉树&#xff08;以指针方式存储&#xff09;。题目来自【牛客题霸】https://www.nowcoder.com/share/jump/43719512169254700747…

机器学习笔记之优化算法(十五)Baillon Haddad Theorem简单认识

机器学习笔记之优化算法——Baillon Haddad Theorem简单认识 引言 Baillon Haddad Theorem \text{Baillon Haddad Theorem} Baillon Haddad Theorem简单认识证明过程证明&#xff1a;条件 1 ⇒ 1 \Rightarrow 1⇒ 条件 2 2 2证明&#xff1a;条件 3 ⇒ 3 \Rightarrow 3⇒条件 1…

【MaxKey对接一】对接gitlab的oauth登录

MaxKey的Oauth过程 引导进入 GET http://{{maxKey_host}}/sign/authz/oauth/v20/authorize?client_idYOUR_CLIENT_ID&response_typecode&redirect_uriYOUR_REGISTERED_REDIRECT_URI 登录后回调地址 YOUR_REGISTERED_REDIRECT_URI/?code{{code}} 换取Access Token GET…

「UG/NX」Block UI 曲线收集器CurveCollector

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

docker 01(初识docker)

一、docker概念 Docker是一个开源的应用容器引擎&#xff1b;诞生于2013年初&#xff0c;基于Go 语言实现&#xff0c;dotCloud公司出品(后改名为Dockerlnc);Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux …

网络安全设备篇——加密机

加密机是一种专门用于数据加密和解密的网络安全设备。它通过使用密码学算法对数据进行加密&#xff0c;从而保护数据的机密性和完整性。加密机通常被用于保护敏感数据&#xff0c;如金融信息、个人身份信息等。 加密机的主要功能包括&#xff1a; 数据加密&#xff1a;加密机使…

探究Java spring中jdk代理和cglib代理!

面对新鲜事物&#xff0c;我们要先了解在去探索事物的本质-默 目录 一.介绍二者代理模式 1.1.Jdk代理模式 1.2cglib代理模式 1.3二者区别 1.3.1有无接口 1.3.2灵活性 1.4对于两种代理模式的总结 1.4.1jdk代理模式 1.4.2cglib代理模式 二.两种代理模式应用场景 2.1jd…

搜狗拼音占用了VSCode及微信小程序开发者工具快捷键Ctrl + Shit + K 搜狗拼音截图快捷键

修改搜狗拼音的快捷键 右键--更多设置--属性设置--按键--系统功能快捷键--系统功能快捷键设置--取消Ctrl Shit K的勾选--勾选截屏并设置为Ctrl Shit A 微信开发者工具设置快捷键 右键--Command Palette--删除行 微信开发者工具快捷键 删除行&#xff1a;Ctrl Shit K 或…

【开源项目】Stream-Query的入门使用和原理分析

前言 无意间发现了一个有趣的项目&#xff0c;Stream-Query。了解了一下其基本的功能&#xff0c;可以帮助开发者省去Mapper的编写。在开发中&#xff0c;我们会编写entity和mapper来完成业务代码&#xff0c;但是Stream-Query可以省去mapper&#xff0c;只写entity。 快速入…

分布式事务理论基础

今天啊&#xff0c;本片博客我们一起来学习一下微服务中的一个重点和难点知识&#xff1a;分布式事务。 我们会基于Seata 这个框架来学习。 1、分布式事务问题 事务&#xff0c;我们应该比较了解&#xff0c;我们知道所有的事务&#xff0c;都必须要满足ACID的原则。也就是 …

Hadoop集群搭建(hadoop-3.3.5)

一、修改服务器配置文件 1、配置环境变量 vim /etc/profile #java环境变量 export JAVA_HOME/usr/local/jdk/jdk8 export JRE_HOME$JAVA_HOME/jre export CLASSPATH$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH export PATH$JAVA_HOME/bin:$JRE_HOME/bin:$PATH #hadoop环境变量 …

前端开发怎么解决前端安全性的问题? - 易智编译EaseEditing

前端安全性是保护前端应用程序免受恶意攻击和数据泄露的重要方面。以下是一些解决前端安全性问题的关键方法&#xff1a; 输入验证与过滤&#xff1a; 对所有用户输入进行验证和过滤&#xff0c;防止恶意用户通过注入攻击等手段破坏应用程序或获取敏感信息。 跨站点脚本&#…

[.NET/WPF] CommunityToolkit.Mvvm 异步指令

我们在开发中, 经常会有这样的需求: 点击按钮后, 进行一些耗时的工作工作进行时, 按钮不可再次被点击工作进行时, 会显示进度条, 或者 “加载中” 的动画 RelayCommand CommunityToolkit.Mvvm 中的 RelayCommand 除了支持最简单的同步方法, 还支持以 Task 作为返回值的异步方…

【数据结构入门指南】二叉树

【数据结构入门指南】二叉树 一、二叉树的概念二、现实中的二叉树三、特殊的二叉树四、二叉树的性质五、二叉树的存储结构5.1 顺序结构5.2 链式结构 一、二叉树的概念 二叉树是一棵特殊的树。一棵二叉树是结点的一个有限集合&#xff0c;该节点&#xff1a; ①&#xff1a;或者…

Spring Boot实现IP地址解析

一、本地解析 如果使用本地ip解析的话&#xff0c;我们将会借助ip2region&#xff0c;该项目维护了一份较为详细的本地ip地址对应表&#xff0c;如果为了离线环境的使用&#xff0c;需要导入该项目依赖&#xff0c;并指定版本&#xff0c;不同版本的方法可能存在差异。 <d…