365天深度学习训练营-第J3周:DenseNet算法实战与解析

news/2024/4/20 6:51:04/文章来源:https://blog.csdn.net/m0_58585940/article/details/129151502

目录

  一、前言

二、论文解读

1、DenseNet的优势

2、设计理念

 3、网络结构

 4、与其他算法进行对比

三、代码复现

1、使用Pytorch实现DenseNet

2、使用Tensorflow实现DenseNet网络

四、分析总结


  一、前言

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊|接辅导、项目定制
● 难度:夯实基础⭐⭐
● 语言:Python3、Pytorch3
● 时间:2月18日-2月14日
🍺要求:1.根据本文的Pytorch代码,编写Tensorflow代码
2.了解DenseNet和ResnetV的区别
3.改进地方可以迁移到哪里呢

二、论文解读

论文:Densely Connected Convolutional Networks

       众所周知,最近一两年卷积神经网络提高效果的方向,要么深(比如ResNet,解决了网络深时候的梯度消失问题)要么宽(比如GoogleNet的Inception),而作者则是从特征图入手,通过对特征图的极致利用达到更好的效果和更少的参数。

1、DenseNet的优势

  • 减轻了vanishing-gradient(梯度消失)

这种连接方式使得特征和梯度的传递更加有效,网络也就更加容易训练。每一层都可以直接利用损失函数的梯度以及最开始的输入信息,相当于是一种隐形的深度监督(implicit deep supervision),这有助于训练更深的网络。前面提到过梯度消失问题在网络深度越深的时候越容易出现,原因就是输入信息和梯度信息在很多层之间传递导致的,而现在这种密集连接相当于每一层都直接连接输入和损失,因此就可以减轻梯度消失现象,这样构建更深的网络不是问题。

  • 加强了特征的传递,更有效地利用了特征

每层的输出特征图都是之后所有层的输入。

  • 一定程度上较少了参数数量

DenseNets的稠密连接模块(dense block)的一个优点是它比传统的卷积网络有更少的参数,因为它不需要再重新学习多余的特征图。传统的前馈结构可以被看成一种层与层之间状态传递的算法。每一层接收前一层的状态,然后将新的状态传递给下一层。它改变了状态,但也传递了需要保留的信息。ResNets将这种信息保留的更明显,因为它加入了自身变换(identity transformations)。最近很多关于ResNets的研究都表明ResNets的很多层是几乎没有起作用的,可以在训练时随机的丢掉。DenseNet结构中,增加到网络中的信息与保留的信息有着明显的不同。DenseNet的dense block中每个卷积层都很窄(例如每一层有12个滤波器),仅仅增加小数量的特征图到网络的“集体知识”(collective knowledge),并且保持这些特征图不变——最后的分类器基于网络中的所有特征图进行预测。

另外作者还观察到这种密集连接有正则化的效果,因此对于过拟合有一定的抑制作用,因为参数减少了,所以过拟合现象减轻。
参考文章


2、设计理念

DenseNet 的想法很大程度上源于一个叫做随机深度网络(Deep networks with stochastic depth)工作。当时我们提出了一种类似于 Dropout 的方法来改进ResNet。我们发现在训练过程中的每一步都随机地「扔掉」(drop)一些层,可以显著的提高 ResNet 的泛化性能。这个方法的成功至少带给我们两点启发:

  • 首先,它说明了神经网络其实并不一定要是一个递进层级结构,也就是说网络中的某一层可以不仅仅依赖于紧邻的上一层的特征,而可以依赖于更前面层学习的特征。想像一下在随机深度网络中,当第 l 层被扔掉之后,第 l+1 层就被直接连到了第 l-1 层;当第 2 到了第 l 层都被扔掉之后,第 l+1 层就直接用到了第 1 层的特征。因此,随机深度网络其实可以看成一个具有随机密集连接的 DenseNet。

  • 其次,我们在训练的过程中随机扔掉很多层也不会破坏算法的收敛,说明了 ResNet 具有比较明显的冗余性,网络中的每一层都只提取了很少的特征(即所谓的残差)。实际上,我们将训练好的 ResNet 随机的去掉几层,对网络的预测结果也不会产生太大的影响。既然每一层学习的特征这么少,能不能降低它的计算量来减小冗余呢?

DenseNet 的设计正是基于以上两点观察。我们让网络中的每一层都直接与其前面层相连,实现特征的重复利用;同时把网络的每一层设计得特别「窄」,即只学习非常少的特征图(最极端情况就是每一层只学习一个特征图),达到降低冗余性的目的。这两点也是 DenseNet 与其他网络最主要的不同。需要强调的是,第一点是第二点的前提,没有密集连接,我们是不可能把网络设计得太窄的,否则训练会出现欠拟合(under-fitting)现象,即使 ResNet 也是如此。

 3、网络结构

     CNN网络一般要经过Pooling或者stride>1的Conv来降低特征图的大小,而DenseNet的密集连接方式需要特征图大小保持一致。为了解决这个问题,DenseNet网络中使用DenseBlock+Transition的结构,其中DenseBlock是包含很多层的模块,每个层的特征图大小相同,层与层之间采用密集连接方式。而Transition层是连接两个相邻的DenseBlock,并且通过Pooling使特征图大小降低。图5给出了DenseNet的网路结构,它共包含4个DenseBlock,各个DenseBlock之间通过Transition层连接在一起。

       在DenseBlock中,各个层的特征图大小一致,可以在channel维度上连接。DenseBlock中的非线性组合函数H(·)的是 BN+ReLU+3x3 Conv 的结构,如图6所示。另外值得注意的一点是,与ResNet不同,所有DenseBlock中各个层卷积之后均输出k个特征图,即得到的特征图的channel数为k,或者说采用k个卷积核。k在DenseNet称为growth rate,这是一个超参数。一般情况下使用较小的k(比如12),就可以得到较佳的性能。假定输入层的特征图的channel数为k0,那么l层输入的channel数为,因此随着层数增加,尽管k设定得较小,DenseBlock的输入会非常多,不过这是由于特征重用所造成的,每个层仅有k个特征是自己独有的。

       由于后面层的输入会非常大,DenseBlock内部可以采用bottleneck层来减少计算量,主要是原有的结构中增加1x1 Conv,如图7所示,即BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv,称为DenseNet-B结构。其中1x1 Conv得到4k个特征图它起到的作用是降低特征数量,从而提升计算效率。

       对于Transition层,,它主要是连接两个相邻的DenseBlock,并且降低特征图大小。Transition层包括一个1x1的卷积和2x2的AvgPooling,结构为BN+ReLU+1x1Conv+2x2AvgPooling。另外,Transition层可以起到压缩模型的作用。假定层的上接DenseBlock得到的特征图channels数为m,Transition层可以产生【θm】个特征(通过卷积层),其中 是压缩系数θ∈(0,1](compression rate)。当 θ=1时,特征个数经过Transition层没有变化,即无压缩,而当压缩系数小于1时,这种结构称为DenseNet-C,文中使用θ=0.5。对于使用bottleneck层的DenseBlock结构和压缩系数小于1的Transition组合结构称为DenseNet-BC。

       对于ImageNet数据集,图片输入大小为224×224,网络结构采用包含4个DenseBlock的DenseNet-BC,其首先是一个stride=2的7x7卷积层,然后是一个stride=2的3x3 MaxPooling层,后面才进入DenseBlock。ImageNet数据集所采用的网络配置如表1所示:

 4、与其他算法进行对比

三、代码复现

1、使用Pytorch实现DenseNet

  •       这里我们采用了Pytorch的框架来实现DenseNet,首先实现DenseBlock中的内部结构,这里是BN+ReLU+1×1Conv+BN+ReLU+3×3Conv结构,最后也加入dropout层用于训练过程。
class _DenseLayer(nn.Module):def __init__(self, num_input_features, growth_rate, bn_size, drop_rate, efficient=False):super(_DenseLayer, self).__init__()self.add_module('norm1', nn.BatchNorm2d(num_input_features)),self.add_module('relu1', nn.ReLU(inplace=True)),self.add_module('conv1', nn.Conv2d(num_input_features, bn_size * growth_rate,kernel_size=1, stride=1, bias=False)),self.add_module('norm2', nn.BatchNorm2d(bn_size * growth_rate)),self.add_module('relu2', nn.ReLU(inplace=True)),self.add_module('conv2', nn.Conv2d(bn_size * growth_rate, growth_rate,kernel_size=3, stride=1, padding=1, bias=False)),self.drop_rate = drop_rateself.efficient = efficientdef forward(self, *prev_features):bn_function = _bn_function_factory(self.norm1, self.relu1, self.conv1)if self.efficient and any(prev_feature.requires_grad for prev_feature in prev_features):bottleneck_output = cp.checkpoint(bn_function, *prev_features)else:bottleneck_output = bn_function(*prev_features)new_features = self.conv2(self.relu2(self.norm2(bottleneck_output)))if self.drop_rate > 0:new_features = F.dropout(new_features, p=self.drop_rate, training=self.training)return new_features
  • 实现DenseBlock模块,内部是密集连接方式(输入特征数线性增长): 
class _DenseBlock(nn.Module):def __init__(self, num_layers, num_input_features, bn_size, growth_rate, drop_rate, efficient=False):super(_DenseBlock, self).__init__()for i in range(num_layers):layer = _DenseLayer(num_input_features + i * growth_rate,growth_rate=growth_rate,bn_size=bn_size,drop_rate=drop_rate,efficient=efficient,)self.add_module('denselayer%d' % (i + 1), layer)def forward(self, init_features):features = [init_features]for name, layer in self.named_children():new_features = layer(*features)features.append(new_features)return torch.cat(features, 1)
  • 实现Transition层,它主要是一个卷积层和一个池化层:
class _Transition(nn.Sequential):def __init__(self, num_input_features, num_output_features):super(_Transition, self).__init__()self.add_module('norm', nn.BatchNorm2d(num_input_features))self.add_module('relu', nn.ReLU(inplace=True))self.add_module('conv', nn.Conv2d(num_input_features, num_output_features,kernel_size=1, stride=1, bias=False))self.add_module('pool', nn.AvgPool2d(kernel_size=2, stride=2))
  • 最后我们实现DenseNet网络: 
class DenseNet(nn.Module):r"""Densenet-BC model class, based on`"Densely Connected Convolutional Networks" <https://arxiv.org/pdf/1608.06993.pdf>`Args:growth_rate (int) - how many filters to add each layer (`k` in paper)block_config (list of 3 or 4 ints) - how many layers in each pooling blocknum_init_features (int) - the number of filters to learn in the first convolution layerbn_size (int) - multiplicative factor for number of bottle neck layers(i.e. bn_size * k features in the bottleneck layer)drop_rate (float) - dropout rate after each dense layernum_classes (int) - number of classification classessmall_inputs (bool) - set to True if images are 32x32. Otherwise assumes images are larger.efficient (bool) - set to True to use checkpointing. Much more memory efficient, but slower."""def __init__(self, growth_rate=12, block_config=(16, 16, 16), compression=0.5,num_init_features=24, bn_size=4, drop_rate=0,num_classes=10, small_inputs=True, efficient=False):super(DenseNet, self).__init__()assert 0 < compression <= 1, 'compression of densenet should be between 0 and 1'# First convolutionif small_inputs:self.features = nn.Sequential(OrderedDict([('conv0', nn.Conv2d(3, num_init_features, kernel_size=3, stride=1, padding=1, bias=False)),]))else:self.features = nn.Sequential(OrderedDict([('conv0', nn.Conv2d(3, num_init_features, kernel_size=7, stride=2, padding=3, bias=False)),]))self.features.add_module('norm0', nn.BatchNorm2d(num_init_features))self.features.add_module('relu0', nn.ReLU(inplace=True))self.features.add_module('pool0', nn.MaxPool2d(kernel_size=3, stride=2, padding=1,ceil_mode=False))# Each denseblocknum_features = num_init_featuresfor i, num_layers in enumerate(block_config):block = _DenseBlock(num_layers=num_layers,num_input_features=num_features,bn_size=bn_size,growth_rate=growth_rate,drop_rate=drop_rate,efficient=efficient,)self.features.add_module('denseblock%d' % (i + 1), block)num_features = num_features + num_layers * growth_rateif i != len(block_config) - 1:trans = _Transition(num_input_features=num_features,num_output_features=int(num_features * compression))self.features.add_module('transition%d' % (i + 1), trans)num_features = int(num_features * compression)# Final batch normself.features.add_module('norm_final', nn.BatchNorm2d(num_features))# Linear layerself.classifier = nn.Linear(num_features, num_classes)# Initializationfor name, param in self.named_parameters():if 'conv' in name and 'weight' in name:n = param.size(0) * param.size(2) * param.size(3)param.data.normal_().mul_(math.sqrt(2. / n))elif 'norm' in name and 'weight' in name:param.data.fill_(1)elif 'norm' in name and 'bias' in name:param.data.fill_(0)elif 'classifier' in name and 'bias' in name:param.data.fill_(0)def forward(self, x):features = self.features(x)out = F.relu(features, inplace=True)out = F.adaptive_avg_pool2d(out, (1, 1))out = torch.flatten(out, 1)out = self.classifier(out)return 

2、使用Tensorflow实现DenseNet网络

  • DenseLayer
class  DenseLayer(Model):def __init__(self,bottleneck_size,growth_rate):super().__init__()self.filters=growth_rateself.bottleneck_size=bottleneck_sizeself.b1=BatchNormalization()self.a1=Activation('relu')self.c1=Conv2D(filters=self.bottleneck_size,kernel_size=(1,1),strides=1)self.b2=BatchNormalization()self.a2=Activation('relu')self.c2=Conv2D(filters=32,kernel_size=(3,3),strides=1,padding='same')def call(self,*x):x=tf.concat(x,2)x=self.b1(x)x=self.a1(x)x=self.c1(x)x=self.b2(x)x=self.a2(x)y=self.c2(x)    return y
  • Block
class DenseBlock(Model):def __init__(self,Dense_layers_num,growth_rate):#Dense_layers_num每个denseblock中的denselayer数,growthsuper().__init__()self.Dense_layers_num=Dense_layers_numself.Dense_layers=[]bottleneck_size=4*growth_ratefor i in range(Dense_layers_num):layer=DenseLayer(bottleneck_size,growth_rate)self.Dense_layers.append(layer)def call(self,input):x=[input]for layer in self.Dense_layers:output=layer(*x)x.append(output)y=tf.concat(x,2)return y
  • Transition
class Transition(Model):def __init__(self,filters):super().__init__()self.b=BatchNormalization()self.a=Activation('relu')self.c=Conv2D(filters=filters,kernel_size=(1,1),strides=1)self.p=AveragePooling2D(pool_size=(2,2),strides=2)def call(self,x):x=self.b(x)x=self.a(x)x=self.c(x)y=self.p(x)return y 
  • DenseNet
class DenseNet(Model):def __init__(self,block_list=[6,12,24,16],compression_rate=0.5,filters=64):super().__init__()growth_rate=32self.padding=ZeroPadding2D(((1,2),(1,2)))self.c1=Conv2D(filters=filters,kernel_size=(7,7),strides=2,padding='valid')self.b1=BatchNormalization()self.a1=Activation('relu')self.p1=MaxPooling2D(pool_size=(3,3),strides=2,padding='same')self.blocks=tf.keras.models.Sequential()input_channel=filtersfor i,layers_in_block in enumerate(block_list):if i<3 :self.blocks.add(DenseBlock(layers_in_block,growth_rate))block_out_channels=input_channel+layers_in_block*growth_rateself.blocks.add(Transition(filters=block_out_channels*0.5))if i==3:self.blocks.add(DenseBlock(Dense_layers_num=layers_in_block,growth_rate=growth_rate))self.p2=GlobalAveragePooling2D()self.d2=Dense(1000,activation='softmax') def call(self,x):x=self.padding(x)x=self.c1(x)x=self.b1(x)x=self.a1(x)x=self.p1(x)x=self.blocks(x)x=self.p2(x)y=self.d2(x)return y
model=DenseNet()

四、分析总结

分析:

该文章提出的DenseNet核心思想在于建立了不同层之间的连接关系,充分利用了feature,进一步减轻了梯度消失问题,加深网络不是问题,而且训练效果非常好。另外,利用bottleneck layer,Translation layer以及较小的growth rate使得网络变窄,参数减少,有效抑制了过拟合,同时计算量也减少了。DenseNet优点很多,而且在和ResNet的对比中优势还是非常明显的。

DenseNet具有如下优点:

  • 1.信息流通更为顺畅;
  • 2.支持特征重用;
  • 3.网络更窄

由于DenseNet需要在内存中保存Dense Block的每个节点的输出,此时需要极大的显存才能支持较大规模的DenseNet,这也导致了现在工业界主流的算法依旧是残差网络。

讨论

  从表面来看,DenseNets和ResNets很像:方程(2)和方程(1)的不同主要在输入 Hl(*) (进行拼接而不是求和)。然而,这个小的改变却是给这两种网络结构的性能带来了很大的差异。

模型简化性(Model Compactness)。将输入进行连接的直接结果是,DenseNets 每一层学到的特征图都可以被以后的任一层利用。该方式有助于网络特征的重复利用,也因此得到了更简化的模型。

DenseNet-BC 是参数效率最高的一个 DenseNet 版本。此外,DenseNet-BC 仅仅用了大概 ResNets 1/3 的参数量就获得了相近的准确率(中图)。该结果与图3的结果相一致。如图4右图,仅有 0.8M 参数量的 DenseNet-BC 和有 10.2M参数的 101-ResNets 准确率相近。

隐含的深度监督(implicit deep supervision)。稠密卷积网络可以提升准确率的一个解释是,由于更短的连接,每一层都可以从损失函数中获得监督信息。可以将 DenseNets 理解为一种“深度监督”(Deep supervision)。深度监督的好处已经在之前的深度监督网络(DSN)中说明,该网络在每一隐含层都加了分类器,迫使中间层也学习判断特征(discriminative features)。

  DenseNet和深度监督网络相似:网络最后的分类器通过最多两个或三个过度层为所有层提供监督信息。然而,DenseNets的损失含数字和梯度不是很复杂,这是因为所有层之间共享了损失函数。

随机 VS 确定连接。稠密卷积网络与残差网络的随机深度正则化(stochastic depth regularzaion)之间有着有趣的关系。在随机深度中,残差网络随机丢掉一些层,直接将周围的层进行连接。因为池化层没有丢掉,所以该网络和DenseNet有着相似的连接模式:以一定的小概率对相同池化层之间的任意两层进行直接连接——如果中间层随机丢掉的话。尽管这两个方法在根本上是完全不一样的,但是 DenseNet 关于随机深度的解释会给该正则化的成功提供依据。

  总结一下:DenseNet和stochastic depth的关系,在 stochastic depth中,residual中的layers在训练过程中会被随机drop掉,其实这就会使得相邻层之间直接连接,这和DenseNet是很像的

特征重复利用。根据设计来看,DenseNets 允许每一层获得之前所有层(尽管一些是通过过渡层)的特征图。我们做了一个实验来判断是否训练的网络可以重复利用这个机会。我们首先在 C10+ 数据上训练了 L=40, k=12 的 DenseNet。对于每个 block的每个卷积层 l,我们计算其与 s 层连接的平均权重。三个 dense block 的热度图如图 5 所示。平均权重表示卷积层与它之前层的依赖关系。位置(l, s)处的一个红点表示层 l 充分利用了前 s 层产生的特征图。由图中可以得到以下结论:

  • 1,在同一个 block 中,所有层都将他的权重传递给其他层作为输入。这表明早期层提取的特征可以被同一个 dense block 下深层所利用
  • 2,过渡层的权重也可以传递给之前 dense block 的所有层,也就是说 DenseNet 的信息可以以很少的间接方式从第一层流向最后一层
  • 3,第二个和第三个 dense block 内的所有层分配最少的权重给过渡层的输出,表明过渡层输出很多冗余特征。这和 DenseNet-BC 强大的结果有关系
  • 4,尽管最后的分类器也使用通过整个 dense block 的权重,但似乎更关注最后的特征图,表明网络的最后也会产生一些高层次的特征。

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

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

相关文章

基于OSG的虚拟校园系统的设计与实现

基于open scene graph的虚拟校园系统的设计与实现 摘要 •引言 • OSG基本原理 •OSG操作与动画 •视点的定位和切换 •自由漫游 •路径漫游 • 路径动画 • 点选和文字 • 粒子系统 • 3DMAX • 无线通信与数据库设计 • 实现步骤 • 结论 摘要 随着科技的不断发展,人工智能&a…

DO-254 和 DO-178B的区别(文末有易灵思核心板及配套下载线)

DO-178B介绍 DO-178B&#xff0c;机载系统和设备认证中的软件考虑&#xff0c;在电子硬件被要求符合 DO-254 之前多年就已发布和采纳。DO-178B 的先行一步对电子硬件开发带来两个特别的后果。首先&#xff0c;使得硬件制造商有了一种倾向&#xff0c;为了避免 DO-178B 对软件开…

【MySQL】sql中explain解释和应用

这里写目录标题学习原因MySQL中explain的使用和用法解释explain的使用explain 运行结果的意义文字展示表格展示参考资料&#xff1a;结束语学习原因 在对sql的优化过程中使用了explain对指定的sql进行查看它的运行效果&#xff0c;以便找出sql的性能特点并进行优化 MySQL中ex…

Linux - POSIX信号量,基于环形队列的生产者消费者模型

信号量在Linux下&#xff0c;POSIX信号量是一种线程同步机制&#xff0c;用于控制多个线程之间的访问顺序。POSIX信号量可以用于实现线程之间的互斥或者同步。在之前的阻塞队列生产者消费者模型中&#xff0c;阻塞队列是一个共享资源&#xff0c;不管是生产者还是消费者&#x…

Mysql实战之日志系统:一条SQL更新语句是如何执行的

1.前言 上一篇咱们了解了MySQL 的执行过程&#xff0c;其中设计连接器、分析器、优化器、执行器和存储引擎&#xff0c;接下来我将给大家讲解一下在MySQL中一条更新语句是如何执行。我相信大家可能听公司的DBA提起过&#xff0c;可以将数据恢复到半个月内任意时间的状态&#…

Scala集合详解(第七章:集合、数组、列表、set集合、map集合、元组、队列、并行)(尚硅谷笔记)

集合第七章:集合7.1 集合简介7.1.1 不可变集合继承图7.1.2 可变集合继承图7.2 数组7.2.1 不可变数组7.2.2 可变数组7.2.3 不可变数组与可变数组的转换7.2.4 多维数组7.3 列表 List7.3.1 不可变 List7.3.2 可变 ListBuffer7.4 Set 集合7.4.1 不可变 Set7.4.2 可变 mutable.Set7.…

Android system实战 — Android R(11) 进程保活白名单

Android system实战 — Android R 进程保活白名单0. 前言1. 具体实现1.1 准备工作1.2 源码实现1.2.1 源码1.2.2 diff文件0. 前言 最近在Android R上实现一些需求&#xff0c;进行记录一下&#xff0c;关于进程保活的基础知识可以参考Android system — 进程生命周期与ADJ&#…

自动驾驶路径规划概况

文章目录前言介绍1. 路径规划在自动驾驶系统架构中的位置2. 全局路径规划的分类2.1 基础图搜索算法2.1.1 Dijkstra算法2.1.2 双向搜索算法2.1.3 Floyd算法2.2 启发式算法2.2.1 A*算法2.2.2 D*算法2.3 基于概率采样的算法2.3.1 概率路线图&#xff08;PRM&#xff09;2.3.2 快速…

蓝牙运动耳机什么牌子的好、运动蓝牙耳机排行榜推荐

近些年&#xff0c;户外运动兴起&#xff0c;运动耳机迎来爆发增长&#xff0c;拒绝运动乏味&#xff0c;追求健康运动方式&#xff0c;已经成为当下年轻人的共同诉求。跑步骑行听音乐&#xff0c;已经是运动爱好者再熟悉不过的操作&#xff0c;很多人在运动中离不开音乐的节奏…

代码随想录算法训练营第七天 | 454.四数相加II 、 383. 赎金信、15. 三数之和、18. 四数之和 、总结

打卡第七天&#xff0c;还是哈希表。 今日任务 454.四数相加II383.赎金信15.三数之和18.四数之和总结 454.四数相加II 代码随想录 class Solution { public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, ve…

【vue2每日小知识】实现directive自定义指令的封装与全局注册

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;将我们的自定义指令directive统一管理并批量注册 目录 一、directive自定义指令介绍 二…

DS期末复习卷(六)

一、选择题(30分) 1&#xff0e; 设一组权值集合W{2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6}&#xff0c;则由该权值集合构造的哈夫曼树中带权路径长度之和为&#xff08; D &#xff09;。 (A) 20 (B) 30 (C ) 40 (D) 45 W(23)*3(456)*245 2&#xff0e;执行一…

Python、Java、JavaScript、C、Go等编程语言如何实现“定时器”功能

这是CSDN平台2月推出的一个活动(活动链接为&#xff1a;CSDN 征文活动)&#xff0c;聊聊时间的话题&#xff0c;小编我也不知道有什么好聊的时间的话题&#xff0c;看了CSDN给出的部分话题上&#xff0c;有一个这样的话题&#xff0c;如何用各种编程语言实现“定时器”&#xf…

GUI可视化应用开发及Python实现

0 建议学时 4学时&#xff0c;在机房进行 1 开发环境安装及配置 1.1 编程环境 安装PyCharm-community-2019.3.3 安装PyQt5 pip install PyQt5-tools -i https://pypi.douban.com/simple pip3 install PyQt5designer -i https://pypi.douban.com/simple1.2 环境配置 选择“…

JVM13命令行

2. JVM 监控及诊断工具-命令行篇 2.1. 概述 简单命令行工具 在我们刚接触 java 学习的时候&#xff0c;大家肯定最先了解的两个命令就是 javac&#xff0c;java&#xff0c;那么除此之外&#xff0c;还有没有其他的命令可以供我们使用呢&#xff1f; 我们进入到安装 jdk 的…

【11】FreeRTOS的延时函数

目录1.延时函数-介绍2.相对延时函数-解析2.1函数prvAddCurrentTaskToDelayedList-解析2.3滴答定时器中断服务函数xPortSysTickHandler()-解析2.4函数taskSWITCH_DELAYED_LISTS() -解析3.延时函数-实验4.总结1.延时函数-介绍 函数描述vTaskDelay()相对延时xTaskDelayUntil()绝对…

CTFer成长之路之SSRF漏洞

SSRF漏洞CTF SSRF Training 题目描述: web容器中存在一个flag&#xff0c;mysql中存在一个管理员账号密码&#xff0c;其余容器中均没有特定flag mysql容器中内置 tcpdump vulnweb容器中内置一个 fpm.py 攻击脚本 docker-compose.yml version: "3" services:w…

Spring代理模式——静态代理和动态代理

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

笔记本电脑电池和充电器CE认证IEC62133测试

EC 符合性声明 - 您可以从品牌所有者或欧盟境内的商品官方进口商处获取此文件。证明您的商品经过检测符合下表所列标准的文件。您也可以从品牌所有者或欧盟境内的官方进口商处获取此文件。原品牌的笔记本电脑或手机&#xff08;如三星、苹果、戴尔、惠普等&#xff09;提供的原…

【验证码的识别】—— 点触式验证码的识别

一、前言 大家好&#xff0c;不知不觉的我来csdn已经又一周年了&#xff0c;在这一年里&#xff0c;我收获了很多东西&#xff0c;我是2022年2月22日入驻CSDN的&#xff0c;一开始只是为了方便浏览文章的&#xff0c;后来&#xff0c;我也有事没事发发文章&#xff0c;创作了1…