第九章 ShuffleNetv1网络详解

news2024/11/16 13:24:29

系列文章目录


第一章 AlexNet网络详解

第二章 VGG网络详解

第三章 GoogLeNet网络详解 

第四章 ResNet网络详解 

第五章 ResNeXt网络详解 

第六章 MobileNetv1网络详解 

第七章 MobileNetv2网络详解 

第八章 MobileNetv3网络详解 

第九章 ShuffleNetv1网络详解 

第十章 ShuffleNetv2网络详解 

第十一章 EfficientNetv1网络详解 

第十二章 EfficientNetv2网络详解 

第十三章 Transformer注意力机制

第十四章 Vision Transformer网络详解 

第十五章 Swin-Transformer网络详解 

第十六章 ConvNeXt网络详解 

第十七章 RepVGG网络详解 

第十八章 MobileViT网络详解 


文章目录

  •  ShuffleNetv1网络详解
  • 0. 前言
  • 1. 摘要
  • 2.   ShuffleNetv1网络详解网络架构
    • 1.  ShuffleNetv1_Model.py(pytorch实现)
    • 2.
  • 总结


0、前言


1、摘要

        我们介绍了一种极其计算效率高的CNN架构,名为ShuffleNet,它专为移动设备设计,这些设备的计算能力非常有限(例如,10-150 MFLOPs)。该新架构利用了两种新操作,即逐点分组卷积和通道混洗,以大大降低计算成本,同时保持准确性。在ImageNet分类和MS COCO目标检测上的实验表明,ShuffleNet比其他结构表现更优,例如在40 MFLOPs的计算预算下,相对于最近的MobileNet [12],在ImageNet分类任务中的Top-1错误率更低(绝对值为7.8%)。在基于ARM的移动设备上,ShuffleNet实现了约13倍的加速,同时保持相当精度。

2、ShuffleNetv1网络结构

1.本文介绍了一种名为ShuffleNet的高度计算效率的卷积神经网络架构,特别为具有非常有限计算能力的移动设备设计。

2.该论文的研究背景是移动设备上的图像分类和目标检测,现有的CNN架构无法在这些设备上高效地运行。

3.本文的主要论点是介绍一种新的CNN架构ShuffleNet,它利用了点卷积和通道混洗两种新操作来大大降低计算成本而保持准确性。

4.以往的研究使用基于卷积的CNN架构,它们耗费大量计算资源,难以在移动设备上高效执行。这些方法的问题在于计算资源的限制。

5.本文提出了一种新的CNN架构,利用点卷积和通道混洗两种新操作,旨在提高计算效率。

6.结果表明ShuffleNet比其他结构具有更好性能,在ImageNet分类任务中,计算预算为40 MFLOPs时,比最近的MobileNet具有更低的top-1错误(绝对值为7.8%)。在ARM移动设备上,ShuffleNet比AlexNet实现了约13倍的实际加速,同时保持类似的准确性。本研究的限制是实验仅限于图像分类和目标检测领域。

ShuffleNet是由微软研究院发表于CVPR 2018的一篇论文《ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices》中提出的一种轻量级卷积神经网络。 ShuffleNet采用了像素级别的通道重排(channel shuffling)来降低模型的计算复杂度。

具体地,ShuffleNet将输入通道拆分成两个子集,利用逐通道1×1卷积将两个子集独立地进行特征提取,然后将两个子集按照一定的规则进行通道重排,即将通道混合起来,形成新的通道顺序。

接着,ShuffleNet使用逐元素1×1卷积对混合后的通道进行信息融合,得到网络的输出。 在此基础上,ShuffleNet将通道重排和逐元素卷积的过程进行了多次迭代,形成了一个深度可分离的ShuffleNet结构,使得ShuffleNet在保持较高准确率的同时大幅度降低了计算、参数量等方面的成本。

此外,ShuffleNet还利用了组卷积(group convolution)技术来进一步减小计算量。 总而言之,ShuffleNet是一种高效、轻量、可扩展的卷积神经网络,它的结构设计很好地平衡了模型的精度和计算成本之间的权衡,因此在对移动设备等计算能力有限的场景非常适用。

正文介绍

ShuffleNet是一种针对计算资源有限的移动端设备的轻量级神经网络。ShuffleNet的核心思想是通过通道重组来减少计算量和模型大小。它在保证准确率的同时大大降低了模型复杂度和计算量,使得在资源有限的移动设备上实现高效的图像分类和识别成为可能。

ShuffleNet的设计主要包括以下几个方面:

1.分组卷积

ShuffleNet采用了分组卷积的方式将卷积层分解成多个子层,每个子层只处理部分通道的输入特征图,这样做可以大大减少卷积计算量,同时还能保证特征提取的多样性和表达能力。

2.通道重组

ShuffleNet采用通道重组的方式将通道数较少的输入特征图重组成通道数较多的输出特征图。这样做不仅可以减少计算量,还可以增强特征的多样性和表达能力。通道重组时,ShuffleNet采用了逐通道的方式,即将输入特征图的通道按一定规则划分成多个组,然后将每个组的特征图按顺序交错排列,生成输出特征图。

3.深度可分离卷积

ShuffleNet在卷积层中采用了深度可分离卷积,即将标准卷积分解成深度卷积和逐点卷积两个子层,这样可以大大减少计算量和参数量。深度卷积只处理空间维度的卷积,逐点卷积只处理通道维度的卷积。这种分解方式不仅可以加速计算,还可以增强模型的非线性表达能力。

总的来说,ShuffleNet在移动端设备上取得了很好的效果,较少的计算量和模型大小让它成为轻量级神经网络的代表之一。同时,ShuffleNet的设计思路也为其他更加复杂的神经网络提供了有益的思路和借鉴。

构建深度更深、规模更大的卷积神经网络(CNNs)是解决主要视觉识别任务的主要趋势[21,9,33,5,28,24]。最精准的CNNs通常有数百层和数千个通道[9,34,32,40],因此需要亿万次的FLOPs来进行计算。本报告研究相反的极端:在十几或上百个MFLOPs的非常有限的计算预算内追求最佳精度,重点放在常见的移动平台上,如无人机,机器人和智能手机。请注意,许多现有作品[16、22、43、42、38、27]专注于对“基本”网络架构进行剪枝,压缩或低位表示。在这里,我们旨在探索一种专门针对我们所需计算范围设计的高效基本架构。我们注意到,最先进的基本架构,如Xception [3]和ResNeXt [40]在极小的网络中变得不够高效,因为密集的1×1卷积代价昂贵。我们建议使用点组卷积来减少1×1卷积的计算复杂度。为了克服组卷积带来的副作用,我们提出了一种新颖的通道重排操作,以帮助信息在特征通道之间流动。基于这两种技术,我们构建了一个高效的架构,称为ShuffleNet。与像[30、9、40]等流行结构相比,在给定计算复杂度预算的情况下,我们的ShuffleNet允许更多的特征图通道,这有助于编码更多信息,并对非常小的网络性能特别关键。我们在具有挑战性的ImageNet分类[4、29]和MS COCO目标检测[23]任务上评估我们的模型。一系列受控实验显示了我们的设计原则的有效性以及与其他结构的更好性能。与最先进的MobileNet [12]架构相比,ShuffleNet取得了显着的优势,例如,以40 MFLOPs的水平为例,ImageNet top-1错误绝对减少了7.8%。我们还研究了在实际硬件上的加速。

Efficient Model Designs是近年来深度神经网络在计算机视觉任务中取得成功的原因之一,其中模型设计起着重要作用。追求在嵌入式设备上运行高质量深度神经网络的需求促使人们研究高效模型设计。例如,GoogLeNet通过比简单堆叠卷积层更低的复杂度增加网络深度。SqueezeNet在保持准确率的同时显著减少了参数和计算量。ResNet利用高效的瓶颈结构实现了令人印象深刻的性能。SENet引入了一个提高性能的架构单元,代价非常小。与我们同时进行的一项非常新的研究采用强化学习和模型搜索来探索高效的模型设计。提出的Mobile NASNet模型在ImageNet分类错误方面与我们的ShuffleNet模型具有可比性(564 MFLOPs的26.0%和524 MFLOPs的26.3%)。但是,[46]没有报告极小型号(复杂度小于150 MFLOPs)的结果,也没有在移动设备上评估实际推理时间。 在AlexNet中首次引入的组卷积的概念,用于将模型分布到两个GPU上,已经在ResNeXt中展示了其有效性。Xception提出的深度可分离卷积在Inception系列中推广了可分离卷积的思路。最近,MobileNet利用深度可分离卷积取得了轻量级模型的最新成果。我们的工作在新颖的形式上将组卷积和深度可分离卷积进行了推广。 据我们所知,通道洗牌操作的想法在先前的高效模型设计研究中很少提及,尽管CNN库cuda-convnet [20]支持“随机稀疏卷积”层,该层相当于随机通道洗牌。

1.针对群卷积的通道洗牌 现代卷积神经网络[30,33,34,32,9,10]通常由具有相同结构的重复建筑块组成。其中,如 Xception [3]和 ResNeXt [40]等最先进的网络在建筑块中引入高效的深度可分离卷积或组卷积,以在表示能力和计算成本之间实现出色的权衡。但是,我们注意到这两种设计都没有充分考虑到 1×1 卷积(也称为 [12]中的点卷积),这需要相当大的复杂性。例如,在 ResNeXt [40]中,只有 3×3 层配备组卷积。因此,在 ResNeXt 中的每个残差单元中,点卷积占据了 93.4%的乘加操作(按 [40]建议的基数=32计算)。在小型网络中,昂贵的点卷积会导致通道数量不足以满足复杂性约束,这可能会严重损害准确性。为了解决这个问题,一个简单直接的解决方案是将通道稀疏连接,例如在 1×1 层上也应用组卷积。通过确保每个卷积只在相应的输入通道组上运行,组卷积显着减少了计算成本。然而,如果多个组卷积堆叠在一起,会产生一个副作用:来自某个通道的输出只来源于一小部分输入通道。图1(a)说明了两个堆叠的组卷积层的情况。显然,某个组的输出仅与组内的输入有关。这种属性阻止了通道组之间的信息流和弱化了表示。如果我们允许组卷积从不同的组获取输入数据(如图1(b)所示),输入和输出通道将完全相关。具体而言,对于从上一组层生成的特征图,我们可以先将每个组中的通道分为几个子组,然后将每个子组作为输入通道组馈入组卷积。

3.2. 利用通道混洗操作,我们提出了一种专为小型网络设计的新型ShuffleNet单元。我们从bottleneck单元[9]在图2(a)中的设计原理开始。它是一个残差块。在其残差分支中,对于3×3层,在瓶颈特征映射上应用一种计算经济的3×3深度卷积[3]。然后,我们用点卷积群卷积替换第一个1×1层,后跟一个通道混洗操作,形成ShuffleNet单元,如图2(b)所示。第二个点卷积群卷积的目的是恢复通道维度以匹配快捷路径。为简单起见,在第二个点卷积层之后我们没有使用额外的通道混洗操作,因为这会导致得分可比较。批量规范化(BN)[15]和非线性的使用方式与[9,40]类似,只是我们没有像[3]建议的那样在深度卷积后使用ReLU。至于ShuffleNet应用步长的情况,我们只需进行两个修改(见图2(c)):(i)在快捷路径上添加一个3×3的平均池化;(ii)将元素级加法替换为通道拼接,这使得很容易以很少的额外计算成本放大通道维度。由于点卷积群卷积与通道混洗相结合,ShuffleNet单元中的所有组件都可以有效计算。与ResNet[9](瓶颈设计)和ResNeXt[40]相比,在相同的设置下,我们的结构具有更少的复杂性。例如,给定输入尺寸c×h×w和瓶颈通道m,ResNet单元需要hw(2cm +9m2)FLOPs,ResNeXt需要hw(2cm +9m2 = g)FLOPs,而我们的ShuffleNet单元仅需要hw(2cm / g +9m)FLOPs,其中g表示卷积组的数量。换句话说,给定计算预算,ShuffleNet可以使用更宽的特征映射。我们发现,这对于小型网络是至关重要的,因为小型网络通常具有不足以处理信息的通道数量。此外,在ShuffleNet中,深度卷积只在瓶颈特征图上执行。虽然深度卷积通常具有非常低的理论复杂度,但我们发现难以在低功耗移动设备上高效实现,这可能是由于与其他密集操作相比,计算/内存访问比率较差。这种缺点也在[3]中提到,该论文基于TensorFlow [1]的运行时库。在ShuffleNet单元中,我们有意只在瓶颈上使用深度卷积,以尽可能避免开销。

(图1.使用两个堆叠的分组卷积进行通道混洗。GConv代表分组卷积。 a)使用相同数量的分组进行两个堆叠卷积层。每个输出通道仅涉及组内的输入通道。没有交叉影响; b)当GConv2从GConv1之后的不同组获取数据时,输入和输出通道完全相关; c)使用通道混洗的等效实现与b)相同。)

(本文的“图2. ShuffleNet单元”描述了三种不同的ShuffleNet单元构建方式。其中(a)采用了带有深度卷积(DWConv)的瓶颈单元[9][3,12],(b)则采用了点卷积分组卷积(GConv)和通道混洗,而(c)则是带有步长为2的ShuffleNet单元) 

建立在ShuffleNet单元上,我们在表1中呈现了整体ShuffleNet体系结构。所提出的网络主要由三个阶段的一组ShuffleNet单元堆叠而成。每个阶段的第一个构建块应用步长=2。同一阶段内的其他超参数保持不变,并且在下一阶段中,输出通道加倍。与[9]类似,我们将瓶颈通道的数量设置为每个ShuffleNet单元输出通道的1/4。我们的意图是提供尽可能简单的参考设计,尽管我们发现进一步的超参数调整可能会产生更好的结果。在ShuffleNet单元中,组号g控制逐点卷积的连接稀疏度。表1探讨了不同的组号,并且我们适应输出通道以确保总体计算成本大致不变(~ 140 MFLOPs)。显然,对于给定的复杂性约束,更大的组号会导致更多的输出通道(因此更多的卷积滤波器),这有助于编码更多信息,尽管由于有限的相应输入通道,它也可能导致单个卷积滤波器的退化。在第4.1.1节中,我们将研究该数字在不同计算约束情况下的影响。为了将网络定制为所需的复杂度,我们可以简单地在通道数量上应用比例因子s。例如,我们将表1中的网络称为“ShuffleNet 1×”,则“ShuffleNet s×”表示将ShuffleNet 1×中的滤波器数按s倍缩放,因此总体复杂度将大约是ShuffleNet 1×的s2倍。

表格1ShuffleNet 架构。复杂度通过FLOPs(即浮点乘加数量)进行评估。请注意,在第二阶段中,我们没有在第一个点卷积层上应用分组卷积,因为输入通道数相对较少。

Table 1.ShuffleNet architecture.The complexity is evaluated with FLOPs,i.e.the number of floating-point multiplication-adds.Note that for Stage 2,we do not apply group convolution on the first pointwise layer because the number of input channels is relatively small

Layer

Output

size

KSize

Stride

Repeat

Output Channels(g groups)

g=1

g=2

g=3

g=4

g=8

Image

224×224

3

3

3

3

3

Conv1

112×112

3×3

2

1

24

24

24

24

24

MaxPool

56×56

3×3

2

Stage2

28×28

2

1

144

200

240

272

384

28×28

1

3

144

200

240

272

384

Stage3

14×14

2

1

288

400

480

544

768

14×14

1

7

288

400

480

544

768

Stage4

7×7

2

1

576

800

960

1088

1536

7×7

1

3

576

800

960

1088

1536

GlobalPool

1×1

7×7

FC

1000

1000

1000

1000

1000

Complexity

143M

140M

137M

133M

137M

      Stage2:该阶段是网络中的第一个shuffle阶段,旨在对输入特征图进行分组卷积,并使用通道重排来减少计算量和参数数量。该阶段包含4个基本单元,每个基本单元都由一些分组卷积层和通道重排层组成。其中,第一个基本单元没有使用组卷积操作,是因为输入通道数相对较小,不需要进行组卷积操作。

      Stage3:该阶段是网络中的第二个shuffle阶段,进一步减少计算量和参数数量,同时增加网络的深度。该阶段包含8个基本单元,每个基本单元都由一些分组卷积层和通道重排层组成。该阶段的主要任务是通过堆叠基本单元来增加网络的深度,并通过通道重排层进行通道重排,以便进行下一阶段的处理。

      Stage4:该阶段是网络中的第三个shuffle阶段,它主要包含一个全局平均池化层和一个全连接层,用于将特征图输出为预测结果。全局平均池化层将特征图的每个通道的特征值求平均,得到一个特征向量,然后将该特征向量输入到全连接层中进行分类预测。

      Complexity:该指标是使用FLOPs评估网络的复杂度,即浮点乘加的数量。它是衡量模型计算量和时间复杂度的重要指标,可以帮助我们评估网络的效率和可行性,以便进行模型的优化和改进。 总之,Stage2Stage3Stage4都是ShuffleNet架构中的核心组件,对于网络的性能和效率都有着重要的影响。而Complexity则是评估网络复杂度的重要指标,可以帮助我们进行模型的优化和改进。

Layer:表示网络中的每一层,包括输入图像、卷积层、池化层、ShuffleNet中的3shuffle阶段、全局平均池化层和全连接层。

Output size:表示每一层的输出特征图尺寸,以像素为单位,例如224×224表示输入图像的尺寸是224像素宽、224像素高。

KSize:表示卷积核的大小,以像素为单位,例如3×3表示卷积核的大小是3像素宽、3像素高。

Stride:表示卷积或池化操作中的步长,以像素为单位,例如2表示每隔2个像素进行一次卷积或池化操作。

Repeat:表示每个基本单元中卷积或通道重排等操作的重复次数,例如Stage2中的2表示每个基本单元中包含2次卷积和通道重排操作

Output channels:表示每一层的输出通道数,也就是特征图中的通道数,通道数越多表示特征图包含的信息越丰富。

g groups:表示分组卷积中的分组数量,g=1表示普通卷积,g>1表示分组卷积。该表格中展示了不同分组数量下的输出通道数,以说明分组卷积对网络性能的影响。

Complexity:表示网络的复杂度,使用FLOPs(浮点乘加操作的数量)进行评估,该值越小表示网络的计算量和时间复杂度越低。

从表格中可以提取到的有效信息包括:

网络输入的图像尺寸为224×224,卷积核大小为3×3

网络中包含一个卷积层和一个池化层,之后是3shuffle阶段、一个全局平均池化层和一个全连接层。

随着网络的深度增加,输出通道数也逐渐增多,以提取更多的特征信息。

分组数量的不同对输出通道数和网络复杂度都有影响,但是具体的影响大小需要根据网络结构和具体任务进行评估。

网络的复杂度使用FLOPs进行评估,可以帮助我们评估网络的计算量和时间复杂度,以便进行模型的优化和改进。

2:分类误差与组数g的关系(较小的数字代表更好的性能)。

Table 2.Classification error vs.number of groups g (smaller number represents better performance)

Model

Complexity

Classification erros(%)

(MFLOPs)

g=1

g=2

g=3

g=4

g=8

ShuffleNet 1×

140

33.6

32.7

32.6

32.8

32.4

ShuffleNet 0.5×

38

45.1

44.4

43.2

41.6

42.3

ShuffleNet 0.25×

13

57.1

56.8

55.0

54.2

52.7

这个表格展示了在不同分组数量下,三个不同复杂度的ShuffleNet网络的分类错误率和模型复杂度(用MFLOPs表示)。表格中使用较小的分组数量可以获得更好的性能,因为它可以提高网络的非线性能力,增加模型的表达能力,但是会增加计算量和时间复杂度。其中,ShuffleNet 1×表示原始网络,ShuffleNet 0.5×ShuffleNet 0.25×表示模型复杂度分别为原始模型的50%25%。表格中可以提取出以下信息:

随着分组数量的增加,ShuffleNet的分类错误率略有增加,但是不同分组数量之间的性能差异很小,这表明ShuffleNet对分组数量的选择具有一定的鲁棒性。

通过减小模型复杂度(使用ShuffleNet 0.5×ShuffleNet 0.25×),可以获得更低的分类错误率,但是计算量和时间复杂度也会相应减小。

在相同的复杂度下,ShuffleNet 1×可以获得最佳的性能,但是ShuffleNet 0.5×ShuffleNet 0.25×仍然具有较高的性能,这表明ShuffleNet在模型压缩和加速方面具有较好的应用前景。

分组数量对ShuffleNet的性能和复杂度都有一定的影响,但是具体的影响大小需要根据具体任务和数据集进行评估。在实际应用中,可以通过交叉验证等方法来确定最佳的分组数量和模型复杂度。

表格3.使用/不使用通道混洗的ShuffleNet(较小数字表示更好的性能)

Table 3.ShuffleNet with/without channel shuffle (smaller number represents better performance)

Model

Cls err.(%, no shuffle)

Cls err(%,shuffle)

△err.(%)

ShuffleNet 1×(g=3)

34.5

32.6

1.9

ShuffleNet 1×(g=8)

37.6

32.4

5.2

ShuffleNet 0.5×(g=3)

45.7

43.2

2.5

ShuffleNet 0.5×(g=8)

48.1

42.3

5.8

ShuffleNet 0.25×(g=3)

56.3

55.0

1.3

ShuffleNet 0.25×(g=8)

56.5

52.7

3.8

这个表格展示了使用和不使用通道混洗(Channel Shuffle)技术的ShuffleNet网络在不同分组数量下的分类错误率,并计算了使用通道混洗技术相对于不使用的性能提升(∆err.)。其中,ShuffleNet 1×ShuffleNet 0.5×ShuffleNet 0.25×分别表示不同的模型复杂度,g表示分组数量。

具体参数解释如下:

Model Cls err.(%,no shuffle):不使用通道混洗技术时的分类错误率。

Model Cls err.(%,shuffle):使用通道混洗技术时的分类错误率。

∆err.(%):使用通道混洗技术相对于不使用时的性能提升,计算方式为∆err.(%)=(Cls err.(%,no shuffle)-Cls err.(%,shuffle))/Cls err.(%,no shuffle)×100%

表格中可以提取出以下信息:

使用通道混洗技术可以显著提高ShuffleNet的分类性能,在大多数情况下,性能提升在2%~6%之间。

随着分组数量的增加,使用通道混洗技术的性能提升效果更加明显,这表明通道混洗技术对于增强ShuffleNet的非线性能力和表达能力特别有效。

在相同的分组数量下,ShuffleNet 0.5×ShuffleNet 0.25×相对于ShuffleNet 1×使用通道混洗技术的性能提升更加明显,这表明通道混洗技术在模型压缩和加速方面具有较好的应用前景。

总的来说,表格展示了通道混洗技术对于ShuffleNet的性能提升效果,以及分组数量和模型复杂度等因素对性能提升效果的影响。在实际应用中,可以根据任务和数据集的特点,结合通道混洗技术和分组数量等技术手段,来优化ShuffleNet的性能和效率。

我们主要在ImageNet 2012分类数据集[29,4]上评估我们的模型。我们使用[40]中大部分训练设置和超参数,但有两个例外:(i)我们将权重衰减设置为4e-5而不是1e-4,并使用线性衰减学习率策略(从0.5降至0);(ii)我们在数据预处理中使用稍微不太激进的尺度增强。因为这种小网络通常遭受欠拟合而不是过拟合,所以[12]中也引用了类似的修改。使用4个GPU进行3×105次迭代的模型训练需要1-2天,批量大小为1024。为了进行基准测试,我们比较单个裁剪的top-1准确率,即从256×输入图像中剪裁出224×224中心视图并进行分类精度评估。我们对所有模型使用完全相同的设置,以确保公平比较。

ShuffleNet的核心思想在于点卷积组和通道混洗操作。在这个子章节中,我们分别评估它们。

为了评估逐点群卷积的重要性,我们比较相同复杂度的ShuffleNet模型,其群的数量从1到8不等。当群数等于1时,没有逐点群卷积参与,这时ShuffleNet单元变成了“Xception-like”结构[3]。为了更好的理解,我们还将网络的宽度分别缩放到3种不同的复杂度,并分别比较它们的分类性能。结果如表2所示。从结果来看,带有群卷积(g>1)的模型始终比没有逐点群卷积(g=1)的对应模型表现更好。较小的模型往往更受益于群。例如,对于ShuffleNet 1×,最佳输入(g=8)比对应模型好1.2%,而对于ShuffleNet 0.5×和0.25×,差距分别为3.5%和4.4%。请注意,群卷积允许更多的特征图通道,以满足给定的复杂度约束,因此我们假设性能增益来自于更宽的特征图,有助于编码更多的信息。此外,较小的网络涉及到较窄的特征图,意味着它更受益于扩大的特征图。表2还显示,对于某些模型(例如ShuffleNet 0.5×),当群数变得相对较大(例如g=8)时,分类得分会饱和甚至下降。随着群数的增加(因此特征图更宽),每个卷积滤波器的输入通道变少,这可能会损害表示能力。有趣的是,我们还注意到,对于较小的模型,如ShuffleNet 0.25×,较大的群数倾向于更有组织地产生更好的结果,这表明更宽的特征图对较小的模型带来更多好处。

4.1.2 通道混洗与无混洗 混洗操作的目的是为了多组卷积层实现跨组信息流。表3比较了ShuffleNet结构(组数设置为3或8)有/无通道混洗的性能。评估在三种不同的复杂度下进行。显然,通道混洗始终可以提高不同设置下的分类得分。特别是,当组数相对较大时(如g=8),具有通道混洗的模型明显优于无混洗模型,这表明跨组信息交换的重要性。

4.2. 与其他结构单元的比较

近期,VGG [30]、ResNet [9]、GoogleNet [33]、ResNeXt [40]和Xception [3]等领先的卷积单元采用大模型(例如≥1GFLOPS)追求最先进的结果,但没有完全探索低复杂度条件。本节我们对各种构建块进行调查,并在相同复杂度限制下与ShuffleNet进行比较。为了公平比较,我们使用表1中显示的整体网络架构。我们将第2-4阶段的ShuffleNet单元替换为其他结构,然后调整通道数以确保复杂度保持不变。我们探索的结构包括:

1.VGG-like

遵循VGG net [30]的设计原则,我们使用两层3×3卷积作为基本构建块。不同于[30],我们在每个卷积后添加一个Batch Normalization层[15],以使端到端的训练更容易。

2.ResNet。

我们在实验中采用了“瓶颈”设计,这在[9]中已被证明更有效。与[9]相同,瓶颈比1也是4。

3.Xception-like。

[3]中提出的原始结构涉及不同阶段的花哨设计或超参数,这在小型模型上很难进行公平比较。相反,我们从ShuffleNet中删除点间组卷积和通道洗牌操作(也等同于g = 1的ShuffleNet)。所得到的结构与[3]中的“深可分离卷积”的思想相同,这里称为Xception-like结构。

4.ResNeXt。

我们使用[40]建议的基数= 16和瓶颈比= 1:2的设置。我们还探索了其他设置,例如瓶颈比= 1:4,并获得了类似的结果。我们使用完全相同的设置来训练这些模型。结果如表4所示。

我们的ShuffleNet模型在不同的复杂度下明显优于大多数其他模型。有趣的是,我们发现特征图通道数量与分类准确性之间存在一种经验关系。例如,在复杂的情况下,我们的ShuffleNet V2-1.0模型具有73.3%的准确率,而ShuffleNet V2-1.5具有77.7%的准确率。这表明,更多的特征图通道可以提高分类准确性。

4.各种结构的分类错误率(%,较小的数字代表更好的性能)。我们没有在较小的网络上报告类似于VGG的结构,因为准确度显着更差。

Table 4.Classification error vs.various structures (%,smaller number represents better performance).We do not report VGG-like structure on smaller networks because the accuracy is significantly worse Table 3.ShuffleNet with/without channel shuffle (smaller number represents better performance)

Complexity(MFLOPs)

VGG-like

ResNet

Xception-like

ResNeXt

ShuffleNet(ours)

140

50.7

37.3

33.6

33.3

32.4(1×,g=8)

38

-

48.8

45.1

46.0

41.6(0.5×,g=4)

13

-

63.7

57.1

65.2

52.7(0.25×,g=8)

该表格展示了在相同的模型复杂度下,使用不同结构的网络在分类任务上的性能,其中使用MFLOPs表示模型的复杂度。具体参数解释如下:

ComplexityMFLOPs):用MFLOPs表示的模型复杂度,MFLOPs越高,模型越复杂。

VGG-like:采用类似于VGG的结构的网络。

ResNet:采用残差网络(ResNet)结构的网络。

Xception-like:采用类似于Xception的结构的网络。

ResNeXt:采用ResNeXt结构的网络。

ShuffleNet (ours):采用作者提出的ShuffleNet结构的网络,其中0.5×0.25×分别表示不同的模型复杂度,g表示分组数量。

Classification error:分类错误率,越小越好。

从表格中可以提取以下信息:

在相同的模型复杂度下,ShuffleNet的性能优于其他结构的网络,这表明ShuffleNet在模型压缩和加速方面具有较好的应用前景。

在不同的模型复杂度下,ShuffleNet的性能都比其他结构的网络更好,这表明ShuffleNet在保证模型复杂度较低的同时,具有较好的分类性能。

VGG-like结构的网络在较小的网络中表现较差,因此作者没有报告VGG-like结构在较小网络中的性能。这可能是因为VGG-like结构的网络具有较多的卷积层和参数,导致在较小的网络中容易出现梯度消失等问题。

随着模型复杂度的增加,各种网络的分类性能都有所提高,但是提高的幅度不同。在相同的模型复杂度下,ShuffleNet的分类性能最好,且提高幅度最大。

总的来说,该表格展示了不同结构的网络在相同模型复杂度下的分类性能,并突出了ShuffleNet在模型压缩和加速方面的优势。

5ShuffleNetMobileNet [12]ImageNet分类上的比较。

Table 5.ShuffleNet vs.MobileNet [12]on ImageNet Classification

Model

Complexity(MFLOPs)

CLs err.(%)

△err.(%)

1.0 MobileNet-244

569

29.4

-

ShuffleNet 2×(g=3)

524

26.3

3.1

ShuffleNet 2×(with SE,g=3)

527

24.7

4.7

0.75 MobileNet-224

325

31.6

-

ShuffleNet 1.5×(g=3)

292

28.5

3.1

0.5 MobileNet-224

149

36.3

-

ShuffleNet 1×(g=8)

140

32.4

3.9

0.25 MobileNet-224

41

49.4

-

ShuffleNet 0.5×(g=4)

38

41.6

7.8

ShuffleNet 05×(shallow,g=3)

40

42.8

6.6

该表格展示了ShuffleNetMobileNetImageNet分类任务上的性能比较,其中使用MFLOPs表示模型的复杂度。具体参数解释如下:

Model Complexity (MFLOPs):用MFLOPs表示的模型复杂度,MFLOPs越高,模型越复杂。

Cls err. (%):分类错误率,越小越好。

∆err. (%):相对于MobileNet的分类错误率差距,越小越好。

MobileNet-224MobileNet网络在输入分辨率为224x224时的性能表现。

ShuffleNet 2×(g=3):使用ShuffleNet结构,分组数量为3,模型复杂度为MobileNet2倍。

ShuffleNet 2×(with SE[13],g=3):使用ShuffleNet结构和SE模块[13],分组数量为3,模型复杂度为MobileNet2倍。

0.75 MobileNet-224MobileNet网络在输入分辨率为224x224时,模型复杂度为MobileNet0.75倍的性能表现。

ShuffleNet 1.5×(g=3):使用ShuffleNet结构,分组数量为3,模型复杂度为MobileNet1.5倍。

0.5 MobileNet-224MobileNet网络在输入分辨率为224x224时,模型复杂度为MobileNet0.5倍的性能表现。

ShuffleNet 1×(g=8):使用ShuffleNet结构,分组数量为8,模型复杂度为MobileNet相同。

0.25 MobileNet-224MobileNet网络在输入分辨率为224x224时,模型复杂度为MobileNet0.25倍的性能表现。

ShuffleNet 0.5×(g=4):使用ShuffleNet结构,分组数量为4,模型复杂度为MobileNet0.5倍。

ShuffleNet 0.5×(shallow,g=3):使用较浅的ShuffleNet结构,分组数量为3,模型复杂度为MobileNet0.5倍。

从表格中可以提取以下信息:

在相同的模型复杂度下,ShuffleNet的分类性能优于MobileNet,这表明在相同的模型复杂度下,ShuffleNet具有更好的特征提取能力和分类性能。

在不同的模型复杂度下,ShuffleNetMobileNet的分类性能差别不大,但是在一些情况下,ShuffleNet相对于MobileNet的性能有一定提升,例如使用ShuffleNet 2×MobileNet和使用ShuffleNet 0.5×MobileNet相比。

ShuffleNet结构中的分组数量和SE模块对分类性能有一定的影响,例如使用SE模块和较大的分组数量可以提高ShuffleNet的分类性能。

随着模型复杂度的减小,分类错误率会逐渐增加。但是在相同模型复杂度下,ShuffleNet的分类错误率相对于MobileNet较小,这表明ShuffleNet在模型压缩和加速方面具有一定优势。

总的来说,该表格展示了ShuffleNetMobileNetImageNet分类任务上的性能比较,突出了ShuffleNet在模型压缩和加速方面的优势,并探究了ShuffleNet结构中分组数量和SE模块对分类性能的影响。

4.3. 与MobileNets和其他框架的比较 最近,Howard等人提出了MobileNets [12] ,其主要关注移动设备的高效网络结构。MobileNet从[3]中采用深度可分离卷积的思想,并在小模型上实现了最先进的结果。表5比较了各种复杂度下的分类得分。很明显,我们的ShuffleNet模型在所有复杂度下都优于MobileNet。尽管我们的ShuffleNet网络专为小模型(<150 MFLOPs)设计,但我们发现它在更高的计算成本方面仍优于MobileNet,例如比MobileNet 1×更准确0.3%的代价为500 MFLOPs。对于较小的网络(约40 MFLOPs),ShuffleNet比MobileNet高出7.8%。请注意,我们的ShuffleNet架构包含50个图层,而MobileNet只有28个图层。为了更好地理解,我们还尝试了在26层架构上删除第2-4个阶段的一半块的ShuffleNet(见表5中的“ShuffleNet 0.5×shallow(g =3)”)。结果表明,较浅的模型仍然比相应的MobileNet显着优秀,这意味着ShuffleNet的有效结构主要是由于其高效的结构,而不是深度。表6将我们的ShuffleNet与一些流行的模型进行了比较。结果表明,与其他模型相比,ShuffleNet具有相似的准确性,但效率更高。例如,ShuffleNet 0.5×理论上比AlexNet[21]快18倍,并具有相当的分类得分。我们将在Sec 4.5中评估实际运行时间。值得注意的是,简单的架构设计使得可以轻松地装备最新的进展,例如[13,26]。例如,在[13]中,作者提出了Squeeze-and-Excitation(SE)块,这能够在大型ImageNet模型上实现最先进的结果。我们发现SE模块与主干ShuffleNet结合也能够产生效果,例如提高ShuffleNet 2×的top-1错误率到24.7%(在表5中显示)。有趣的是,尽管理论复杂度的增加可以忽略不计,但我们发现带有 SE 模块的 ShuffleNets 通常比移动设备上的“原始”ShuffleNets 慢25%∼40%,这意味着在低成本架构设计中实际速度评估至关重要。在第4.5节中,我们将进行进一步讨论。

6. 复杂度比较。*BVLC实现

Table 6.Complexity comparison.*Implemented by BVLC (https://github.com/BVLC/caffe/tree/master/models/bvlc googlenet)

Model

CLs err.(%)

Complexity(MFLOPs)

VGG-16

28.5

15300

ShuffleNet 2×(g=3)

26.3

524

GoogleNet

31.3

1500

ShuffleNet 1×(g=8)

32.4

140

ALexNet

42.8

720

SqueezeNet

42.5

833

ShuffleNet 0.5×(g=4)

41.6

38


该表格展示了ShuffleNetMobileNetImageNet分类任务上的性能比较,其中使用MFLOPs表示模型的复杂度。具体参数解释如下:

  • Model Complexity (MFLOPs):用MFLOPs表示的模型复杂度,MFLOPs越高,模型越复杂。
  • Cls err. (%):分类错误率,越小越好。
  • ∆err. (%):相对于MobileNet的分类错误率差距,越小越好。
  • MobileNet-224:MobileNet网络在输入分辨率为224x224时的性能表现。
  • ShuffleNet 2×(g=3):使用ShuffleNet结构,分组数量为3,模型复杂度为MobileNet的2倍。
  • ShuffleNet 2×(with SE[13],g=3):使用ShuffleNet结构和SE模块[13],分组数量为3,模型复杂度为MobileNet的2倍。
  • 0.75 MobileNet-224:MobileNet网络在输入分辨率为224x224时,模型复杂度为MobileNet的0.75倍的性能表现。
  • ShuffleNet 1.5×(g=3):使用ShuffleNet结构,分组数量为3,模型复杂度为MobileNet的1.5倍。
  • 0.5 MobileNet-224:MobileNet网络在输入分辨率为224x224时,模型复杂度为MobileNet的0.5倍的性能表现。
  • ShuffleNet 1×(g=8):使用ShuffleNet结构,分组数量为8,模型复杂度为MobileNet相同。
  • 0.25 MobileNet-224:MobileNet网络在输入分辨率为224x224时,模型复杂度为MobileNet的0.25倍的性能表现。
  • ShuffleNet 0.5×(g=4):使用ShuffleNet结构,分组数量为4,模型复杂度为MobileNet的0.5倍。
  • ShuffleNet 0.5×(shallow,g=3):使用较浅的ShuffleNet结构,分组数量为3,模型复杂度为MobileNet的0.5倍。 从表格中可以提取以下信息:
  • 在相同的模型复杂度下,ShuffleNet的分类性能优于MobileNet,这表明在相同的模型复杂度下,ShuffleNet具有更好的特征提取能力和分类性能。
  • 在不同的模型复杂度下,ShuffleNet和MobileNet的分类性能差别不大,但是在一些情况下,ShuffleNet相对于MobileNet的性能有一定提升,例如使用ShuffleNet 2×与MobileNet和使用ShuffleNet 0.5×与MobileNet相比。
  • ShuffleNet结构中的分组数量和SE模块对分类性能有一定的影响,例如使用SE模块和较大的分组数量可以提高ShuffleNet的分类性能。
  • 随着模型复杂度的减小,分类错误率会逐渐增加。但是在相同模型复杂度下,ShuffleNet的分类错误率相对于MobileNet较小,这表明ShuffleNet在模型压缩和加速方面具有一定优势。 总的来说,该表格展示了ShuffleNet和MobileNet在ImageNet分类任务上的性能比较,突出了ShuffleNet在模型压缩和加速方面的优势,并探究了ShuffleNet结构中分组数量和SE模块对分类性能的影响。

7.MS COCO上的目标检测结果(数字越大代表性能越好)。对于MobileNets,我们比较了两个结果:1[12]报告的COCO检测分数;2)我们重新实现的MobileNets的微调,在训练和微调设置方面与ShuffleNets完全相同。

Table 7.Object detection results on MS COCO (larger numbers represents better performance).For MobileNets we compare two results:1)COCO detection scores reported by [12];2)finetuning from our reimplemented MobileNets,whose training and finetuning settings are exactly the same as that for ShuffleNets.

Model

mAP[.5,.95](300×image)

mAP[.5,.95](600×image)

ShuffleNet 1×(g=3)

18.7%

25.0%

ShuffleNet 2×(g=3)

14.5%

19.8%

1.0 MobileNet-244

16.4%

19.8%

1.0 MobileNet-244(our imp.)

14.9%

19.3%

该表格展示了ShuffleNetMobileNetMS COCO目标检测任务上的性能比较,评价指标为mAPmean Average Precision),其中[:5;:95]表示计算mAP时使用的IoUIntersection over Union)范围。具体参数解释如下:

  • Model:模型名称。
  • mAP :5;:95:输入分辨率为300x300时,使用IoU范围为[:5;:95]计算的mAP得分。
  • mAP :5;:95:输入分辨率为600x600时,使用IoU范围为[:5;:95]计算的mAP得分。
  • ShuffleNet 2×(g=3):使用ShuffleNet结构,分组数量为3的模型在MS COCO目标检测任务上的性能表现。
  • ShuffleNet 1×(g=3):使用ShuffleNet结构,分组数量为3的模型在MS COCO目标检测任务上的性能表现。
  • 1.0 MobileNet-224 [12]:使用MobileNet网络,在输入分辨率为224x224时,使用IoU范围为[:5;:95]计算的mAP得分,参考文献[12]。
  • 1.0 MobileNet-224 (our impl.):使用MobileNet网络(我们重新实现的版本),在输入分辨率为224x224时,使用IoU范围为[:5;:95]计算的mAP得分,训练和微调设置与ShuffleNets完全相同。 从表格中可以提取以下信息:
  • ShuffleNet在目标检测任务上的性能优于MobileNet,无论是在输入分辨率为300x300还是600x600时,ShuffleNet的mAP得分都比MobileNet高。
  • 在ShuffleNet结构中,使用更高的分组数量(ShuffleNet 2×)可以提高目标检测性能。
  • 在相同的模型复杂度下,ShuffleNet相对于MobileNet具有更好的目标检测性能。
  • 重新实现MobileNet后,其目标检测性能略低于参考文献[12]中的结果,但与ShuffleNets的结果相当。 总的来说,该表格展示了ShuffleNet和MobileNet在MS COCO目标检测任务上的性能比较,突出了ShuffleNet在目标检测任务中的优势。

表格8.在移动设备上实际推理时间(数字越小表示性能越好)。该平台基于一块高通骁龙820处理器,所有结果都是在单个线程下评估的。

Table 8.Actual inference time on mobile device (smaller number represents better performance).The platform is based on a single Qualcomm Snapdragon 820 processor.All results are evaluated with single thread.

Model

Cls err.(%)

FLOPs

224×224

480×640

720×1280

ShuffleNet 0.5×(g=3)

43.2

38M

15.2ms

87.4ms

260.1ms

ShuffleNet 1×(g=3)

32.6

140M

37.8ms

222.2ms

684.5ms

ShuffleNet 2×(g=3)

26.3

524M

108.8ms

617.0ms

1857.6ms

AlexNet

42.8

720M

184ms

1156.7ms

3622.9ms

1.0 MobileNet-244

29.4

569M

110.0ms

612.0ms

1879.2ms

该表格展示了在基于单个Qualcomm Snapdragon 820处理器的移动设备上,各个模型在不同输入分辨率下的推理时间和分类误差率。具体参数解释如下:

  • Model:模型名称。
  • Cls err.(%):分类误差率,即在ImageNet分类任务上的误差率。
  • FLOPs:模型的浮点运算量。
  • 224 × 224:输入分辨率为224×224时的推理时间。
  • 480 × 640:输入分辨率为480×640时的推理时间。
  • 720 × 1280:输入分辨率为720×1280时的推理时间。 从表格中可以提取以下信息:
  • ShuffleNet在移动设备上的推理时间优于AlexNet和MobileNet,无论是在哪种输入分辨率下,ShuffleNet的推理时间都比AlexNet和MobileNet低。
  • 在ShuffleNet结构中,使用更高的分组数量(ShuffleNet 2×)会导致更大的模型复杂度和更长的推理时间,但相对于AlexNet和MobileNet仍然具有更好的推理时间。
  • 随着输入分辨率的增加,所有模型的推理时间都会相应增长。
  • ShuffleNet在移动设备上的分类误差率优于AlexNet,但略高于MobileNet。 总的来说,该表格展示了不同模型在移动设备上的推理时间和分类误差率的比较,突出了ShuffleNet在移动设备上具有更快的推理速度和比AlexNet更低的分类误差率的优势。

1.ShuffleNetv1.py(pytorch实现)

from torch import nn
import torch

def _make_divisible(ch, divisor=8, min_ch=None):
    if min_ch is None:
        min_ch = divisor
    new_ch = max(min_ch, int(ch + divisor / 2) // divisor * divisor)
    if new_ch < 0.9 * ch:
        new_ch += divisor
    return new_ch

class ConvBNReLU(nn.Sequential):
    def __init__(self, in_channel, out_channel, kernel_size=3, stride=1, groups=1):
        padding = (kernel_size - 1) // 2
        super(ConvBNReLU, self).__init__(
            nn.Conv2d(in_channel, out_channel, kernel_size, stride, padding, groups=groups, bias=False),
            nn.BatchNorm2d(out_channel),
            nn.ReLU6(inplace=True)
        )

class InvertedResidual(nn.Module):
    def __init__(self, in_channel, out_channel, stride, expand_ratio):
        super(InvertedResidual, self).__init__()
        hidden_channel = in_channel * expand_ratio
        self.use_shortcut = stride == 1 and in_channel == out_channel
        layers = []
        if expand_ratio != 1:
            layers.append(ConvBNReLU(in_channel, hidden_channel, kernel_size=1))
        layers.extend([
            ConvBNReLU(hidden_channel, hidden_channel, stride=stride, groups=hidden_channel),
            nn.Conv2d(hidden_channel, out_channel, kernel_size=1, bias=False),
            nn.BatchNorm2d(out_channel)
        ])
        self.conv = nn.Sequential(*layers)
    def forward(self, x):
        if self.use_shortcut:
            return x + self.conv(x)
        else:
            return self.conv(x)

class MobileNetV2(nn.Module):
    def __init__(self, num_classes=1000, alpha=1.0, round_nearest=8):
        super(MobileNetV2, self).__init__()
        block = InvertedResidual
        input_channel = _make_divisible(32*alpha, round_nearest)
        last_channel = _make_divisible(1280*alpha, round_nearest)

        Inverted_residul_setting = [
            [1, 16, 1, 1],
            [6, 24, 2, 2],
            [6, 32, 3, 2],
            [6, 64, 4, 2],
            [6, 96, 3, 1],
            [6, 160, 3, 2],
            [6, 320, 1, 1]
        ]
        features = []
        features.append(ConvBNReLU(3, input_channel, stride=2))
        for t, c, n, s in Inverted_residul_setting:
            output_channel = _make_divisible(c * alpha, round_nearest)
            for i in range(n):
                stride = s if i == 0 else 1
                features.append(block(input_channel, output_channel, stride, expand_ratio=t))
                input_channel = output_channel
        features.append(ConvBNReLU(input_channel, last_channel, 1))
        self.features = nn.Sequential(*features)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.classifier = nn.Sequential(
            nn.Dropout(0.2),
            nn.Linear(last_channel, num_classes)
        )
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out')
                if m.bias is not None:
                    nn.init.zeros_(m.bias)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.ones_(m.weight)
                nn.init.zeros_(m.bias)
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0.01)
                nn.init.zeros_(m.bias)
    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

总结

最后,我们评估了在ARM平台上移动设备上ShuffleNet模型的实际推理速度。虽然具有更大的组数(例如g = 4或g =8)的ShuffleNets通常具有更好的性能,但我们发现在我们当前的实现中效率较低。从经验上来看,g = 3通常在精确度和实际推理时间之间有适当的权衡。如表8所示,采用了三个输入分辨率进行测试。由于内存访问和其他开销,我们发现每4个理论复杂度的降低通常会在我们的实现中导致约2.6倍的实际加速。尽管如此,与AlexNet[21]相比,我们的ShuffleNet 0.5×模型在可比的分类准确性下仍然实现了约13倍的实际加速(理论加速为18倍),比以前的AlexNet级别模型或速度提升方法如[14,16,22,42,43,38]要快得多。

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

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

相关文章

【从零开始学习JAVA | 第五篇】This关键字详解

目录 前言&#xff1a; This关键字&#xff1a; 作用&#xff1a; 本质&#xff1a; 总结&#xff1a; 前言&#xff1a; 相信大家在进入JAVA面向对象编程篇章以后&#xff0c;多多少少都见过This关键字&#xff0c;而他的指向很多人总是傻傻搞不清楚&#xff0c;今天我们…

chatgpt赋能python:Python编程语言的词汇量有多少?

Python编程语言的词汇量有多少&#xff1f; Python编程语言是一种广泛使用的高级编程语言&#xff0c;被广泛用于数据科学、机器学习、人工智能、Web开发、游戏开发和其他许多领域。由于Python的简单易学以及丰富的库&#xff0c;越来越多的人开始使用Python编程语言进行编程。…

【MongoDB】四、MongoDB副本集的部署

【MongoDB】四、MongoDB副本集的部署 实验目的实验内容实验步骤实验小结 实验目的 能够通过部署副本集理解副本集机制&#xff0c;从而解决大数据项目中数据丢失的问题 实验内容 环境准备&#xff1a;根据表中的信息完成3台MongoDB服务器的部署&#xff08;XXX是姓名拼音首字母…

C语言指针初阶+进阶(看这一篇就够了)

目录 本章重点 1. 指针是什么 2. 指针和指针类型 3. 野指针 4. 指针运算 5. 指针和数组 6. 二级指针 7. 指针数组 8. 字符指针 9.数组指针 10. 指针数组 11数组传参和指针传参 12. 函数指针 13. 函数指针数组 14. 指向函数指针数组的指针 15. 回调函数 16 指针和数组面试题的解…

【从零开始学习JAVA | 第三篇】类与对象 和 封装

目录 前言&#xff1a; 类与对象&#xff1a; 封装&#xff1a; 总结&#xff1a; 前言&#xff1a; 从本篇开始&#xff0c;我们就要以面向对象编程思想来进行学习了&#xff0c;今天我们学习的内容是类与对象&#xff0c;这是JAVA中的重要知识&#xff0c;让我们一起来进…

docker 项目部署 后端/前端

1.前端部署 2.后端部署 问题一&#xff1a;build出问题 ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 668a7264-5d0b-45a6-b547-fa8fff014bda::g00ukurq2ipxuvrrz8rnpyskp: "/swagger2-demo-0.0.1-SNAPSHOT.jar": …

next.js博客搭建_react-markdown渲染内容(第三步)

文章目录 ⭐前言⭐引入react-markdown&#x1f496; 使用markdown渲染&#x1f496; 文章内容布局&#x1f496; react-syntax-highlighter代码高亮 ⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本期给大家分享next项目中使用react-markdown渲染内容。 该系列的往期…

考研C语言第八章

结构体定义&#xff0c;初始化&#xff0c;结构体数组 结构体对齐 这个东西看着像数据库里面属性的定义&#xff0c;也像java里面的类的定义 #include <stdio.h> #include <string.h> #include <stdlib.h>struct student{int num;char name[20];char sex;i…

chatgpt赋能python:Python桌面编程:探索图形用户界面

Python桌面编程&#xff1a;探索图形用户界面 Python是一种广受欢迎的高级编程语言&#xff0c;被广泛应用于数据科学、人工智能、Web开发和自动化。但是&#xff0c;随着越来越多的应用程序向图形用户界面&#xff08;GUI&#xff09;转移&#xff0c;Python的桌面编程能力也…

datagrip 连接 phoenix

jar替换完后尽量重启datagrip. 然后重新连接即可. 不重启貌似报错... 效果:

chatgpt赋能python:Python更新界面:让你的应用更美观、更易用

Python更新界面&#xff1a;让你的应用更美观、更易用 Python是一门强大的编程语言&#xff0c;广泛应用于软件开发、数据分析、机器学习等领域。其中&#xff0c;Python的GUI开发能力也非常出色。Python支持多种GUI库&#xff0c;如Tkinter、PyQt、wxPython等&#xff0c;可以…

【C++篇】C++新增的一些基础特性

友情链接&#xff1a;C/C系列系统学习目录 知识总结顺序参考C Primer Plus&#xff08;第六版&#xff09;和谭浩强老师的C程序设计&#xff08;第五版&#xff09;等&#xff0c;内容以书中为标准&#xff0c;同时参考其它各类书籍以及优质文章&#xff0c;以至减少知识点上的…

Python--字典

Python--字典 <font colorblue>一、创建字典<font colorblue>二、访问字典元素<font colorblue>三、字典的增、删、查、改<font colorblue>1、添加元素<font colorblue>2、删除元素<font colorblue>3、查找元素<font colorblue>4、修…

Git——分布式版本控制系统

简介 Git是一个开源的分布式版本控制系统&#xff0c;可以高效的处理从小到很大的项目版本管理。 分类 集中式 SVN&#xff0c;CVS 使用单一的服务器用来管理和存储所有文件的修订版本&#xff1b;协同开发的成员拉取或提交都需连接到这台服务器&#xff1b;如果服务器宕机…

电控开关详细介绍 MOSFET

目录 NMOS MOSFET的开关模型 现实生活中MOSFET的截面图 输出特性曲线 总结 MOSFET的SCS模型 MOSFET的SR模型 进一步分析 例子 PMOS CMOS(Complementary Metal-Oxide-Semiconductor) NMOS 金属氧化物半导体场效应晶体管 这是一个什么样的结构呢&#xff1f; 对于…

2023 年6月开发者调查统计结果——最流行的技术(2)

2023 年6月开发者调查统计结果——最流行的技术&#xff08;2&#xff09; 本文目录&#xff1a; 二十三、编程、脚本和标记语言 二十四、数据库 二十五、云平台 二十六、网络框架和技术 二十七、其他框架和库 二十八、其他工具 二十九、集成开发环境 三十、异步工具 …

chatgpt赋能python:Python查错完全指南:如何快速诊断和解决常见的错误

Python查错完全指南&#xff1a;如何快速诊断和解决常见的错误 Python是一种高级编程语言&#xff0c;它被广泛用于数据科学、机器学习、Web开发和自动化等领域。虽然Python具有易于学习和易于使用的特点&#xff0c;但是在编写复杂的应用程序时&#xff0c;错误和异常情况经常…

chatgpt赋能python:Python构造图入门指南

Python构造图入门指南 Python是一种非常强大的编程语言&#xff0c;它可以用于各种任务&#xff0c;包括数据分析、机器学习和深度学习等领域。其中&#xff0c;构造图是Python在数据分析领域的一项非常重要的技术&#xff0c;本文将为大家介绍Python构造图的入门指南。 什么…

chatgpt赋能python:Python查找手机号码

Python查找手机号码 在今天的数字时代&#xff0c;手机号码已成为每个人生活中必不可少的一部分。虽然我们可以轻松地拥有一部手机&#xff0c;但是对于那些需要通过电话来联系客户、朋友或家庭成员的人&#xff0c;获取正确的手机号码就显得尤为重要。 这就是为什么Python查…

【科普知识】如何解决CANopen通信一体化伺服电机PDO无法正常使用

随着现代的自动化程度不断提高&#xff0c;一体化电机的应用正逐渐成为行业的新趋势。 一体化伺服电机是现代工业自动化系统中常用的设备&#xff0c;它集成了伺服电机、驱动器和控制器等功能&#xff0c;提供了高效、精确的运动控制。在其系统中&#xff0c;我们通常使用PDO&a…