最近闲着无聊在家敲了一些基本的CNN模型,这里对网上资料做一个简要的整理总结,供自己学习使用。

一、VGG

​ VGG模型是2014年ILSVRC竞赛的第二名,第一名是GoogLeNet。但是VGG模型在多个迁移学习任务中的表现要优于googLeNet。而且,从图像中提取CNN特征,VGG模型是首选算法。它的缺点在于,参数量有140M之多,需要更大的存储空间。但是这个模型很有研究价值。

VGG有多种网络结构,如VGG-11,VGG-13,VGG-16,VGG-19等。以吴恩达老师视频中讲到的VGG-16为例,

VGG网络的特点:(1)采用了小卷积核。作者将卷积核全部替换为3x3。(2)作者采用了小池化核。相比AlexNet的3x3的池化核,VGG全部为2x2的池化核。(3)层数更深,特征图更宽。基于前两点外,由于卷积核专注于扩大通道数、池化专注于缩小宽和高,使得模型架构上更深更宽的同时,计算量的增加放缓。

​ VGG的提出,使人们得到了这样一个结论:卷积神经网络的深度增加和小卷积核的使用对网络的最终分类识别效果有很大的作用。

二、GoogLeNet

文章中提出优化模型有两种途径:提高深度或是宽度。但是这两种方法都存在局限性:1.参数太多,容易过拟合,若训练数据集有限;2.网络越大计算复杂度越大,难以应用;3.网络越深,梯度越往后穿越容易消失,难以优化模型。

GoogLeNet正是围绕着这两个思路提出的,其通过构建密集的块结构——Inception(如下图)来近似最优的稀疏结构,从而达到提高性能而又不大量增加计算量的目的。

GoogLeNet增加了多种核1x1,3x3,5x5,还有直接max pooling的,但是如果简单的将这些应用到feature map上的话,concat起来的feature map厚度将会很大,所以在googlenet中为了避免这一现象提出的inception具有如下结构,在3x3前,5x5前,max pooling后分别加上了1x1的卷积核起到了降低feature map厚度的作用。5*5的卷积核会带来巨大的计算量,所以采用1 * 1的卷积核进行降维。(以下是一个Inception的代码)

class Inception(nn.Module):def __init__(self,in_channels, n1x1, n3x3_reduce, n3x3, n5x5_reduce, n5x5,         npool):super().__init__()self.brance1 = nn.Sequential(nn.Conv2d(in_channels,n1x1,kernel_size=1),nn.BatchNorm2d(n1x1),nn.ReLU(inplace=True))self.brance2 = nn.Sequential(nn.Conv2d(in_channels,n3x3_reduce,kernel_size=1),nn.BatchNorm2d(n3x3_reduce),nn.ReLU(inplace=True),nn.Conv2d(n3x3_reduce,n3x3,kernel_size=3,padding=1),nn.BatchNorm2d(n3x3),nn.ReLU(inplace=True))self.brance3 = nn.Sequential(nn.Conv2d(in_channels,n5x5_reduce,kernel_size=1),nn.BatchNorm2d(n5x5_reduce),nn.ReLU(inplace=True),nn.Conv2d(n5x5_reduce,n5x5,kernel_size=5,padding=2),nn.BatchNorm2d(n5x5),nn.ReLU(inplace=True))self.brance4 = nn.Sequential(nn.MaxPool2d(3,stride=1,padding=1),nn.Conv2d(in_channels,npool,kernel_size=1),nn.BatchNorm2d(npool),nn.ReLU(inplace=True))def forward(self,x):out = [self.brance1(x),self.brance2(x),self.brance3(x),self.brance4(x)]out = torch.cat(out,1)return out

为了解决深度问题,GoogLeNet巧妙的在不同深度处增加了两个loss来保证梯度回传消失的现象。总的网络结构如下:

三、ResNet

ResNet的提出背景是网络越深效果越好,因为CNN越深越能提取到更丰富更抽象的特征,这些特征有更高更鲁棒的语义信息,网络越深对输入图像的变化越不敏感。但是单纯的深模型会遇到问题:模型深,易造成梯度消失,继续训练时,很难再更新参数,很难学到特征。

基于这种背景,何凯明团队于2015年提出了ResNet(Residual Networks 残差网络)。残差网络(如下)通过在一个浅层网络基础上叠加y=x层,可以让网络随深度增加而不退化。将浅层的输入值直接连接到端部位置,这样避免了层层映射过程中,由于权重小于1而导致的梯度消失。它一方面使得模型可以更深,这样网络表达的能力更好了,另一方面也使得训练速度加快。

假设某段神经网络的输入是x,期望输出是H(x),如果直接把x传递到输出端,那么我们要学习的目标是F(x)=H(x)-x。此时目标相当于发生变更,称之为残差。(以下是一个残差模块的代码)

class BottleNeck(nn.Module):expansion = 4def __init__(self,in_channels,out_channels,stride=1):super().__init__()self.residual_function = nn.Sequential(nn.Conv2d(in_channels,out_channels,stride=1,bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True),nn.Conv2d(out_channels,out_channels,stride=stride,padding=1,bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True),nn.Conv2d(out_channels,out_channels*BottleNeck.expansion,\kernel_size=1,bias=False),nn.BatchNorm2d(out_channels*expansion))self.shortcut = nn.Sequential()if stride!=1 or in_channels!=out_channels*BottleNeck.expansion:self.shortcut = nn.Sequential(nn.Conv2d(in_channels,out_channels*BottleNeck.expansion,\kernel_size=1,bias=False),nn.BatchNorm2d(out_channels*BottleNeck.expansion))def forward(self,x):return nn.ReLU(inplace=True)(self.residual_function(x)+self.shortcut(x))

残差网络可以设计18、34、50、101、152层,用的都是1x1和3x3的小卷积核。

四、RIR

RIR模型的全称是ResNet in ResNet,这是一种深度dual-stream架构,它对ResNets和标准的CNN进行了推广,并且很容易实现(没有额外的计算开销)。论文中指出当前的ResNet使用identity连接会导致不同级别的特征在每一层积聚,即使在一个深度网络,前面的一些层学习到的一些特征可能在后面的层不再提供有用的信息。因此RIR网络被提出,它保留了两个流:residual stream(残差流)和transient stream(原始卷积流)。它的结构如下:

从图中可以看出一个2层的RIR模块由2个ResNet Init组成。ResNet Init结构如图b所示,dual stream通过自身卷积和交叉卷积相加得到结果,代码如下:

class ResnetInit(nn.Module):def __init__(self,in_channels,out_channels,stride):super().__init__()self.residual_stream_conv = nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1,stride=stride)self.transient_stream_conv = nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1,stride=stride)self.residual_stream_conv_across = nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1,stride=stride)self.transient_stream_conv_across = nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1,stride=stride)self.residual_bn_relu = nn.Sequential(nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.transient_bn_relu = nn.Sequential(nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.shortcut = nn.Sequential()if stride!=1 or in_channels!=out_channels:self.shortcut = nn.Sequential(nn.Conv2d(in_channels,out_channels,kernel_size=1,stride=stride))def forward(self,x):x_residual,x_transient = x,xresidual_r_r = self.residual_stream_conv(x_residual)residual_r_t = self.residual_stream_conv_across(x_transient)transient_t_t = self.transient_stream_conv(x_transient)transient_t_r = self.transient_stream_conv_across(x_residual)residual_shortcut = self.shortcut(x_residual)x_residual = self.residual_bn_relu(residual_r_r+residual_r_t+residual_shortcut)x_transient = self.transient_bn_relu(transient_t_r+transient_t_t)return x_residual,x_transient

五、InceptionResNet

谷歌于2016年提出了InceptionResNetV1和InceptionResNetV2。二者都是将Inception同ResNet相融合,加上了shortcut的分支。Inception提出的目的是使得模型更宽,ResNet提出的目的是使得模型更深,将二者结合可以使得模型又宽又深。模型结构如下:

在InceptionResNet网络中,作者采用了三种不同的Inception-ResNet模块(Inception-resnet-A,Inception-resnet-B,inception-resnet-C)。三种模块结构如下:

除此之外,作者还提出了Reduction模块(如下),分别接在Inception-resnet-A后(ReductionA)和Inception-resnet-B后(ReductionB)。Reduction的提出是为了补偿因Inception块引起的降维。k、l、m、n表示filter个数,可以在论文的表中进行查找。

InceptionResNet-v1/v2将Inception和ResNet结合到一起,使得Inception减少了冗余度和复杂度,使它能够更快的收敛,更加容易训练。

六、PreActResNet

鉴于ResNet在非常深的网络结构中也会遇到优化问题(尽管我们一般不会使用非常深的网络),作者对ResNet进行改进,提出了PreAct的残差结构,如下图所示

左图是原始的ResNet残差结构,右图是作者提出的PreActResNet残差结构。从图中我们可以看出,PreAct残差结构在进行卷积之前加入了BatchNorm和ReLU。通过实验我们得到这样的结论:不管网络有多深,整个网络中的梯度流都不会产生弥散问题。

class PreActBasic(nn.Module):expansion = 1def __init__(self, in_channels, out_channels, stride):super().__init__()self.residual = nn.Sequential(nn.BatchNorm2d(in_channels),nn.ReLU(inplace=True),nn.Conv2d(in_channels, out_channels, kernel_size=3, \stride=stride, padding=1),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True),nn.Conv2d(out_channels, out_channels * PreActBasic.expansion, \kernel_size=3, padding=1))self.shortcut = nn.Sequential()if stride != 1 or in_channels != out_channels * PreActBasic.expansion:self.shortcut = nn.Conv2d(in_channels, out_channels * PreActBasic.expansion,\                                       kernel_size=1, stride=stride)def forward(self, x):res = self.residual(x)shortcut = self.shortcut(x)return res + shortcut

七、ResNeXt

ResNeXt网络结构于2017年提出,在ResNet的基础上作出了进一步的改进。与InceptionResNet类似,作者提出这个模型的思想也是基于将模型做的更深及更宽。本文提出的 ResNeXt 结构可以在不增加参数复杂度的前提下提高准确率,还减少了超参数的数量。

在ResNeXt提出之前,有VGG系列和Inception系列网络模型。VGG系列模型主要是通过堆叠网络(即深度)来提高网络性能,Inception系列网络模型提出了split-transform-merge策略(即提高宽度)来提高网络性能。而ResNeXt将二者结合起来。下面是一个ResNeXt模块的结构:

论文中提出了cardinality(the size of the set of transformations),图示是cardinality=32时,即存在32个并联的模块,在代码中是通过组卷积实现的,就是卷积中的group size,令group=cardinality。实验证明,增加 cardinality 比增加深度和宽度更有效。

class ResNeXtBlcok(nn.Module):def __init__(self,in_channels,out_channels,stride):super().__init__()C = CARDINALITYD = int(out_channels*DEPTH)//BASEWIDTHself.split_transform = nn.Sequential(nn.Conv2d(in_channels,C*D,kernel_size=1,groups=C,bias=False),nn.BatchNorm2d(C*D),nn.ReLU(inplace=True),nn.Conv2d(C*D,C*D,kernel_size=3,stride=stride,padding=1,groups=C),nn.BatchNorm2d(C*D),nn.ReLU(inplace=True),nn.Conv2d(C*D,out_channels*expansion,kernel_size=1,bias=False),nn.BatchNorm2d(out_channels*expansion))self.shortcut = nn.Sequential()if stride!=1 or in_channels!=out_channels*4:self.shortcut = nn.Sequential(nn.Conv2d(in_channels,out_channels*expansion,kernel_size=1,\stride=stride,bias=False),nn.BatchNorm2d(out_channels*expansion))self.relu = nn.ReLU(inplace=True)def forward(self,x):shortcut = self.shortcut(x)split_transform = self.split_transform(x)out = shortcut+split_transformout = self.relu(out)return out

八、WideResNet

WideResNet的提出是因为ResNet的跳跃连接导致只有少量的残差块学习到特征。于是作者尝试着利用另一种思路:减少深度,增加宽度,就提出了WideResNet。

图c就是在图a的基础上,拓宽了跳跃连接的宽度。图d在图c的基础上增加了dropout,以提高模型的泛化能力。

模型参数如下:

在搭建好BasicBlock和BottleNeck之后,模型的代码如下:

class WideResNet(nn.Module):def __init__(self,block,block_num,wfactor,class_num=100):super().__init__()self.in_channel=16self.pre = nn.Sequential(nn.Conv2d(3,16,kernel_size=3,stride=1,padding=1),nn.BatchNorm2d(16),nn.ReLU(inplace=True))self.stage1 = self._make_stage(block,block_num[0],16*wfactor,1)self.stage2 = self._make_stage(block,block_num[1],32*wfactor,2)self.stage3 = self._make_stage(block,block_num[2],64*wfactor,2)self.avgpool = nn.AvgPool2d(8,1)self.fc = nn.Linear(64*wfactor*block.expansion,class_num)def _make_stage(self,block,block_num,out_channels,stride):strides = [stride] + [1]*(block_num-1)layers = []for stride in strides:layers.append(block(self.in_channel,out_channels,stride=stride))self.in_channel = out_channelsreturn nn.Sequential(*layers)def forward(self,x):x = self.pre(x)x = self.stage1(x)x = self.stage2(x)x = self.stage3(x)x = self.avgpool(x)x = x.view(x.size(0),-1)x = self.fc(x)return x

九、Xception

在Xception模型中,作者提出了“depth-wise separable convolution”的结构。depthwise separable convolution就是先用M个3x3卷积核一对一卷积输入的M个feature map,不求和,生成M个结果;然后用N个1x1的卷积核正常卷积前面生成的M个结果,求和,最后生成N个结果。因此文章中将depthwise separable convolution分成两步,一步叫depthwise convolution,另一步是pointwise convolution。

class SeperableConv(nn.Module):def __init__(self,in_channels,out_channels,kernel_size,**kwargs):super().__init__()self.depthwise = nn.Conv2d(in_channels,in_channels,kernel_size,\groups=in_channels,bias=False,**kwargs)self.pointwise = nn.Conv2d(in_channels,out_channels,kernel_size=1,bias=False)def forward(self,x):x = self.depthwise(x)x = self.pointwise(x)return x

下图中为Xception结构的表示。它就是由Inception v3直接演变而来。其中引入了Residual learning的结构。

Xception中引入了Entry/Middle/Exit三个flow,每个flow内部使用不同的重复模块。Entry flow主要是用来不断下采样,减小空间维度;中间的Middle flow是最核心的部分,不断学习关联关系,优化特征;最终则是通过Exit flow汇总、整理特征,用于交由FC来进行表达。

十、DenseNet

DenseNet于2017年提出。我们知道ResNet的提出,是通过shortcut来避免出现梯度消失/爆炸。因为当梯度消失/爆炸时,输入的特征不易于学习。DenseNet的核心思想就是在每一层上都加上一个单独的shortcut,使得任意两层都能直接连通。DenseNet的模型如下:

在代码实现中,是通过torch.cat操作实现任意两层互联。各层的参数如下:

其中,k表示growth_rate,即每个Dense Block中每层输出的feather map数量。BottleNeck是由1x1和3x3两层卷积层组成,目的是降维,减少计算量。Transition Layer层中包含了卷积层和池化层,使得输出通道比输入通道减少一半,并减少计算量。

实验结果证明,DenseNet在与ResNet同等复杂度和参数的情况下,效果要优于ResNet。

十一、SENet

SENet的全称是Squeeze and Excitation Networks,顾名思义,就是在网络中加入了Squeeze和Excitation操作。作者提出这个网络的目的是显式地建模卷积特征通道之间的相互依赖性来提高网络的表达能力。网络结构如下:

其中,Squeeze通过空间维度压缩特征,在空间上做全局平均池化,每个通道的二维特征变成了一个实数,这个实数某种程度上具有全局的感受野,并且输出的维度和输入的通道数相匹配。而Excitation的作用是用两个全连接层和Sigmoid函数得到各通道的权值,第一个全连接层会压缩通道数,减少计算量。该权值与Fscale得到的feature map结合得到最后的结果。下图是将SE模块嵌入Inception和ResNet中的例子:

与ResNet结合的代码如下:

class BasicResidualSEBlock(nn.Module):expansion = 1def __init__(self,in_channels,out_channels,stride,r=16):super().__init__()self.residual = nn.Sequential(nn.Conv2d(in_channels,out_channels,kernel_size=3,stride=stride,padding=1),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True),nn.Conv2d(out_channels,out_channels*self.expansion,kernel_size=3,padding=1),nn.BatchNorm2d(out_channels*self.expansion),nn.ReLU(inplace=True))self.shortcut = nn.Sequential()if stride!=1 or in_channels!=out_channels:self.shortcut = nn.Sequential(nn.Conv2d(in_channels,out_channels*self.expansion,\kernel_size=1,stride=stride),nn.BatchNorm2d(out_channels*self.expansion),nn.ReLU(inplace=True))self.squeeze = nn.AdaptiveAvgPool2d(1)self.excitation = nn.Sequential(nn.Linear(out_channels*self.expansion,out_channels*self.expansion//r),nn.ReLU(inplace=True),nn.Linear(out_channels*self.expansion//r,out_channels*self.expansion),nn.Sigmoid())def forward(self,x):shortcut = self.shortcut(x)residual = self.residual(x)squeeze = self.squeeze(residual)squeeze = squeeze.view(squeeze.size(0), -1)excitation = self.excitation(squeeze)excitation = excitation.view(residual.size(0),residual.size(1),1,1)x = residual*(excitation.expand_as(residual))+shortcutreturn nn.ReLU(inplace=True)(x)

十二、SqueezeNet

SqueezeNet 发表于ICLR-2017,作者分别来自Berkeley和Stanford,SqueezeNet不是模型压缩技术,而是 “design strategies for CNN architectures with few parameters”。SqueezeNet的思想与Inception非常类似,其提出了squeeze层和expand层。Squeeze层只采用了1x1的卷积核,使得卷积过后的通道尽可能小,以减少计算量。然后进入expand层,expand层的卷积核由1x1和3x3的卷积核构成(如下图),其思想就和Inception类似。

s1x1 (squeeze convolution layer中1x1filter的个数)、e1x1(expand layer中1∗1filter的个数)、e3x3(expand layer中3x3 filter的个数)都可以进行调整。

这里给出一个子模块的代码:

class Fire(nn.Module):def __init__(self,in_channel,out_channel,squeeze_channel):super().__init__()self.squeeze = nn.Sequential(nn.Conv2d(in_channel,squeeze_channel,kernel_size=1),nn.BatchNorm2d(squeeze_channel),nn.ReLU(inplace=True)) self.expand1x1 = nn.Sequential(nn.Conv2d(squeeze_channel,int(out_channel//2),kernel_size=1),nn.BatchNorm2d(int(out_channel//2),),nn.ReLU(inplace=True))self.expand3x3 = nn.Sequential(nn.Conv2d(squeeze_channel,int(out_channel//2),kernel_size=3,padding=1),nn.BatchNorm2d(int(out_channel//2)),nn.ReLU(inplace=True))def forward(self,x):x = self.squeeze(x)return torch.cat([self.expand1x1(x),self.expand3x3(x)],1)

文中给了三种不同的网络模型:

左边为原始的SqueezeNet,中间为包含simple bypass的改进版本,最右侧为使用complex bypass的改进版本。在下表中给出了更多的细节。关于bypass,个人理解就像shortcut,使得模型更容易优化。

十三、MobileNet

MobileNet V1,2017年Google人员发表,针对手机等嵌入式设备提出的一种轻量级的深层神经网络,采用了深度可分离的卷积。核心思想就是卷积核的巧妙分解,可以有效减少网络参数。它将标准卷积分解成一个深度卷积和一个点卷积(1 × 1卷积核),即Depthwise和Pointwise。如下图:

Depthwise将每个卷积核应用到每一个通道,体现在代码中的group,而Pointwise中1 × 1卷积则用来组合通道卷积的输出。

class DepthSeperable(nn.Module):def __init__(self,in_channels,out_channels,kernel_size,**kwargs):super().__init__()self.depthwise = nn.Sequential(nn.Conv2d(in_channels,in_channels,kernel_size=kernel_size,\groups=in_channels,**kwargs),nn.BatchNorm2d(in_channels),nn.ReLU(inplace=True))self.pointwise = nn.Sequential(nn.Conv2d(in_channels,out_channels,kernel_size=1),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))def forward(self,x):x = self.depthwise(x)x = self.pointwise(x)return x

而后,通过一个流线型的架构(堆叠式),都是由深度可分离的卷积模块堆叠的,构成最后的模型。具体的参数如下:

MobileNetV2则是在V1的基础上做出了改进,先进行1x1的Pointwise通道扩张,Depthwise+Pointwise通道压缩,然后Linear激活。

十四、ShuffleNet

ShuffleNetV1,2017年旷视科技的Xiangyu Zhang,Jian Sun发表,参考MobileNet和ResNet,提出了Channel Shuffle来增强分组卷积的全局信息流通。ShuffleNetV1是专门为计算能力有限的移动平台设计。采用两个新操作——逐渐群卷积(pointwise group convolution)和通道混洗(channel shuffle)在保障精确率损失不大的同时大大减少了计算成本。

ShuffleNetV1最大的创新点是在之前模型的基础上进一步加入了channel shuffle。假设引入group操作,设group为g,那么N个输入feature map就被分成了g个group,M个filter就被分成g个group。然后在做卷积操作时,第一个group的M/g个filter中的每一个都和第一个group的N/g个输入feature map做卷积得到结果。第二个group同理,直至最后一个group。这种操作大大减少了计算量。但如果多个group叠加在一起,如有两个卷积层都有group操作,就会产生边界效应。即某个输出channel仅来自输入channel的一小部分,这样学出来的特征会非常局限。于是需要channel shuffle来解决。效果如下图:

在进行GConv之前对其输入feature map做一个分配,也就是每个group分成几个subgroup,然后将不同group的subgroup作为GConv2的一个group的输入,使得GConv2的每一个group都能卷积输入的所有group的feature map,如(c)中的channel shuffle。其代码如下:

class ChannelShuffle(nn.Module):def __init__(self,group):self.group = groupdef forward(self,x):batch_size,channels,height,width = x.data.size() channel_per_group = channels/self.groupx = x.view(batch_size,self.group,channel_per_group,height,width)x = x.transpose(1,2).contiguous()  #这一步画一下图就明白了x = x.view(batch_size,-1,height,width)return x

ShuffleNetV2根据提出的4则轻量化标准改进了ShuffleNet V1:通道宽度相同、减少分组卷积、减少分支、减少Element-wise。主要是在网络结构及参数上做出了改动。

a和b是ShuffleNet v1的两种不同block结构,两者的差别在于后者对特征图尺寸做了缩小。c和d是ShuffleNet v2的两种不同block结构。从a和c的对比可以看出c在开始处增加了一个channel split操作,该操作将输入特征的通道分开(文中是对半切分),这样操作的目的是使得运行速度最快。然后c中取消了1x1卷积层中的group操作,这和同时前面的channel split其实已经算是变相的group操作了。其次,channel shuffle的操作移到了concat后面,同时也是因为第一个1x1卷积层没有group操作,所以在其后面跟channel shuffle也没有太大必要。最后是将element-wise add操作替换成concat,这是为了减少element-wise操作。多个c结构连接在一起的话,channel split、concat和channel shuffle是可以合并在一起的。b和d的对比也是同理,只不过因为d的开始处没有channel split操作,所以最后concat后特征图通道数翻倍。

关于ShuffleNetV2的详细解释可以参考https://blog.csdn.net/u014380165/article/details/81322175

一些常见的CNN模型相关推荐

  1. 常见的CNN模型介绍

    第一次写博客 目的是练习一下那种感觉,不足之处还望见谅 LeNet模型 用途: LeNet主要用来进行手写字符的识别与分类 特点 每个卷积层包括三部分:卷积.池化和非线性激活函数(sigmoid激活函 ...

  2. 自然语言处理中CNN模型几种常见的Max Pooling操作

    /* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author: 张俊林 (想更系统地学习深度学习知识?请参考:深度学习枕边书) CNN是目前自然语言处理中和RNN并驾齐驱的两 ...

  3. CNN 模型的参数(parameters)数量和浮点运算数量(FLOPs)是怎么计算的

    文章目录: 1 模型参数(parameters)的个数 1.1 模型参数介绍 1.2 常见网络的模型参数个数 1.2 举例如何计算神经网络模型参数 2 FLOPS:每秒浮点运算次数 2.1 `FLOP ...

  4. 卷积神经网络(CNN)模型结构

    在前面我们讲述了DNN的模型与前向反向传播算法.而在DNN大类中,卷积神经网络(Convolutional Neural Networks,以下简称CNN)是最为成功的DNN特例之一.CNN广泛的应用 ...

  5. 深度学习(四):卷积神经网络(CNN)模型结构,前向传播算法和反向传播算法介绍。

    在前面我们讲述了DNN的模型与前向反向传播算法.而在DNN大类中,卷积神经网络(Convolutional Neural Networks,以下简称CNN)是最为成功的DNN特例之一.CNN广泛的应用 ...

  6. 自然语言处理常见算法与模型

    自然语言处理中常见算法与模型 个人学习记录备份,内容只对本人有效,不保证正确性 尊重原创,感谢原作者知识共享,版权均归原作者所有 NLP预训练模型 信息熵.最大熵模型(MaxEnt/MEM) 概率图模 ...

  7. 基于TensorFlow的CNN模型——猫狗分类识别器(五)之训练和评估CNN模型

    注意:这是一个完整的项目,建议您按照完整的博客顺序阅读. 目录 三.训练和优化CNN模型 1.搭建训练主循环 2.训练时间的记录 3.早期终止机制 4.训练数据的可视化 5.训练数据的保存与加载 四. ...

  8. CNN模型的计算量、参数、显存占用

    经典CNN模型的计算量.参数.显存占用 文章目录 经典CNN模型的计算量.参数.显存占用 1. 深度学习复杂度 2. FLOPS概念 3.参数量计算 4. 输出特征图尺寸 5. 常用模型的FlOPs和 ...

  9. 【嵌入式AI】CNN模型压缩(剪枝,量化)详解与tensorflow实验

    1,CNN模型压缩综述 1 模型压缩的必要性及可行性 (1)必要性:首先是资源受限,其次在许多网络结构中,如VGG-16网络,参数数量1亿3千多万,占用500MB空间,需要进行309亿次浮点运算才能完 ...

最新文章

  1. Vue:Elementui中的Tag与页面其它元素相互交互的两三事
  2. Linux 网络编程—— libpcap 详解
  3. python猜拳游戏三局两胜制_猜拳游戏三局两胜------java实现代码
  4. 百度人脸搜索的一次尝试(JAVA)
  5. 设置linearlayout最大高度_高位消防水箱设置要求及历年真题
  6. pydebugger
  7. 在FC中如何获取fcdot文件
  8. $.ajax注册表单
  9. Java旅游动吧项目讲解_springboot动吧项目
  10. 百度前端学院参考答案:第二十五天到第二十七天 倒数开始 滴答滴 滴答滴(2)...
  11. Markdown+Pandoc→HTML幻灯片速成
  12. 烧光百亿,敢从宝马挖人!中国后台最硬神车,竟惨到卖厂还债?
  13. Ubuntu16.04+NVIDIA显卡驱动安装步骤
  14. 杨辉三角c语言if 编程,杨辉三角_用c语言怎么编程
  15. Java人事面试100问
  16. html中如何设置表格分页,html中table表格分页(修订了的)
  17. CVPR2020论文列表(中英对照)
  18. ROS中的diagnostics模块
  19. java anon,试图找到泄漏!对于pmap来说,anon意味着什么?
  20. Java实现等额本金

热门文章

  1. 文件路径 - Windows、Linux系统上的斜线,反斜线区别
  2. 斜线/、反斜线\、双斜线//、双反斜线\\——详解
  3. jquery中的this 到底是什么意思? $(this)
  4. python爬出书籍下载-Python网络爬虫从入门到实践 PDF 高质量扫描版
  5. 宝安区2021年高考成绩查询入口,宝安区2021年学位申请房屋锁定网上查询说明(附入口)...
  6. 生信软件-- HiC PRO使用
  7. matlab中行矢量,请教 错误使用 zeros 大小矢量必须是包含实数元素的行矢量
  8. 引用账户锁定无法登录_“引用的账户当前已锁定,切无法登录“问题解决方案...
  9. 百度新一轮干部轮岗:沈抖领军智能云,何俊杰负责移动生态
  10. 养猫最新版小程序源码