【论文阅读】【剪枝】Learning Efficient Convolutional Networks through Network Slimming

news2024/11/23 6:34:30

摘要        

        深度卷积神经网络(CNN)在许多实际应用中的部署在很大程度上受到其高计算成本的阻碍。在本文中,我们提出了一种新的神经网络学习方案,以同时1)减小模型大小;2) 减少运行时内存占用;以及3)在不损害精度的情况下减少计算操作的数量。这是通过以简单但有效的方式在网络中实施通道级稀疏性来实现的。与许多现有方法不同,所提出的方法直接适用于现代CNN架构,为训练过程引入了最小开销,并且不需要用于生成模型的专用软件/硬件加速器。我们称我们的方法为网络瘦身,它将宽网络和大网络作为输入模型,但在训练过程中,不重要的通道会被自动识别并在之后进行修剪,从而生成具有相当精度的瘦而紧凑的模型。我们在各种图像分类数据集上,用几个最先进的CNN模型(包括VGGNet、ResNet和DenseNet)实证证明了我们方法的有效性。对于VGGNet,网络瘦身的多通道版本使模型大小减少了20倍,计算操作减少了5倍。

1.介绍

        近年来,卷积神经网络(CNN)已成为各种计算机视觉任务的主要方法,例如图像分类[22]、对象检测[8]、语义分割[26]。大规模数据集、高端现代GPU和新的网络架构允许开发前所未有的大型CNN模型。例如,从AlexNet[22]、VGGNet[31]和GoogleNet[34]到ResNet[14],ImageNet分类挑战获胜者模型从8层发展到100多层。

        然而,规模较大的网络中心虽然具有更强的代表权,但更需要资源。例如,152层ResNet[14]具有超过6000万个参数,当推断分辨率为224×224的图像时,需要超过20千兆浮点运算(FLOP)。这在资源受限的平台(如移动设备、可穿戴设备或物联网(IoT)设备)上不太可能负担得起。

        在现实世界应用中部署神经网络主要受1)模型大小的限制:神经网络强大的表示能力来自其数百万可训练参数。这些参数以及网络结构信息需要存储在磁盘上,并在推理期间加载到内存中。例如,存储在ImageNet上训练的典型CNN会消耗超过300MB的空间,这对嵌入式设备来说是一个巨大的资源负担。2) 运行时内存:在推理期间,即使批量大小为1,CNNs的中间激活/响应甚至可能比存储模型参数占用更多的内存空间。对于高端GPU来说,这不是问题,但对于许多计算能力较低的应用程序来说,这是负担不起的。3) 计算操作的数量:卷积操作在高分辨率图像上的计算量很大。大型CNN在移动设备上处理一张图像可能需要几分钟的时间,这使其不适合实际应用。

        已经提出了许多工作来压缩大型CNN或直接学习更有效的CNN模型以进行快速推断。这些包括低秩近似[7]、网络量化[3,12]和二值化[28,6]、权重修剪[12]、动态推断[16]等。然而,大多数这些方法只能解决上述一个或两个挑战。此外,一些技术需要专门设计的软件/硬件加速器来加速执行[28,6,12]。

        减少大型网络中心资源消耗的另一个方向是稀疏网络。稀疏性可以施加在不同级别的结构上[2,37,35,29,25],这产生了相当大的模型大小压缩和推理加速。然而,这些方法通常需要特殊的软件/硬件加速器来获取内存增益或时间节省,尽管它比[12]中的非结构化稀疏权重矩阵更容易。

        在本文中,我们提出了网络瘦身(network slimming),这是一种简单而有效的网络训练方案,它解决了在有限资源下部署大型网络中心时的所有上述挑战。我们的方法将L1正则化应用于批处理规范化(BN)层中的缩放因子,因此在不引入任何现有CNN架构的情况下易于实现。通过L1正则化将BN缩放因子的值推向零,使我们能够识别不重要的通道(或神经元),因为每个缩放因子对应于特定的卷积通道(或完全连接层中的神经元)。这有助于在接下来的步骤中进行通道级修剪。附加的正则化项很少影响性能。事实上,在某些情况下,它会导致更高的泛化精度。修剪不重要的通道有时可能会暂时降低性能,但这种影响可以通过随后对修剪后的网络进行微调来补偿。修剪后,与最初的广域网相比,所得到的较窄网络在模型大小、运行时内存和计算操作方面更加紧凑。上述过程可以重复几次,产生一种多通道网络瘦身方案,该方案导致更紧凑的网络。

        在多个基准数据集和不同网络架构上的实验表明,我们可以获得高达20倍模式大小压缩和原始模型计算操作减少5倍的CNN模型,同时实现相同甚至更高的精度。此外,我们的方法利用传统的硬件和深度学习软件包实现了模型压缩和推理加速,因为得到的更窄的模型没有任何稀疏存储格式或计算操作。

2.相关工作

在本节中,我们将从五个方面讨论相关工作。

低秩分解使用奇异值分解(SVD)等技术,用低秩矩阵逼近神经网络中的权重矩阵[7]。该方法尤其适用于完全连接的层,产生了约3倍的模型大小压缩,但没有明显的速度加速,因为CNN中的计算操作主要来自卷积层。

权重量化。HashNet[3]提出量化网络权重。在训练之前,将网络权重散列到不同的组,并在每个组权重中共享值。这样,只需要存储共享权重和哈希索引,因此可以节省大量存储空间。[12] 在深度压缩流水线中使用了改进的量化技术,并在AlexNet和VGGNet上实现了35x到49x的压缩率。然而,这些技术既不能节省运行时内存,也不能节省推理时间,因为在推理过程中,共享权重需要恢复到其原始位置。

        [28,6]将实值权重量化为二进制/三进制权重(权重值限制为{−1,1}或{−1,0,1})。这就节省了大量的模型大小,并且在给定按位操作库的情况下也可以获得显著的加速。然而,这种激进的低比特近似方法通常具有适度的精度损失。

权重修剪/稀疏。[12] 提出在经过训练的神经网络中用小权重修剪不重要的连接。生成的网络权重大多为零,因此可以通过以稀疏格式存储模型来减少存储空间。然而,这些方法只能通过专用的稀疏矩阵运算库和/或硬件实现加速。运行时内存节省也非常有限,因为大多数内存空间被激活映射(仍然密集)而不是权重消耗。

        在[12]中,没有训练期间稀疏性的指导。[32]通过使用额外的门变量显式地对每个权重施加稀疏约束来克服这一限制,并通过修剪具有零门值的连接来实现高压缩率。这个方法实现了比[12]更好的压缩率,但也有同样的缺点。

结构化修剪/稀疏。最近,[23]提出在训练的神经网络中修剪具有较小传入权重的通道,然后微调网络以恢复准确性。[2] 通过在训练之前随机停用卷积层中的输入-输出通道连接,引入了稀疏性,这也产生了具有中等精度损失的较小网络。与这些工作相比,我们在训练期间在优化目标中明确地施加了通道方向的稀疏性,导致了更平滑的通道修剪过程和很少的精度损失。

        [37]在训练期间施加神经元级稀疏性,因此可以修剪一些神经元以获得紧凑的网络。[35]提出了一种结构化稀疏学习(SSL)方法,以稀疏化CNN中不同级别的结构(例如,过滤器、通道或层)。这两种方法都在训练期间利用组稀疏性调节来获得结构化稀疏性。我们的方法不依赖于卷积权重上的组稀疏性,而是将简单的L1稀疏性应用于通道缩放因子,因此优化目标要简单得多。

        由于这些方法删减或稀疏部分网络结构(例如,神经元、通道)而不是单个权重,因此它们通常需要较少专门的库(例如,用于稀疏计算操作)来实现推理加速和运行时内存节省。我们的网络瘦身也属于这一类,绝对不需要专门的libraries来获得好处。

神经架构学习。虽然最先进的网络网络通常由专家设计[22,31,14],但也有一些关于自动学习网络架构的探索。[20] 介绍了在给定资源预算下进行网络架构搜索的子模块/超级模块优化。最近的一些工作[38,1]提出通过强化学习来自动学习神经结构。这些方法的搜索空间非常大,因此需要训练数百个模型来区分好坏。网络瘦身也可以被视为架构学习的一种方法,尽管选择限于每层的宽度。然而,与上述方法不同的是,网络瘦身仅通过单个训练过程学习网络架构,这符合我们的效率目标。

通道级稀疏的优势。如在先前工作[35,23,11]中所讨论的,稀疏性可以在不同级别实现,例如,权重级别、内核级别、通道级别或层级别。细粒度级别(例如,权重级别)的稀疏性提供了最高的灵活性,通用性导致了更高的压缩率,但通常需要特殊的软件或硬件加速器来对稀疏模型进行快速推断[11]。相反,最粗糙的层级稀疏性不需要特殊的包来获取推理加速,而由于需要修剪某些整个层,因此它不太灵活。事实上,移除层仅在深度足够大时有效,例如,超过50层[35,18]。相比之下,通道级稀疏性在灵活性和易实现性之间提供了很好的折衷。它可以应用于任何典型的神经网络或完全连接的网络(将每个神经元视为一个通道),由此产生的网络本质上是未调谐网络的“稀疏”版本,可以在传统的神经网络平台上高效地进行推断。

挑战。实现通道级稀疏性需要修剪与通道相关的所有传入和传出连接。这使得在预先训练的模型上直接修剪权重的方法无效,因为通道的输入或输出端的所有权重不太可能恰好接近零值。如[23]中所述,在预训练的ResNets上修剪通道只能导致参数数量减少约10%,而不会造成精度损失。[35]通过将稀疏正则化引入训练目标来解决这个问题。具体而言,他们采用组LASSO在训练期间将对应于同一通道的所有滤波器权重同时推向零。然而,这种方法需要计算关于所有滤波器权重的附加正则化项的梯度,这是非常重要的。我们介绍了一个简单的想法来解决上述挑战,具体内容如下。

缩放因子和稀疏度引起的惩罚。我们的想法是为每个通道引入缩放因子γ,乘以该通道的输出。然后我们联合训练网络权重和这些缩放因子,并对后者进行稀疏正则化。最后,我们用较小的因素对这些频道进行修剪,并对修剪后的网络进行微调。具体而言,我们方法的培训目标如下

3. Network slimming

我们的目标是提供一种简单的方案,以实现深度CNN中的通道级稀疏性。在本节中,我们首先讨论了通道级稀疏性的优势和挑战,并介绍了如何在批量归一化中利用缩放层来有效地识别和修剪网络中不重要的通道。

通道级稀疏的优势。如在先前工作[35,23,11]中所讨论的,稀疏性可以在不同级别实现,例如,权重级别、内核级别、通道级别或层级别。细粒度级别(例如,权重级别)的稀疏性提供了最高的灵活性,通用性导致了更高的压缩率,但通常需要特殊的软件或硬件加速器来对稀疏模型进行快速推断[11]。相反,最粗糙的层级稀疏性不需要特殊的包来获取推理加速,而由于需要修剪某些整个层,因此它不太灵活。事实上,移除层仅在深度足够大时有效,例如,超过50层[35,18]。相比之下,通道级稀疏性在灵活性和易实现性之间提供了很好的折衷。它可以应用于任何典型的神经网络或完全连接的网络(将每个神经元视为一个通道),由此产生的网络本质上是未调谐网络的“稀疏”版本,可以在传统的神经网络平台上高效地进行推断。

挑战。实现通道级稀疏性需要修剪与通道相关的所有传入和传出连接。这使得在预先训练的模型上直接修剪权重的方法无效,因为通道的输入或输出端的所有权重不太可能恰好接近零值。如[23]中所述,在预训练的ResNets上修剪通道只能导致参数数量减少约10%,而不会造成精度损失。[35]通过将稀疏正则化引入训练目标来解决这个问题。具体而言,他们采用组LASSO在训练期间将对应于同一通道的所有滤波器权重同时推向零。然而,这种方法需要计算关于所有滤波器权重的附加正则化项的梯度,这是非常重要的。我们介绍了一个简单的想法来解决上述挑战,具体内容如下。

缩放因子和稀疏度引起的惩罚。我们的想法是为每个通道引入缩放因子γ,乘以该通道的输出。然后我们联合训练网络权重和这些缩放因子,并对后者进行稀疏正则化。最后,我们用较小的因素对这些频道进行修剪,并对修剪后的网络进行微调。具体而言,我们方法的培训目标如下

其中(x,y)表示训练输入和目标,W表示可训练权重,第一和项对应于CNN的正常训练损失,g(·)是缩放因子上的稀疏性导致的惩罚,λ平衡这两个项。

在我们的实验中,我们选择g(s)=|s|,这被称为L1范数,并被广泛用于实现稀疏性。采用亚梯度下降作为非光滑L1惩罚项的优化方法。另一种选择是用smooth-L1惩罚[30]替换L1惩罚,以避免在非平滑点使用子梯度。

        由于修剪通道基本上对应于删除该通道的所有传入和传出连接,因此我们可以直接获得窄网络(见图1),而无需使用任何特殊的稀疏计算包。缩放因子充当频道选择的代理。当它们与网络权重联合优化时,网络可以自动识别不重要的通道,这些通道可以被安全地去除,而不会大大影响泛化性能。

 图1:我们将缩放因子(从批处理归一化层重用)与卷积层中的每个通道相关联。在训练期间对这些缩放因子进行稀疏正则化,以自动识别不重要的通道。具有小比例因子值(橙色)的通道将被修剪(左侧)。修剪后,我们获得了紧凑的模型(右侧),然后对其进行微调,以达到与正常训练的全网络相当(甚至更高)的精度。

利用BN层中的缩放因子。批归一化[19]已被大多数现代神经网络采用,作为实现快速收敛和更好泛化性能的标准方法。BN规范化激活的方式激励我们设计一种简单而有效的方法,以结合信道方向的缩放因子。特别是,BN层使用小批量统计对内部激活进行归一化。设zin和zout为BN层的输入和输出,B表示当前的小批量,BN层执行以下转换:

其中µB和σB是B上输入激活的平均值和标准偏差值,γ和β是可训练仿射变换参数(尺度和位移),这提供了将归一化激活线性变换回任何尺度的可能性。

通常的做法是在卷积层之后插入BN层,具有信道方向缩放/移位参数。因此,我们可以直接利用BN层中的γ参数作为网络瘦身所需的缩放因子。它具有不给网络引入开销的巨大优势。事实上,这可能也是我们学习有意义的缩放因子进行信道修剪的最有效方法。1)如果我们向没有BN层的CNN添加缩放层,缩放因子的值对于评估信道的重要性没有意义,因为卷积层和缩放层都是线性变换。通过减小缩放因子值同时放大卷积层中的权重,可以获得相同的结果。2) 如果我们在BN层之前插入缩放层,缩放层的缩放效果将被BN中的归一化过程完全抵消。

3)如果我们在BN层之后插入缩放层,则每个通道有两个连续的缩放因子。

通道修剪和微调。在信道级稀疏性诱导的正则化下进行训练后,我们获得了一个模型,其中许多缩放因子接近于零(见图1)。然后,我们可以通过删除所有传入和传出连接以及相应的权重,以接近零的缩放因子来修剪信道。我们在所有层上使用全局阈值修剪通道,该阈值定义为所有缩放因子值的某个百分比。例如,我们通过选择百分位阈值为70%,以较低的缩放因子修剪70%的通道。通过这样做,我们获得了一个更紧凑的网络,具有更少的参数和运行时内存,以及更少的计算操作。

        当修剪比率较高时,修剪可能会暂时导致一些精度损失。但这在很大程度上可以通过对修剪后的网络进行后续微调来补偿。在我们的实验中,在许多情况下,微调的窄网络甚至可以实现比原始未调谐网络更高的精度。

多通道方案。我们还可以将所提出的方法从单遍学习方案(使用稀疏正则化、修剪和微调进行训练)扩展到多遍方案。具体来说,网络瘦身过程导致了一个狭窄的网络,我们可以再次应用整个训练过程来学习一个更紧凑的模型。图2中的虚线说明了这一点。实验结果表明,这种多通道方案在压缩率方面可以得到更好的结果。

处理跨层连接和预激活结构。上面介绍的网络瘦身过程可以直接应用于大多数普通的CNN架构,如AlexNet[22]和VGGNet[31]。当它应用于具有跨层连接和预激活设计的现代网络(如ResNet[15]和DenseNet[17])时,需要进行一些调整。对于这些网络,一个层的输出可以被视为多个后续层的输入,其中BN层被放置在卷积层之前。在这种情况下,在层的传入端实现稀疏性,即,该层选择性地使用其接收的信道子集。为了在测试时获得参数和计算节省,我们需要放置一个信道选择层来屏蔽我们识别的不重要信道。

 4.实验

实验部分就不写了

5.分析

在网络瘦身中有两个关键的超参数,即修剪百分比t和稀疏正则化项λ的系数(见等式1)。在本节中,我们将更详细地分析它们的影响。

修剪百分比的影响。一旦我们获得了一个用稀疏正则化训练的模型,我们就需要决定从模型中删减多少百分比的通道。如果我们修剪的频道太少,节省的资源就会非常有限。然而,如果我们修剪过多的通道,可能会对模型造成破坏,并且可能无法通过微调来恢复精度。我们在CIFAR-10上训练了λ=10−5的DenseNet40模型,以显示修剪不同百分比信道的效果。结果汇总在图5中。从图5可以得出结论,只有当修剪比率超过阈值时,修剪或微调模型的分类性能才会降低。

微调过程通常可以补偿修剪造成的可能的精度损失。只有当阈值超过80%时,微调模型的测试误差才低于基线模型。值得注意的是,当使用稀疏度训练时,即使没有微调,该模型的性能也优于原始模型。这可能是由于L1稀疏性对信道缩放因子的正则化影响。

通道稀疏正则化。L1稀疏项的目的是迫使许多缩放因子接近零。与正常训练损失相比,方程1中的参数λ控制其显著性。在图4中,我们用不同的λ值绘制了整个网络中比例因子的分布。对于这个实验,我们使用在CIFAR-10数据集上训练的VGGNet。

可以观察到,随着λ的增加,缩放因子越来越集中在零附近。当λ=0时,即没有稀疏正则化,分布相对平坦。当λ=10−4时,几乎所有比例因子都落入接近零的小区域。这个过程可以看作是发生在深度网络中间层的特征选择,其中仅选择具有不可忽略的缩放因子的信道。我们通过热图进一步可视化这个过程。图6显示了VGGNet中一层的缩放因子在训练过程中的大小。每个通道以相等的权重开始;随着时间的推移,一些通道的缩放因子变大(更亮),而另一些通道变小(更暗)。

6.结论

我们提出了network slimming技术来学习更紧凑的神经网络。它直接将稀疏性诱导的正则化应用于批量归一化层中的缩放因子,因此可以在训练过程中自动识别不重要的通道,然后进行修剪。在多个数据集上,我们已经表明,所提出的方法能够显著降低最先进网络的计算成本(高达20倍),并且没有精度损失。更重要的是,所提出的方法同时减少了模型大小、运行时内存和计算操作,同时为训练过程引入了最小的开销,并且生成的模型不需要用于有效推理的特殊库/硬件。

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

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

相关文章

Kali Linux- 社会工程及压力工具教程

在本章中,我们将了解 Kali Linux 中使用的社会工程工具。 文章目录社会工程Kali Linux - 压力工具SlowhttptestinvitefloodTHC-SSL-DOS总结社会工程 社会工程师工具包 (SET) 是一个专为社会工程设计的开源渗透测试框架。SET具有许多自定义攻…

第九章(12):STL之常用查找算法

文章目录前情回顾常用查找算法findfind_ifadjacent_findbinary_searchcountcount_if下一座石碑🎉welcome🎉 ✒️博主介绍:一名大一的智能制造专业学生,在学习C/C的路上会越走越远,后面不定期更新有关C/C语法&#xff0…

读懂用户之用户调研怎么做?(内附模板教程)

随着互联网的发展,不管是做产品设计、运营,还是市场推广,我们都需要思考的是“用户真正想要的是什么?”。这时候,用户调研的重要性就凸显出来了。 一、什么是用户调研 用户调研,指通过各种方式得到受访者的…

Redis常用指令

3. 常用指令 在这部分中呢,我们家学习两个知识,第一个是key的常用指令,第二个是数据库的常用指令。和前面我们学数据类型做一下区分,前面你学的那些指令呢,都是针对某一个数据类型操作的,现在学的都是对所…

#14环形链表#

环形链表 1题目链接 链接 2思路 slow和fast指向链表的开始 slow一次走一步 fast一次走两步 不带环 fast就会为空 带环 fast就会在环里追上slow 3实现 bool hasCycle(struct ListNode* head) {struct ListNode* slow head, * fast head;while (fast && fast->ne…

微信小程序学习第3天——网络数据请求

一、小程序网络请求限制 1、必须https类型的接口 2、必须将接口的域名添加到信任列表中 二、配置request合法域名 配置步骤:登录微信小程序管理后台 -> 开发 -> 开发设置 -> 服务器域名 -> 修改 request 合法域名 点击修改request合法域名&#xf…

【自动化测试】从0开始玩转docker—— 01软件安装

目的 CI / CD在目前各类互联网企业中已然成为推动软件开发行为的重要基础设施服务。同样的对于测试团队来说更是有着举足轻重的重大意义,无论是测试左移的具象化提现亦或是持续测试的顺利开展,掌握这一技能已是广大软件测试工程师的必修课。分享这一技术…

Springboot+Vue+Uniapp自媒体视频系统

简介:本项目采用了基本的springbootvueuniapp设计的自媒体系统。详情请看主要截图。经测试,本项目正常运行。本项目适用于Java毕业设计、课程设计学习参考等用途。 项目描述 项目名称SpringbootVueUniapp自媒体视频系统源码作者LHL项目类型Java EE项目 …

C++vector容器

目录 1.vector基本概念 2.构造函数 3.vector赋值操作,,assign 4.vector容量和大小 ,empty,capacity,size,resize 5.vector的插入和删除,push_back,pop_back,insert,erase,clear 6.vector数据存取,at,[],遍历 7.vector互换…

C++之引用(上)

文章目录前言一、引用二、引用的写法三、引用特性1.引用在定义时必须初始化2. 一个变量可以有多个引用3. 引用一旦引用一个实体,再不能引用其他实体三、引用的权限(含例子)四、常引用总结前言 今天要介绍的是C中的一个新概念——引用。 一、…

MobaXterm使用指南

MobaXterm使用指南 1. 介绍 通俗的来讲,MobaXterm就是一款SSH客户端,它帮助我们在Windows操作系统下去连接并操作Linux服务器。MobaXterm 又名 MobaXVT,是一款增强型终端、X 服务器和 Unix 命令集(GNU/ Cygwin)工具箱。MobaXterm 可以开启多…

Django网页+Yolov5垃圾识别系统

Django网页Yolov5垃圾识别系统如需安装运行环境或远程调试&#xff0c;见文章底部个人微信或QQ名片&#xff0c;由专业技术人员远程协助&#xff01;前言这篇博客针对<<Django网页Yolov5垃圾识别系统>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易…

代码随想录NO33 |Leetcode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球

贪心LeetCode_860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球今天是贪心第四天的题了&#xff0c;快开始dp了&#xff01;大头啊&#xff01; 860.柠檬水找零 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&am…

day28|1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

1005.K次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k &#xff0c;按以下方法修改该数组&#xff1a; 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后&#xff0c;返回数组 可能的…

若依框架实现多级联动下拉

最近也是用到了若依的多级联动&#xff0c;效果如下&#xff08;可多级&#xff09; 若依有已经封装好的一套js&#xff0c;难点在于后端数据封装&#xff0c;前端按照封装好的代码引用即可。 这里主要分享下关于后端数据如何封装多层。后端代码直接奉上。 记得要把集合转j…

SpringBoot+Vue+Wx新冠疫苗预约系统

简介&#xff1a;本项目采用了基本的springbootvue微信小程序设计的新冠疫苗预约系统。详情请看主要截图。经测试&#xff0c;本项目正常运行。本项目适用于Java毕业设计、课程设计学习参考等用途。 项目描述 项目名称SpringBootVueWx新冠疫苗预约系统源码作者LHL项目类型Java…

python爬虫正则表达式

博主简介&#xff1a;博主是一个大二学生&#xff0c;主攻人工智能领域研究。感谢缘分让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;C&#xff0c;python&#xff0c;爬虫等方面的知识分享。如果有需要的小伙伴&#xff0c;可以关注博主&#xff…

零碎的算法笔记(1)

From算法竞赛入门经典 第2版1.判断 n 是否为完全平方数2. 比较大的数组应尽量声明在 main 函数外&#xff0c;否则程序可能无法运行 3.开灯问题1.判断 n 是否为完全平方数 可以先求出其平方根&#xff0c;然后看它是否为整数&#xff0c;即用一个 int 型变量 m 存储 sqrt(n&am…

C++入门(二)

C入门&#xff08;二&#xff09;1.引用1.1引用概念1.2引用特性1.3常应用1.4使用场景1.5传值、传引用效率比较1.6引用和指针的区别2.内联函数2.1概念2.2内联函数的特性3.auto关键字&#xff08;C11&#xff09;3.1auto使用细则4.基于范围的for循环&#xff08;C11&#xff09;5…

题库——“C”

由于小雅兰的C语言程序设计考试的时间实在是越来越近了&#xff0c;那么&#xff0c;这篇博客也就产生了&#xff0c;这篇博客的主要内容是一些C语言程序设计的练习题&#xff0c;现在&#xff0c;就让我们一起进入C语言的世界吧。 1.函数fun的功能是&#xff1a;将形参n中&…