基于CUDA的深度卷积神经网络图像分类

第6章 基于CUDA平台的深度卷积神经网络图像分类

6.1 引言

图像分类是一个可能受多种因素影响的复杂过程。由于分类结果是许多环境和社会经济应用的基础,科学家和从业者在开发先进的分类方法和技术以提高分类准确率方面付出了巨大努力。图像分类广泛应用于医学、教育和安全等基础领域。正确的分类尤其在医学领域具有至关重要的意义。因此,该领域需要改进的方法。所提出的深度卷积神经网络是深度学习中常用的架构,已广泛应用于计算机视觉和语音识别。在文献中,考虑了用于卷积神经网络的不同因素取值。根据在CIFAR数据集上的实验结果,我们认为网络深度是提高准确率的首要因素。它不仅能够提高准确率,而且与增加网络宽度相比,还能以更低的复杂度达到相同的高准确率。

为了将一组数据分类到不同的类别中,必须充分理解数据与其被分类的类别之间的关系。通常,分类由计算机完成,因此为了实现计算机分类,必须对计算机进行训练。有时结果无法达到足够的准确率,因此训练是分类成功的关键。为了提高分类准确率,本文受ImageNet挑战的启发,提出采用深度神经网络模型,通过并行计算实现多幅图像的分类,以更高准确率、降低成本并在更短时间内完成分类。

图像分类问题需要确定图像所属的类别。当类别数量增加、图像中包含多个不同类别的物体,以及关注语义类别层次结构时,该问题变得相当复杂,因为一幅图像可能属于多个类别。同时属于多个类别。模糊类别给概率类别分配带来了另一个难题。此外,结合不同的分类方法已被证明有助于提高分类准确率[1]。

深度卷积神经网络由于具有通过提取隐藏特征进行处理、支持并行处理和实时操作等优势,相较于现有文献中的方法能够提供更好的结果。在神经网络中,卷积的概念始于由具有局部感受野的神经元组成的层,即这些神经元仅连接到输入数据的有限区域,而非全部[4]。

在本次实验中,使用Python中的开源编程库 TensorFlow来构建我们的深度卷积神经网络( DCNN),以执行图像分类过程。我们采用了包含6万张图片的CIFAR‐10数据集[30]。在实验中,从 CIFAR‐10数据集中选取了猫和狗的图像,经过调整大小和直方图均衡化处理后,分别提取了6000条和 3000条数据用于训练和测试。

实验策略采用Python在Ubuntu系统上执行。我们的目标是在图像处理领域取得最佳结果。在实现操作并行性时,我们遇到了一些与中央处理器相关的限制,因为中央处理器仅适用于串行操作。但在并行编程方面,GPU借助CUDA[11]则更为突出。过去, GPU一直作为图形加速器工作。然而,并行编程已发展成为一种强大、通用且完全可编程的并行数据处理方法,适用于需要并行计算的操作。

CUDA 是英伟达的[26]并行计算架构,通过利用 GPU(图形处理器)的强大性能,显著提升计算性能。

我们在配备 2 GB 内存的 NVIDIA GeForce GTX 680 上,使用 Ubuntu 16.04 操作系统执行所提出的方法。在开发的模型中,训练过程中已利用 GPU 技术。

6.2 图像分类

图像处理是数字化场景并执行某些操作的改进示例,或是从中提取有用信息的方法。图像分类是图像处理的一个非常广泛的领域。分类是确保未分类图像被归入特定类别的过程[1]。图像分类是一个计算机视觉问题,涉及医疗保健、农业、气象学和安全等领域的大量基本信息。人脑可以轻松地对图像进行分类。但对于计算机而言,如果图像包含噪声,则并不容易。已开发出不同的方法来执行分类操作。通用分类过程可根据所使用的方法分为两大类:有监督分类和无监督分类[2]。

在有监督分类中,研究人员定义图像中信息类别的同质化表示。这些示例被称为训练区域。选择合适的训练区域是基于分析人员对分类的知识。因此,分析人员倾向于控制某些类别的分类[3]。无监督分类则逆转了有监督分类过程。使用聚类算法的程序被用来确定数据中的统计分组或结构。通常,分析人员需指定数据中可搜索的组或集群数量。除了指定所需的类别数外,分析人员还可以确定集群之间的分离距离以及每个集群内部变化的参数。无监督分类不以预定义的类别集开始。监督学习在学习良好的视觉表示方面取得了巨大成功,这些表示不仅在其训练任务上表现优异,还能迁移到其他任务和数据集上[3]。科学家们已开发出许多方法来解决图像分类问题。这些方法竞相在图像分类上达到完美。

ImageNet [4]是一项图像分类竞赛。每年需要处理的数据量和需要分类的类别数量都在增加。2012年组织的这项竞赛已成为图像分类领域的一个里程碑。

A. Krizevsky 等人 [5]通过他们开发的卷积网络方法,成功取得了近年来的最佳结果。在随后的几年中,绝大多数参赛者都使用了卷积神经网络。所有参赛作品都是基于卷积神经网络开发的。这项比赛证明了卷积神经网络在图像分类中的成功,使其名声大噪。卷积神经网络已成为特征学习和图像分类领域的强大模型。一直致力于取得更好成果的研究人员已经开发出许多基于卷积神经网络的方法。

Michael 等人[6]指出,在深度卷积神经网络结构中如何编码数据和不变性属性仍然是一个合理的问题。在该研究中,提出了一种改变标准卷积核并随后在覆盖后传递更多数据层的CNN方法,但建议在系统中保持一定的稳健性。其基本思想是利用卷积图中的正负峰值。这是通过在输出前调整传统的激活函数步骤来实现的。在两个经典数据集(MNIST 和 CIFAR‐10)上的大量实验表明,所提出的方法优于标准卷积神经网络。H. Dou 等人[7]提出了一种具有深度递减多分支结构的多尺度卷积神经网络,以解决图像中的尺度变化问题。

图像处理如今已被广泛应用于拥有数码相机和计算机的各类个人。只需少量投入,人们便可轻松增强对比度、检测边缘、量化强度,并对图像应用各种数学运算。尽管这些技术可能非常强大,但普通用户常常在不了解最基本图像处理程序原理的情况下随意进行数字图像处理 [8]。虽然某些个人可能对此可以接受,但这往往会导致图像质量显著下降,无法达到掌握基本图像处理操作后所能实现的效果。

计算机视觉中的主要问题之一是图像分类问题,该问题关注确定输入图像中是否存在视觉结构。众所周知,图像分类是一个复杂的过程,可能受到许多因素的影响。由于分类结果是许多环境和社会经济应用的基础,科学家和从业者在开发先进的分类方法和技术以提高分类准确率[9]方面做出了巨大努力。

物体之间的分类对人类来说是一项简单的任务,但对机器而言却一直是一个复杂的问题。随着高容量计算机的出现,高质量低价位视频摄像机的普及以及对自动视频分析日益增长的需求,激发了人们对目标分类算法的兴趣。一个简单的分类系统由固定在感兴趣区域上方的摄像头组成,用于捕获图像并进行后续处理。分类过程包括图像传感器、图像预处理、目标检测、目标分割、特征提取和目标分类。分类系统包含一个数据库,其中存储有预定模式,通过将这些模式与检测到的目标进行比较,从而将其分类到合适的类别。图像分类是在生物医学成像、生物识别技术、视频监控、车辆导航、工业视觉检测、机器人导航和遥感等多个应用领域中重要且具有挑战性的任务。

6.2.1 图像分类方法

I. 数字数据。 图像通过使用数码相机或任何手机摄像头捕获。
II. 预处理。 图像数据增强,包括获取归一化图像、增强对比度、获取灰度图像、二值图像、图像缩放、二值图像取反、去噪、获取图像边界。
III. 特征提取。 从图像样本中测量、计算或检测特征的过程。两种最常见的特征提取类型是(i)几何特征提取和(ii)颜色特征提取。
IV. 准备信息选择。 选择最能描述给定示例的特定属性,例如,信息图像、输出图像、预处理后的训练数据集名称。

示意图0

V. 决策与分类。 利用合理策略将识别出的项目分类到预定义类别中,该策略对比图像模式与目标示例。
VI. 精度评估。 精度评估被用来识别可能的错误来源,并作为比较中使用的指标。

图像分类的类别。 图像排序最常用的方法包括有监督和无监督的分类、参数化和非参数化的分类、面向对象的分类、亚像素分类、逐像素和逐场或光谱分类器、上下文和光谱‐上下文分类器,以及硬分类和软分类 [13]:

  • 有监督分类 – 使用已知信息类别的样本(训练集)对身份未知的像素进行分类的过程。
  • 无监督分类 – 这是一种方法,通过检查大量未知像素,并根据图像值中存在的自然聚类将其划分为若干类别。计算机确定光谱上可区分的类别,然后定义其信息值。
分类技术 优点 假设和/或局限性
神经网络 •可用于分类或能够回归表示布尔函数(与,或,非)
•对噪声输入具有容错性
•实例可以通过多个输出进行分类
•难以理解算法的结构
•特征过多可能导致过拟合
•最优网络结构只能是通过实验确定
支持向量机 •模型非线性类别边界
•过拟合不太可能发生
•计算复杂度降低至{v3}
•一个二次优化问题
•易于控制复杂度决策规则和错误频率
•训练比贝叶斯慢和决策树
•难以确定最佳方案训练数据不足时的参数线性可分
•难以理解其结构一种算法
模糊逻辑 •不同的随机关系可以被识别以描述属性
•先验知识对于获得良好结果非常重要
•如果决策方向不明确,则无法得到明确的解决方案
遗传算法 •可用于特征分类和特征选择
•主要用于优化
•总是能找到一个“良好”的解决方案(并非并不总是最佳解决方案)
•能够处理大规模、复杂的不可微且多峰空间
•针对复杂问题空间
•擅长精炼无关和含噪用于分类的特征
•计算或开发评分函数是非平凡的
•不是寻找某些局部最优解而非全局最优解的最有效方法
•涉及训练/输出数据表示的复杂性
参数化分类器 •参数化分类器的性能——参数化分类器的性能在很大程度上取决于数据与预定义模型的匹配程度以及模型参数估计的准确性。使用的参数包括均值向量和协方差矩阵;例如,最大似然分类器 •非参数分类器——不对数据做任何假设。非参数分类器不使用统计参数来计算类别划分;例如,人工神经网络、支持向量机、决策树分类器
硬分类 •每个像素必须归属于单一类别
软分类 •每个像素可能表现出多个且部分的类别归属

6.2.2 图像分类技术

图像类别 fi 分类是一个复杂的流程,依赖于不同的组件。本文讨论了图像分类中提出的一些策略、问题以及额外的前景。重点将放在用于提高特征描述精度的前沿分类方法上。此外,还讨论了与分组执行相关的一些关键问题。[2]。参见表6.1和 6.2。

示意图1

图 6.2 显示了基于文献调查结果,考虑模糊测度、决策树、支持向量机以及人工神经网络方法在图像分类上的准确率,与近期研究的性能比较。可以看出,模糊测度的准确率较低,人工神经网络的准确率较高,但仍未达到ImageNet挑战。为了提高分类准确率并达到具有竞争力的ImageNet挑战准确率,本研究提出了一种基于深度神经网络模型的并行计算方法,以实现对多幅图像进行更准确的分类、降低分类成本,并在更短时间内完成不同类别(类别)的分类。(http://www.jatit.org/volumes/research-papers/Vol4No11/5Vol4No11.pdf)

6.2.3 研究空白

在调研了不同分类技术的相关文献后,我们可以观察到:
1. 当前算法的准确率在很大程度上依赖于充足的标注数据。
2. 基于图的学习方法表现出较高的准确率,但计算复杂度较高。
3. 算法的准确率取决于样本选择(选择最具信息量的未标记样本)以及对光谱数据的考虑。

6.2.4 研究挑战

  1. 在设计半监督分类算法时,考虑计算复杂度以获得高分类准确率是一项具有挑战性的任务。
  2. 通过利用光谱信息以及空间信息来设计一种有效且鲁棒的算法。
  3. 在设计算法时,需要谨慎选择样本选择方法(使用主动学习)。

6.2.5 问题定义

我们力求通过并行化处理,将多张图像更准确地分类到正确的类别中,同时降低成本并缩短时间。

6.2.6 目标

  1. 系统的训练随后进行测试。训练过程意味着提取图像(来自某一类别)的特征属性,并为特定类别构建一种独特的表示。
  2. 测试步骤意味着将测试图像分类到系统已训练过的各个类别中。类别的分配是基于训练特征所确定的类别间的划分来完成的。

6.3 深度卷积神经网络

人工神经网络是通过模拟人脑的工作机制而衍生出来的。其分层的网络结构是通过模拟神经细胞的工作方式构建的。这种结构长期以来被用于许多人工智能问题,并取得了显著成果[1]。深度学习的基础包括人工神经网络。人工神经网络的提出旨在为研究人员提供更优的大脑模型。在20世纪80年代,由于深度限制,无法进行密集的矩阵操作,因此深度学习难以转化为实际训练。在20世纪80年代后期,辛顿和勒村的反向传播算法[2]引起了加拿大先进研究所的关注,尽管当时在科学界并未引起广泛共鸣,但该研究所附属大学的研究团队或许是这一领域深度学习的权威研究群体[3]。深度学习已被应用于许多机器学习问题并取得了成功的结果。近年来深度学习的发展使得大规模图像的高效处理成为可能。许多著名的架构相继被提出,例如玻尔兹曼机、受限玻尔兹曼机、自编码器和卷积神经网络。其中卷积神经网络在图像分类方面表现尤为出色。随着技术的进步,几乎每个领域都不可避免地受益于这项技术。图像分类在许多关键领域具有重要价值,例如医学、安全和教育。深度学习是机器学习的一个子领域,致力于通过利用分层架构来学习数据中的高层抽象。它是一种不断发展的方法论,已广泛应用于传统的人工智能领域,如语义分析[1],、迁移学习[2,3],、自然语言处理[4],、计算机视觉[5,6],等。当今深度学习蓬勃发展的主要原因有三个:芯片处理能力的显著提升(例如GPU单元)、计算硬件成本的大幅降低,以及机器学习算法的重大进展[9]。近年来,各种深度学习方法已被广泛综述和讨论[8–12]。其中,Schmidhuber等人以时间线的形式强调了重要的灵感来源和技术贡献,而本吉奥则探讨了深度学习研究面临的挑战,并提出了若干前瞻性研究方向。深度网络在计算机视觉任务中表现出色,因为它们能够在执行判别任务的同时提取合适的特征[9,13]。在近年来的ImageNet大规模视觉识别挑战赛(ILSVRC)中[11],,深度学习方法被不同研究人员广泛采用,并取得了顶尖的准确率得分[7]。深度学习使得由多个处理层组成的计算模型能够学习具有多层次抽象的数据表示。这些方法在语音识别、视觉目标识别、目标检测以及药物发现和基因组学等多个领域显著提升了技术水平。深度学习通过使用反向传播算法来揭示机器应如何调整其内部参数,从而从上一层的表示中计算出每一层的表示,以此来发现大型数据集中的复杂结构。深度卷积网络在图像、视频、语音和音频处理方面带来了突破,而循环网络则对文本和语音等序列数据提供了新的见解。深度学习从起源发展到成为人工智能的主流技术,得益于三个近期趋势:训练数据量的爆炸式增长、图形处理单元(GPU)等加速器的使用,以及训练模型设计的进步。这三个趋势使得利用大量数据训练深层神经网络的任务变得可行且有效。

借助任何一种深度学习框架(例如Caffe[11],、 TensorFlow[12],、MXNet[7]),用户都可以开发和训练自己的模型。神经网络模型的范围涵盖大小从小型(5 MB)到非常大(500 MB)。训练神经网络可能需要大量时间,其目标是为神经网络中的不同变量找到合适的权重。一旦模型训练完成,就可以将其用于推理,即将训练好的模型应用于新数据,应用于自然语言处理、语音识别或图像分类等领域。

6.4 统一计算设备架构 (CUDA)

图形处理器(GPU)已成为当今主流计算系统的重要组成部分。在过去六年中,GPU的性能和功能显著提升。现代GPU不仅是一个强大的图形引擎,还是一个高度并行的可编程处理器,其峰值算术和内存带宽远超中央处理器(CPU)。GPU在可编程性和能力方面的快速进步催生了一个研究群体,该群体已成功将一系列计算密集且复杂的问题映射到GPU上[15]。这种在GPU上进行通用计算的努力,也被称为GPU计算,使GPU成为未来高性能计算机系统中传统微处理器的一种极具吸引力的替代方案。由于图形处理单元(GPU)处理能力的快速增长,使用GPU作为协处理器来协助中央处理器(CPU)进行大规模数据计算变得至关重要。计算科学家长期以来一直对图形处理单元(GPU)感兴趣,因为它们每单位浮点(FP)性能的成本相对较低。与传统的多处理器不同,GPU的处理器核心专门针对图形着色器常见的程序行为进行了优化——成千上万个独立线程,每个线程仅包含几十或几百条指令,执行较少的内存访问并生成少量输出值。近年来硬件和可编程性的进步使 GPU向更广泛的开发者社区开放。GPU面向吞吐量优化的架构特性可以在数值计算工作负载上超越中央处理器(CPU)的性能,具体取决于工作负载与GPU设计所针对的计算行为的匹配程度。对于许多开发者来说,一个重要的问题是他们是否能够将特定应用映射到这些新型GPU上,从而相较于当代多核处理器实现显著的性能提升。一个CUDA程序至少包含一个在主机(CPU)或设备,例如GPU。没有数据并行性的阶段在主机代码中执行,而具有丰富数据并行性比例的阶段则在设备代码中执行[4]。CUDA程序是将主机代码和设备代码融合在一起的源代码。NVIDIA C编译器(nvcc)在编译过程中将这两部分分开。主机代码是标准的ANSI C代码,可使用主机的标准C编译器进行编译,并作为典型的中央处理器进程运行。设备代码则是基于ANSI C扩展而来,加入了用于命名数据并行函数(称为核函数)及其相关数据结构的关键字。设备代码也由nvcc进行编译,并在GPU设备上执行。在没有可用设备或某个函数更适合在中央处理器上执行的情况下,也可以使用CUDA软件开发包(SDK)中的仿真功能或MCUDA机械汇编[Stratton 2008]在中央处理器上运行这些部分。在矩阵乘法示例中,整个矩阵乘法计算可以实现为一个核函数,其中每个线程用于计算输出矩阵的一个元素 P。核函数(或简称为核函数)通常会生成大量线程以利用数据并行性。在此示例中,核函数所使用的线程数量是矩阵维度的函数。对于 1000 × 1000的矩阵乘法,若核函数使用一个线程来计算一个 P元素,则调用时将生成 1,000,000个线程。值得注意的是,CUDA线程比中央处理器线程轻量得多[5]。由于高效的硬件支持, CUDA程序员可以认为这些线程的生成和调度仅需很少的时钟循环。这与通常需要数千个时钟周期才能生成和调度的中央处理器线程形成对比。CUDA是对C语言的一种扩展,允许使用普通的C语言编写GPU代码。该代码要么面向主机处理器(中央处理器)运行,要么面向设备处理器(GPU)运行。主机处理器将多线程任务(或称作CUDA中的线程块)分发到GPU设备上。

GPU拥有自身的特殊内部调度器,随后会将这些线程块分配给可用的GPU硬件资源。我们将在后文提供相关细节。如果任务中存在足够的并行性,那么随着GPU中流式多处理器(SMs)数量的增加,程序的运行速度也应相应提升[8]。然而,这引出了一个值得注意的问题:必须考虑代码能够以多快的速度并行执行。可能达到的最佳加速比受限于串行代码所占的比例。如果系统拥有无限的调度能力,并且能够在零时间内完成并行任务,那么我们将达到理想状态下的最大加速效果。

将由连续代码部分来处理。因此,我们必须从一开始就考虑是否能够避免使用if、and或but,并大幅并行化异常权重的处理。

英伟达致力于为CUDA提供支持。其网站 http://www.nvidia.com中的CUDA专区提供了丰富的信息、模型和工具,以帮助开发者进行开发。与前代技术相比,CUDA真正开始蓬勃发展,毫无疑问,未来将有一种编程语言脱颖而出,成为GPU编程的首选。鉴于目前支持CUDA的GPU数量已达数百万,一个庞大的市场正等待着CUDA应用的开发。[21]计算模式正从中央处理器上的“集中式规划”向中央处理器与GPU的“协同处理”转变。为了实现这一新的编程理念,英伟达推出了CUDA并行计算架构,该架构现已应用于 GeForce、ION Quadro和Tesla GPU中,为应用程序开发提供了巨大的现有基础。[28]参见图 6.3。

除了设备DRAM之外,CUDA还支持多种其他类型的内存,可用于提高核函数的CGMA比值。访问DRAM速度慢且成本高。为了解决这一问题,CUDA GPU上配备了多种片内和片外的低容量、高带宽内存。如果某些数据被频繁使用,CUDA会将其缓存在底层内存中,从而处理器无需每次都访问DRAM。下图展示了CUDA支持并在英伟达显卡上常见的内存架构。以下是CUDA中使用的不同类型的内存[24]:

A. 局部内存。每个SP使用局部内存。在核函数(在 GPU上执行的函数)中声明的所有变量都保存在局部内存中。
B. 寄存器。一个核函数可能包含多个表达式。在执行表达式期间,值被保存到SP的寄存器中。
C. 全局内存。它是GPU的主要内存。每当使用 cudaMalloc()函数为变量分配GPU内存时,默认使用全局内存。
D. 共享内存。共享内存由线程块中的每个线程共享。共享内存用于减少延迟(内存访问延迟)。当共享

示意图2

内存被用于变量时,在其声明期间应以关键字_shared_作为前缀,例如:_shared_整型x。
E. 常量内存。 常量内存也被用来降低延迟。但常量内存仅用于多个线程需要访问同一值的情况。通过这种方式,常量内存减少了延迟。
F. 纹理内存。 纹理内存再次被用于降低延迟。纹理内存在一种特殊情况下使用。考虑一幅图像,当它访问某个特定像素时,有很大可能也会访问其周围像素。这类通常一起被访问的数值组会被保存在纹理内存中。

6.5 TENSORFLOW

TensorFlow 是一种在大规模和异构环境中运行的机器学习系统。TensorFlow 使用数据流图来表示计算、共享状态以及改变该状态的操作。它将数据流图的节点映射到集群中的多台机器上,并在单台机器内映射到多种计算设备,包括多核CPU、通用GPU以及称为张量处理单元(TPU)的定制设计的ASIC。这种架构为应用开发者提供了灵活性:与以往“参数服务器”设计中共享状态的管理被内置到系统中不同,TensorFlow 使开发者能够尝试新颖的优化和训练算法[25]。

TensorFlow 支持多种应用,重点是深度神经网络上的训练和推理。一些谷歌服务在生产中使用 TensorFlow,因此它被作为开源项目发布,并已在机器学习研究中得到广泛使用。TensorFlow 使用单一的数据流图来表示机器学习算法中的所有计算和状态,包括各个数学运算、参数及其更新规则,以及输入预处理 [26]。数据流图明确表达了子计算之间的通信,从而便于并行执行独立计算并将计算任务划分到多个设备上。

TensorFlow[28]是一种用于表达机器学习计算的接口,用于执行此类计算。使用TensorFlow表达的计算几乎无需修改即可在各种异构系统上执行,范围从手机(如电话和平板电脑)到由多台机器和数千个计算设备(例如GPU卡 [14])组成的大型分布式系统。该框架具有灵活性,可用于表达多种计算,包括深度神经网络模型的训练和导数计算,并已被用于在超过12个计算机科学及其他领域开展研究并将机器学习系统投入生产,涵盖语音识别、计算机视觉、应用自主性、数据检索、自然语言处理、地理信息提取以及计算药物发现等领域。本章描述了 TensorFlow接口及其在谷歌开发的该接口的一个实现 [29]。

6.6 实施

6.6.1 深度卷积神经网络

深度学习。 深度学习是机器学习研究的一个新领域,其提出旨在使机器学习更接近其独特目标之一。深度学习是一种人工智能函数,它模仿人脑的功能,用于处理数据并创建模式以进行决策。图像的深度学习仅仅是使用从图像中提取的更多特征,而不仅仅是其签名。然而,这是在隐藏层中自动完成的,而不是作为输入(如神经网络中的情况)[7],如图 6.4所示。第一层的神经元将输入数据传递给网络。

示意图3

同样,最后层被称为输出层。位于输入层和输出层之间的层被称为

示意图4

隐藏层。在此示例中,该网络仅有一个以蓝色显示的隐藏层[13]。具有许多隐藏层的网络往往更精确,被称为深度网络;因此,使用这些深度网络的机器学习算法被称为深度学习。

典型的卷积网络[9]由一系列卷积和池化对组成,后接若干全连接层。卷积类似于一个小的神经网络,对其输入的每个位置重复应用一次。因此,网络层在尺寸上变得更小,但在深度上增加。池化是通常用于减小输入图像尺寸的操作。最大池化是最常见的池化算法,在许多计算机视觉任务中已被证明是有效的。

假设我们试图教一台计算机识别图像,并将其分类到这10个类别之一[22];见图6.5。

为此,我们首先需要让计算机学习猫、狗、鸟等动物的外观特征,然后计算机才具备识别新图像的能力。计算机看到的猫科动物图像越多,它在识别猫科动物方面就表现得越好 [30]。这被称为监督学习。通过标记图像,计算机将开始察觉猫类图像中与其他图像不同的模式,并逐步建立起自身的感知能力。我们将使用 Python 和 TensorFlow [28] 编写程序。

TensorFlow 是由谷歌开发的开源深度学习系统,它为开发者提供对每个神经元(在 TensorFlow 中称为“节点”)的精细控制,从而可以调整权重并实现理想的执行效果

TensorFlow 拥有大量的开发库(其中一些将用于图像排序),并且拥有强大的网络,因此几乎只需要查找任何深度学习领域的开源应用即可。

6.6.2 数据集

在这项工作中,我们选择使用CIFAR‐10数据集,该数据集包含60,000张图像,大小为 32 × 32像素。该数据集包含10个类别,这些类别本质上互不相关(无重叠),每个类别包含6000张图像[22]。这些图像是小型的、明显标记的,且没有噪声,这使得该数据集非常适合本任务,并显著减少了训练前的准备工作。从该数据集中选取的一些图像如图6.6所示。

I. CIFAR‐100数据集。 该数据集与CIFAR‐ 10[30],大致相同,唯一的区别是它包含100个类别,每个类别包含600张图像。每个类别中有500张训练图像和100张测试图像。CIFAR‐100中的100个类别被归入20个超类。每张图像都有一个“细粒度”名称(即所属的类别)和一个“粗粒度”标签(即所属的超类)。以下我们将描述CIFAR‐100数据集的类别和超类结构。每个超类包含五个类别。当类别名称为复数形式时,标签名称要求调查人员不要忽略出现多次该问题的图像。参见表 6.3。

6.6.3 实现图像分类器

由于项目规范未提出一个具体的待解决问题,因此首先需要找到并确定一个问题。该问题不应过于复杂,但也不能过于简单。需要实现某种图像分类器,但具体针对何种图像,以及图像分类的细化程度,例如是对不同物体进行分类,还是更具体地对同一类物体的不同类型进行分类,这些都属于实现阶段需要考虑的内容[15]。此外,还需要足够数量且质量足够的数据,以便对图像分类器进行训练和测试;而“足够”在数值上和实际中的具体含义,也可能需在实现章节中进一步明确。因此,本项目部分的首要任务是查找并评估不同的数据集来源,然后确定一个复杂度适中的问题,确保能够获取充足的数据用于图像分类器的训练和测试。之后,当然还需要下载这些数据[16]。

第二个任务是开始实现图像分类器。该图像分类器将使用微软CNTK和谷歌TensorFlow实现,其中以 TensorFlow作为后端,并使用Keras这一第三方API作为

示意图5

超类 类别
水生哺乳动物 河狸, 海豚, 水獭, 海豹, 鲸鱼
fish 观赏鱼, 比目鱼, 鲨鱼, 鳐鱼, 鳟鱼
花卉 兰花, 罂粟花, 玫瑰, 向日葵,郁金香
食品容器 瓶子,碗,罐头,杯子,盘子
水果和蔬菜 苹果,蘑菇,橙子、梨、甜椒
家用电器设备 时钟、电脑键盘,台灯、电话、电视
家用家具 bed,椅子,沙发,桌子,衣柜
昆虫 蜜蜂, 甲虫, 蝴蝶, 毛毛虫, 蟑螂
大型食肉动物 熊, 豹, 狮子, 老虎,wolf
大型人造室外事物 桥, 城堡, 房屋, 道路, 摩天大楼
大型自然室外场景 云, 森林, 山, 平原, 海
大型杂食动物和草食动物 骆驼, 牛, 黑猩猩, 大象, 袋鼠
中型哺乳动物 狐狸, 豪猪, 负鼠, 浣熊,臭鼬
非昆虫无脊椎动物 螃蟹,龙虾,蜗牛,蜘蛛,worm
婴儿,男孩,女孩,男人,女人
爬行动物 鳄鱼,恐龙,蜥蜴,蛇,海龟
小型哺乳动物 仓鼠 ,小鼠,兔子,鼩鼱, 松鼠
树木 枫树, 橡树, 棕榈树, 松树, 柳树
车辆 1 自行车, 公交车, 摩托车,皮卡, 火车
车辆 2 割草机, 火箭,有轨电车, 坦克, 拖拉机

深度学习的前端。Keras目前可用作TensorFlow的前端[29]今天,将Keras加入TensorFlow核心的进程正在进行中,截至1月 2019[25],并且未来可能能够使用 CNTK作为后端未来的某个时间点也同样 [24]。在不同框架中,图像分类器的各种模型将在相同的编程语言和开发环境中实现和开发,以使模型更具可比性。用于实现的编程语言是 Python 3[32],所使用的开发环境是已安装 Visual Studio 的Python工具插件的 Microsoft Visual Studio 2015企业版 [31],此外还将使用相同的编程语言和集成开发环境[27]。

6.6.4 安装和系统要求

为了收集评估系统要求、软件和硬件支持以及编程语言支持所需的信息,研究了TensorFlow、Keras和 CNTK的文档。为了评估安装的便捷性和速度,下载并安装了这些框架。这是评估中较为主观的部分。得出结论所依据的方面包括:能够使用框架所需的步骤数量,以及执行上述步骤的难易程度。以下是作者用于安装各个框架的具体步骤。首先,需要设置开发环境。由于开发将使用Python进行,因此从Python官网 https://www.python.org/下载并安装了Python 3.5.3。

所使用的集成开发环境为Microsoft Visual Studio 2015企业版 [34],,该软件在此研究所用计算机上已预先安装。为了能够在Visual Studio中使用Python,需要安装Visual Studio的Python工具(PTVS)扩展 [33]。要安装PTVS,需通过Windows控制面板修改 Visual Studio的安装,并添加PTVS扩展。谷歌 TensorFlow [29]通过Visual Studio中的PTVS,使用内置工具pip进行下载和安装。为了能够使用GPU,安装了TensorFlow的GPU版本0.12.1,pip自动处理并安装了所有Python相关依赖 [21]。当使用 TensorFlow的GPU版本时,还需要额外下载两项内容: NVIDIA CUDA Toolkit 8.0 和 NVIDIA cuDNN v 5.1(CUDA深度神经网络)库,它们分别从 https://developer.nvidia.com/cuda-downloads 和 https://developer.nvidia.com/cudnn 下载。cuDNN的 dll文件被放置在安装后创建的CUDA文件夹中; Keras通过Visual Studio中的PTVS,使用内置工具 pip进行下载和安装。安装的版本为1.2.2。pip自动处理并安装了所有Python相关依赖,但通过pip安装的 scipy和numpy版本不正确,
需要手动下载和安装。Keras所需的正确版本的scipy和numpy从 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载。通过Windows命令提示符使用pip安装了正确版本的scipy和numpy的whl文件 [26]。现在我们详细讨论CUDA编程模型与深度CNN到 GPU之间的映射机制。

A. 映射实现

训练方法以及深度CNN层与CUDA内核之间的映射关联如图6.7所示。分别设计了两个CUDA内核函数用于各层的前向传播和反向传播。在每次循环开始时,前向卷积内核根据CPU提供的记录索引从全局内存中加载一个样本;通过这种方式连续输入训练数据。由于需要借助CPU,在前向传播后需将网络输出复制回来以计算当前损失函数的值,而在反向传播后需要调整学习率。通过比较当前损失值与预定义的最小损失值,由CPU在每次循环结束时决定是否跳出该循环。

卷积层。 这里没有直接使用Caffe提供的二维卷积例程,而是将数据卷积操作分解为细粒度任务,然后将其映射到GPU上的线程。

池化层。 在此层中,根据预定义的组大小,将卷积结果数组中的元素划分为不同的组。主要目标是找到每组的最大值或计算每组的平均值,这取决于所选择的采样方法。

全连接层。 全连接层中单个神经元的前向传播和反向传播如图6.7所示。在前向传播过程中,需要计算输入向量 x与权重向量 ω的点积,并通过 a= f(z)计算神经元的最终输出 a。在反向传播过程中,梯度 δ1z通过 δ1a X da/dz计算,其中δ1a是 →−ω 与 −−−−→ δa1+ 1的点积。

输出层。 输出层到CUDA内核的映射机制与全连接层类似,通常情况下,在应用时会将同一神经元上的映射操作分配给一个线程。将softmax函数作为激活函数,考虑到在此条件下线程间的通信变得更加频繁。

示意图6

6.6.5 算法

梯度下降是用于训练深度学习模型的主要方法。所提出的方案应包含以下两种用于训练目的的算法:
1. 随机梯度下降
2. 小批量梯度下降

所有分类器均使用随机梯度下降法进行训练,并采用以下三种损失函数之一:感知机、合页或逻辑回归。针对每个标签,训练一个二元分类器,并将图像分类为得分最高的标签。梯度下降的参数包括训练迭代次数和学习步长。最后,在GCN框架中,通过CUDA多流技术对小批量梯度下降(MBGD)算法进行改进,相较于最先进的TensorFlow框架,在CIFAR‐10数据集上的网络训练速度进一步提升[17]。

6.7 结果分析

6.7.1 TensorFlow中的神经网络

包含神经网络的图(见图6.8)应包含以下步骤:
1. 输入数据集——训练数据集及其标签、测试数据集及其标签(以及验证数据集及其标签)。
2. 测试数据集和验证数据集可以放置在 tf.constant() 中,而训练数据集则放置在 tf.placeholder() 中,以便在训练期间以批次形式输入(随机梯度下降)。
3. 包含所有层的神经网络模型。这可以是一个简单的全连接神经网络仅包含1层的神经网络,或更复杂的包含5、9、16等层数的神经网络。
4. 具有适当大小的权重矩阵和偏置向量,并将其初始化为初始值。(每层对应一个权重矩阵和一个偏置向量。)
5. 损失值——模型输出为 logit向量(估计的训练标签),通过将logit向量与真实标签进行比较,可以计算损失值(使用带交叉熵的 softmax函数)。损失值用于指示估计的训练标签与真实训练标签的接近程度,并将用于更新权重值。
6. 优化器,其将使用计算出的损失值通过反向传播来更新权重和偏置。

示意图7

6.7.2 理解原始图像数据集

原始的一批数据是一个 10000 × 3072矩阵,以 numpy数组表示。列数10000表示样本数据的数量。根据CIFAR‐10/CIFAR‐100数据集的说明,行向量(大小为3072)表示一张 32 × 32像素的彩色图像。由于本项目将使用卷积神经网络进行分类任务,原始的行向量并不合适。为了将图像数据输入到卷积神经网络模型中,输入张量的维度应为(宽度 ×高度 ×通道数)或(通道数 _宽度 _高度)。这取决于选择。我们选择第一种形式,因为这是TensorFlow中卷积神经网络操作的默认选择 ×。如何重塑为这种形式?如果计算 ×,会发现一个图像的行向量元素数量完全相同。为了将行向量重塑为(宽度 [20]高度 32 · 32· 3= 3072通道数)的形式,需要两个步骤。第一步是使用reshape函数,第二步是使用numpy中的transpose函数。根据定义

示意图8

根据 numpy 官方网站,reshape 会在不更改其数据的情况下将数组转换为新形状。这里的“不更改其数据”这一表述非常重要,因为我们不希望损坏数据[21]。重塑操作应分为三个更详细的步骤。以下描述其背后的逻辑:
1. 将行向量分为3部分,每部分表示一个颜色通道。得到的数组是一个 3 ×1024矩阵,总共构成10,000× 3× 1024个张量。
2. 将每3个部分进一步除以32,即图像的宽度和高度。结果为 3 ×32× 32,总共形成10,000× 3× 32× 32个张量。为了在numpy中实现这一逻辑概念,应使用以下参数调用reshape函数:(10,000, 3, 32, 32)。我们已经注意到,当提供第三个值(32,宽度)时, reshape函数不会自动进一步分割。我们需要明确指定最后一个值(32,高度)。参见图6.9。

这还不是故事的结尾。现在,一个图像数据以( num_channel, 宽度, 高度)的形式表示。然而,这种形状并不是TensorFlow和Matplotlib所期望的。它们期望的是另一种形状,即(宽度, 高度, num_channel)。因此,需要交换轴的顺序,这时就需要用到转置。转置函数可以接受一个轴的列表,每个值指定我们想要移动的维度索引。例如,在形状为(num_channel, 宽度, 高度)的numpy数组上使用参数(1, 2, 0)调用转置,将返回一个新的形状为(宽度, 高度, num_channel)的numpy数组。参见图6.10。

6.7.3 理解原始标签

标签数据只是从0到9的10,000个数字的列表,对应于 CIFAR‐10中的10个类别。
飞机 : 0 汽车 : 1 鸟 : 2 猫 : 3 鹿 : 4 狗 : 5 青蛙 : 6 马 : 7 船 : 8 卡车 : 9

代码1 定义了一个函数,用于返回一个方便的图像类别列表。该函数将在生产阶段使用。由于预测输出是一个数字,应将其转换为字符串,以便人类可以阅读。参见图6.11。

下面定义的display_stats回答了一些问题,例如在给定的一批数据[23]中。“所有可能的标签有哪些?”“图像数据中的值范围是多少?”“标签是有序的还是随机的?”参见图6.12。我们尝试了第三批次及其7000张图像。结果如图 6.13所示,每个类别的图像数据数量大致相同。

示意图9

示意图10

示意图11

6.7.4 实现预处理函数

有人可能会注意到,一些框架/库(如TensorFlow、 numpy或Scikit‐learn)提供了我们即将构建的类似功能。为了在数据集上获得机器学习算法的最佳准确率,某些机器学习算法要求信息以明确的形式呈现,而其他算法则可以在信息为特定目标设置时表现更好,但并非总是如此。最后,原始数据可能并不具备所需的格式,无法充分揭示与预测变量之间的内在结构和关系。因此,重要的是要以一种能够提供多种不同视角的方式准备可用数据,使机器学习算法在该问题上具有最佳的机会。

归一化。 normalize函数接收数据, x并将其返回为归一化的numpy数组。数据 x可以是任何内容,并且可以是 N维数组。在本章中,它将用于图像的三维数组。采用最小‐最大归一化(y=(x −min)/(max−min))技术,但也有其他可选方法。通过应用最小‐最大归一化,原始图像数据将被转换到0到1的范围内(包含端点)。关于为何要进行归一化的一个简单回答与激活函数有关。参见图6.14。

例如,Sigmoid激活函数接收一个输入值,并输出一个介于0到1之间的新值。当输入值较大时,输出值很容易达到最大值1;同样,当输入值较小时,输出值很容易达到最小值0。参见图6.15。

示意图12

示意图13

示意图14

例如,ReLU激活函数接收一个输入值,并输出一个范围在0 到 无穷大 。当 输入值 相对较大时, 输出值 线性地 增加。然而,当 输入值 较小时, 输出值 容易达到 最大值 0。见图6.16。

示意图15

现在,考虑图像数据时,所有原始值的范围都是从 0到255。当这些数据被传入Sigmoid函数时,输出几乎总是1;而当它们被传入ReLU函数时,输出可能非常大。在进行反向传播过程以优化网络时,这可能导致梯度爆炸或梯度消失问题。为了避免这一问题,最好将所有值归一化到0和1附近。

6.7.5 模型的输出

目前,我们需要了解的是模型的输出。它是基于模型预测结果的每个图像类别的概率集合。为了在代码中表示这些概率,需要一个与图像类别数量相同的向量。例如, CIFAR‐10 提供了 10 个不同的图像类别,因此我们也需要一个大小为 10 的向量。参见图 6.17。

此外,我们的模型应能够将预测结果与真实标签进行比较。这意味着标签数据的形状也应转换为大小为 10的向量。相反,由于该标签是真实标签,我们将其对应元素[21]的值设为1。One_hot_encode函数接收输入 put, x,这是一个标签列表(真实值)。列表中元素的总数等于一个批次中的样本总数。一个_热_编码函数返回一个二维张量,其中行数为批次大小,列数为图像类别数。参见图 6.18。

处理所有数据并保存。
下面的代码6使用了先前实现的函数,即归一化和独热编码,对给定的数据集进行预处理。如图6.19所示,每个批次中10%的数据将被合并以形成验证数据集。剩余的90%数据用作训练数据集。最后,还有一个已提供的测试数据集。下面的代码单元将对所有CIFAR‐10数据进行预处理,并将其保存到外部文件[22]。

def _预处理_并_保存(归一化, one_hot_编码, 特征, 标签, 文件名):
    特征 = 归一化(特征)
    标签 = one_hot_编码(标签)
    pickle.dump((特征, 标签), open(文件名, ’wb’))

def preprocess _和_save_data(cifar10_ dataset_folder_path, 归一化, one_hot_encode):
    n_批次 valid_特征 valid_标签 = []
    for 批次_i in range(1, n_批次 + 1):
        特征, 标签 = load_cfar10_ batch( cifar10_数据集_folder_path, 批次_i)

        # 在整个批次的数据集中找到作为验证数据的索引(10%)
        _的验证索引_ = int(len(特征) * 0.1)

        # 预处理整个数据集90%的批次
        # ‐ 归一化特征
        # ‐ 对 _ _标签进行独热编码
        # ‐ 保存为新文件,文件名为“preprocess_batch_”+ batch_编号
        # ‐ 每个批次对应一个文件
        _预处理_并_保存(归一化,独热编码, 特征[:‐验证标签索引_of_验证],标签[:‐_of _验证],'preprocess_batch_' + str(batch_i) +'.p')

        # 与训练数据集不同,验证数据集将通过所有批次数 据集添加
        # ‐ 取整个批次数据集的10%
        # ‐ 将它们添加到以下列表中
        # ‐ valid features
        # ‐ valid labels
        valid_fea‐_ _ _tures.extend(features[‐index_of_validation:])
        valid_la‐ bels.extend(标签[‐index_of_validation:])

        # 预处理所有堆叠的验证数据集
        _pre‐ process _和_保存 (归一化,one_hot_编码,numpy数组(valid_features), numpy数组(valid_labels), 'preprocess_validation.p')

        # 加载测试数据集
        with open(cifar10_dataset_folder_path + '/test_batch', mode='rb') as file:
            batch = pickle.load(file, encoding='latin1')

        # 预处理测试数据
        test_features = batch['data'].reshape((len(batch ['data']),3, 32, 32)). transpose(0, 2, 3, 1)
        test_labels = batch['labels']

        # 预处理并保存所有测试数据
        _preprocess _和_保存 (归一化,one_hot _编码, numpy数组(test_特征), numpy数组(test_标签), 'prepro‐ cess_训练.p')

代码6:整体流程代码

6.7.6 使用多GPU卡/CUDA训练模型

现代工作站可能包含多个GPU用于逻辑计算。TensorFlow可以利用此条件在不同的显卡上同时运行训练任务。以并行、分散模式训练模型需要组织训练形式。尾部术语所展示的是,在信息子集上进行一次模型训练的复制。简单地使用模型参数的非同步更新会导致训练执行出现问题,因为单个模型副本可能基于过时的模型参数进行训练。另一方面,完全使用同步更新将与最慢的展示副本一样缓慢[18]。

在配备多张GPU卡的工作站上,每块GPU的速度相近,并且拥有足够的内存来运行完整的CIFAR‐10实验。因此,我们按以下方式概述我们的准备框架:
1. 在每块GPU上放置一个单独的模型副本。
2. 通过等待所有图形处理器完成一批信息处理,同步更新模型参数。

该模型的示意图如图 6.20 所示。

示意图16

每个GPU计算导数,并且还计算一组独特信息的梯度。这种设置成功实现了分离在GPU上处理更大的数据批次。这种设置要求所有 GPU共享模型参数。一个可验证的事实是,GPU之间的信息交换速度相当适中[19]。因此,选择将每个模型参数存储并刷新在中央处理器上(参见绿色框)。当所有 GPU处理另一组数据时,新的模型参数分类会被交换到 GPU上。GPU在此任务中保持同步。所有梯度从GPU 收集并汇总到中心点(参见绿色框)。模型参数通过所有模型副本的梯度中值进行更新。两种框架下的训练时间变化相对较低,尽管使用Keras作为后端配合 TensorFlow时变化略高,特别是在CIFAR‐10数据集上的最后一次运行尤为突出,比最近的邻近结果多出30秒,请参见表格6.4。有趣的是,第一个周期始终是最耗时的周期,请参见表格中的最大周期时间列。在进行一些测试并将表中结果汇总后,我们得出结论:前几个周期耗时较长是因为我们在Visual Studio中开启了调试模式运行脚本。当我们关闭调试模式运行脚本时,第一个周期所需时间大约与其他周期相同。training_neural_network函数对给定批次执行优化任务。由于CIFAR‐10数据集包含 5个独立的批次,且每个批次包含不同的图像数据,因此应在每个批次上运行training_neural_network。这可以通过简单的代码实现,如代码7所示。它对每个批次运行10个训练周期,参见图6.21,而图6.22展示了训练结果。

Run (no) 总计时间(秒) 平均周期时间(秒) 最大周期时间(秒)
1 3733 93.4 98
2 3746 93.6 97
3 3757 94.1 99
4 3759 94.0 101
5 3701 92.4 97
1–5 18692 93.5 100

损失越低,模型越好(除非模型对准备信息过拟合)

示意图17

损失在训练和验证上进行计算,其含义是模型在这两个数据集上的表现情况。与准确率不同,损失不是一个比率,而是训练集或验证集每个样本中错误的总和。对于神经网络,损失通常在分类任务中为负对数概率,在回归任务中为残差平方和。因此,学习模型的主要目标通常是通过各种优化方法(例如神经网络中的反向传播)调整权重向量的值,来减小(即最小化)关于模型参数的损失函数。交叉验证是一种用于在有限数据样本上评估机器学习模型的方法。该方法有一个称为 k的参数,表示给定数据样本要被划分为的组数。因此,该过程通常被称为 k折交叉验证。最后,当选择某个具体的 k值时,可以用它代替 k来指代模型,例如 k= 10表示10折交叉验证。

在 k折交叉验证方法中,数据集被划分为 k个子集,并且该方法重复k次。每次其中一个 k子集被用作测试集,其余的 k −1个子集合并形成训练集。然后计算所有k次试验的平均误差。该方法的优点是每个数据点都有一次机会恰好被包含在测试集中一次,并且有机会被包含在训练集中集合 k −1次。随着 k增大,估计结果的方差最小化。参见图6.22。模型的精确度通常在模型参数确定且不再进行学习后决定。此时,鼓励对模型进行测试,并记录模型产生的错误分类数量(零一损失),该数量需与真实目标进行比对。然后计算错误分类的程度。参见图6.23。

在获得训练好的模型后,预测测试数据集中的图像是否为猫或狗等类别将变得非常容易(并能给出每个类别的预测概率)。其背后的原理是,即使测试图像本身不太容易进行预测,经过变换处理后,模型更有可能捕捉到狗/猫的形状特征,并相应地做出预测。部分图像由于对比度差、矩形而非方形图像,或因为狗/猫仅占据图像的很小部分而被错误分类。例如,观察一张狗的矩形图像:当模型尝试对该图像进行预测时,它只看到图像的中心区域(默认裁剪为中心区域),因此无法判断该图像是狗还是猫。从上述情况可以看出,我们的机器已成功预测出小狗的图像并将其分类为狗,同样也正确识别了汽车并将其分类为汽车。学习曲线是训练和测试损失随迭代次数变化的函数图像。这些图表对于可视化分析非常有用。

示意图18

训练/验证损失和验证准确率。该模型的学习曲线如图 6.24所示。从图中可以看出,经过3000次迭代后,准确率保持不变。训练完成后,该技术在测试阶段利用数据库中的未标记信息达到了90%的精确度。当信息量增加时,我们有限数据量的分类准确率提升是不可避免的。例如,如果测试数量为1000,模型预测其中952次准确,则该模型的正确率为95.2%。见图 6.25。

示意图19

示意图20

示意图21

6.8 结论

本研究探讨了深度学习是否可应用于CIFAR‐10数据库中的图像分类。深度学习技术被对于企业和个人而言,使用该技术变得更加便捷,并且比卷积神经网络表现出更优的结果。在本次研究中,图像分类过程采用了Python中的开源编程库 TensorFlow与Keras来构建我们的深度卷积神经网络 (DCNN)。在实现操作并行性时,中央处理器存在一些限制,中央处理器仅适用于连续性任务。然而,在并行编程方面,借助CUDA的图形处理器更为有效。过去, 图形处理器一直作为图形加速器使用。实验结果表明,所提出的技术在CIFAR数据集上明显优于其他先进的有监督和半监督方法。通过利用高光谱图像中的大量未标记像素,未来的半监督学习技术将能够充分训练深度神经网络。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值