目录

  • SqueezeNet
    • Fire Module: Squeeze and Expand
    • SqueezeNet
    • SqueezeNet 总结
  • MobileNet
    • 深度可分离卷积 (Depthwise Separable Convolution)
    • MobileNet v1
    • MobileNet v2
  • ShuffleNet
    • 通道混洗
    • ShuffleNet v1
    • ShuffleNet v2
  • 参考文献

SqueezeNet

Fire Module: Squeeze and Expand

  • SqueezeNet 的主要模块为 Fire Module,它主要从网络结构优化的角度出发,使用了如下 3 点策略来减少网络参数,提升网络性能:

    • (1) 使用 1×11×11×1 卷积来替代部分的 3×33×33×3 卷积,可以将参数减少为原来的 1/91/91/9,同时减少输入通道的数量
    • (2) 利用 1×11×11×1 卷积来减少输入通道的数量
    • (3) 在减少通道数之后,使用多个尺寸的卷积核进行计算,以保留更多的信息,提升分类的准确率

S1,e2,e2S_1,e_2,e_2S1​,e2​,e2​ 均代表卷积层输出的通道数,Fire Module 默认 e1=e2=4×S1e_1=e_2=4×S_1e1​=e2​=4×S1​

import torch
from torch import nnclass Fire(nn.Module):def __init__(self, inplanes, squeeze_planes, expand_planes):# 不改变输入特征图的宽高,只改变通道数# 输入通道数为 inplanes,压缩通道数为 squeeze_planes,输出通道数为 2 * expand_planessuper(Fire, self).__init__()# Squeeze 层self.conv1 = nn.Conv2d(inplanes, squeeze_planes, kernel_size=1, stride=1)self.bn1 = nn.BatchNorm2d(squeeze_planes)self.relu1 = nn.ReLU(inplace=True)# Expand 层self.conv2 = nn.Conv2d(squeeze_planes, expand_planes, kernel_size=1, stride=1)self.bn2 = nn.BatchNorm2d(expand_planes)self.conv3 = nn.Conv2d(squeeze_planes, expand_planes, kernel_size=3, stride=1, padding=1)self.bn3 = nn.BatchNorm2d(expand_planes)self.relu2 = nn.ReLU(inplace=True)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu1(x)out1 = self.conv2(x)out1 = self.bn2(out1)out2 = self.conv3(x)out2 = self.bn3(out2)out = torch.cat([out1, out2], 1)out = self.relu2(out)return out

SqueezeNet

  • 输入图像首先送入 Conv 1,得到通道数为 96 的特征图,然后依次使用 8 个 Fire Module,中间还有两个步长为 2 的最大池化层,通道数也逐渐增加。最后一个卷积为 Conv 10,输出通道数为 NNN 的特征图 (NNN 代表类别数),经过全局池化层后送入 Softmax

SqueezeNet 总结

  • SqueezeNet 是一个精心设计的轻量化网络,其性能与 AlexNet 相近,而模型参数仅有AlexNet的 1/501/501/50。使用常见的模型压缩技术,如 SVD、剪枝和量化等,可以进一步压缩该模型的大小。例如,使用 Deep Compresion 技术对其进行压缩时,在几乎不损失性能的前提下,模型大小可以压缩到 0.5MB
  • 基于其轻量化的特性,SqueezeNet 可以广泛地应用到移动端,促进了物体检测技术在移动端的部署与应用

MobileNet

深度可分离卷积 (Depthwise Separable Convolution)

  • SqueezeNet 虽在一定程度上减少了卷积计算量,但仍然使用传统的卷积计算方式,而在其后的 MobileNet 利用了更为高效的深度可分离卷积的方式,进一步加速了卷积网络在移动端的应用

标准卷积

  • 假设当前特征图大小为 Ci×H×WC_i×H×WCi​×H×W,需要输出的特征图大小为 Co×H×WC_o×H×WCo​×H×W,卷积核大小为 3×33×33×3,Padding 为 1,那么总的计算量
    Fs=Co×H×W×Ci×3×3F_s=C_o\times H\times W\times C_i\times 3\times 3Fs​=Co​×H×W×Ci​×3×3输出特征图上的每一个点都同时融合了空间信息和通道信息

深度可分离卷积

  • 深度可分离卷积将空间信息的融合和通道信息的融合分离开,将卷积的过程分为逐通道卷积 (融合空间信息) 与逐点 1×11×11×1 卷积 (融合通道信息) 两步,大大降低了计算量
  • (1) 逐通道卷积: 对于一个通道的输入特征 H×WH×WH×W,利用一个 3×33×33×3 卷积核进行点乘求和,得到一个通道的输出 H×WH×WH×W。然后,对于所有的输入通道 CiC_iCi​,使用 CiC_iCi​ 个 3×33×33×3 卷积核即可得到 Ci×H×WC_i×H×WCi​×H×W 大小的输出
    逐通道卷积的卷积核参数量为 Ci×3×3C_i×3×3Ci​×3×3,远少于标准卷积 Ci×3×3×CoC_i×3×3×C_oCi​×3×3×Co​ 的数量。同时通道之间相互独立,没有各通道间的特征融合,总计算量为:
    Fd=Ci×H×W×3×3F_d=C_i×H×W\times3\times3Fd​=Ci​×H×W×3×3
  • (2) 逐点 1×11×11×1 卷积: 逐点 1×11×11×1 卷积就是用 1×11\times11×1 卷积层融合不同通道间的特征,同时也可以改变特征图的通道。由于这里 1×11×11×1 卷积的输入特征图大小为 Ci×H×WC_i×H×WCi​×H×W,输出特征图大小为 Co×H×WC_o×H×WCo​×H×W,因此这一步的总计算量为:
    F1=Co×H×W×Ci×1×1F_1=C_o×H×W×C_i×1×1F1​=Co​×H×W×Ci​×1×1
  • 综合上述两步,可以得到深度可分离卷积与标准卷积的计算量之比
    r=Fd+F1Fs=1Co+19≈19r=\frac{F_d+F_1}{F_s}=\frac{1}{C_o}+\frac{1}{9}\approx\frac{1}{9}r=Fs​Fd​+F1​​=Co​1​+91​≈91​可以看到,深度可分离卷积总体计算量约等于标准卷积的 1/91/91/9,极大地减少了卷积过程的计算量

MobileNet v1

深度可分离卷积模块

  • 值得注意的是,在此使用了 ReLU6 来替代原始的 ReLU 激活函数,将 ReLU 的最大输出限制在 6 以下。这主要是为了满足移动端部署的需求。移动端通常使用 Float16 或者 Int8 等较低精度的模型,如果不对激活函数的输出进行限制的话,激活值的分布范围会很大,而低精度的模型很难精确地覆盖如此大范围的输出,这样会带来精度损失

MobileNet v1 整体结构

DwD_wDw​ 代表逐通道卷积 (深度分解卷积),其后需要跟一个 1×11×11×1 卷积;s2s_2s2​ 代表步长为 2 的卷积,用于缩小特征图尺寸,起到与 Pooling 层一样的作用

from torch import nnclass MobileNet(nn.Module):def __init__(self):super(MobileNet, self).__init__()# 3 x 3 standard convolutiondef conv_bn(dim_in, dim_out, stride):return nn.Sequential(nn.Conv2d(dim_in, dim_out, 3, stride, 1, bias=False),nn.BatchNorm2d(dim_out),nn.ReLU(inplace=True))# depthwise separable convolutiondef conv_dw(dim_in, dim_out, stride):return nn.Sequential(# use group convolution in PyTorch to implement channel-wise convolutionnn.Conv2d(dim_in, dim_in, 3, stride, 1, groups=dim_in, bias=False),nn.BatchNorm2d(dim_in),nn.ReLU(inplace=True),nn.Conv2d(dim_in, dim_out, 1, 1, 0, bias=False),nn.BatchNorm2d(dim_out),nn.ReLU(inplace=True),)self.model = nn.Sequential(# input: 3 x 224 x 224conv_bn(  3,  32, 2),     # 32 x 112 x 112conv_dw( 32,  64, 1),   # 64 x 112 x 112conv_dw( 64, 128, 2),   # 128 x 56 x 56conv_dw(128, 128, 1),    # 128 x 56 x 56conv_dw(128, 256, 2),    # 256 x 28 x 28conv_dw(256, 256, 1),    # 256 x 28 x 28conv_dw(256, 512, 2),    # 512 x 14 x 14conv_dw(512, 512, 1),    # 512 x 14 x 14conv_dw(512, 512, 1),    # 512 x 14 x 14conv_dw(512, 512, 1),    # 512 x 14 x 14conv_dw(512, 512, 1),    # 512 x 14 x 14conv_dw(512, 512, 1),    # 512 x 14 x 14conv_dw(512, 1024, 2),   # 1024 x 7 x 7conv_dw(1024, 1024, 1), # 1024 x 7 x 7nn.AvgPool2d(7),        # 1024 x 1 x 1)self.fc = nn.Linear(1024, 1000)def forward(self, x):x = self.model(x)x = x.view(-1, 1024)x = self.fc(x)return x

MobileNet v1 总结

  • 总体上,MobileNet v1 利用深度可分离的结构牺牲了较小的精度,带来了计算量与网络层参数的大幅降低,从而也减小了模型的大小,方便应用于移动端
  • 但 MobileNet v1 也有其自身结构带来的缺陷,主要有以下两点:
    • (1) 模型结构较为复古,采用了与 VGGNet 类似的卷积简单堆叠,没有采用残差、特征融合等先进的结构
    • (2) 深度分解卷积 (i.e. 逐通道卷积) 中各通道相互独立,卷积核维度较小,输出特征中只有较少的输入特征,再加上 ReLU 激活函数,使得输出很容易变为 0,难以恢复正常训练,因此在训练时部分卷积核容易被训练废掉

MobileNet v2

Inverted Residual Block

  • MobileNet v2 利用残差结构取代了原始的卷积堆叠方式,提出了 Inverted Residual Block。在标准的 ResNet 中,由于 3×33×33×3 卷积处的计算量较大,因此通常先使用 1×11×11×1 卷积进行特征降维,减少通道数,再送入 3×33×33×3 卷积,最后再利用 1×11×11×1 卷积升维。这种结构从形状上看中间窄两边宽,类似于沙漏形状;而在 MobileNet 中,由于使用了深度可分离卷积来逐通道计算,本身计算量就比较少,因此在此可以使用 1×11×11×1 卷积来升维,在计算量增加不大的基础上获取更好的效果,最后再用 1×11×11×1 卷积降维。这种结构中间宽两边窄,类似于柳叶,该结构也因此被称为 Inverted Residual Block
  • 依据卷积的步长,该结构可分为两种情形,在步长为 1 时使用了残差连接,融合的方式为逐元素相加;而步长为 2 时不使用残差连接

去掉 ReLU6

  • 深度可分离卷积得到的特征对应于低维空间,特征较少,如果后续接线性映射则能够保留大部分特征,而如果接非线性映射如 ReLU,则会破坏特征,造成特征的损耗,从而使得模型效果变差。针对此问题,MobileNet v2 直接去掉了每一个 Block 中最后的 ReLU6 层,减少了特征的损耗,获得了更好的检测效果
import torch.nn as nn
import math# 标准 3 x 3 卷积
def conv_bn(inp, oup, stride):return nn.Sequential(nn.Conv2d(inp, oup, 3, stride, 1, bias=False),nn.BatchNorm2d(oup),nn.ReLU6(inplace=True))# 标准 1 x 1 卷积
def conv_1x1_bn(inp, oup):return nn.Sequential(nn.Conv2d(inp, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),nn.ReLU6(inplace=True))
class InvertedResidual(nn.Module):def __init__(self, inp, oup, stride, expand_ratio):super(InvertedResidual, self).__init__()self.stride = strideassert stride in [1, 2]hidden_dim = round(inp * expand_ratio) # 中间扩展层的通道数self.use_res_connect = self.stride == 1 and inp == oupif expand_ratio == 1:# 不进行升维self.conv = nn.Sequential(# dw (逐通道卷积)nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),nn.BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),# pw-linear (降维)nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),)else:self.conv = nn.Sequential(# pw (升维)nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),nn.BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),# dw (逐通道卷积)nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),nn.BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),# pw-linear (降维)nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),)def forward(self, x):if self.use_res_connect:return x + self.conv(x)else:return self.conv(x)
class MobileNetV2(nn.Module):def __init__(self, n_class=1000, input_size=224, width_mult=1.):super(MobileNetV2, self).__init__()block = InvertedResidualinput_channel = 32last_channel = 1280interverted_residual_setting = [# t, c, n, s[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],]# building first layerassert input_size % 32 == 0input_channel = int(input_channel * width_mult)self.last_channel = int(last_channel * width_mult) if width_mult > 1.0 else last_channelself.features = [conv_bn(3, input_channel, 2)]# building inverted residual blocksfor t, c, n, s in interverted_residual_setting:output_channel = int(c * width_mult)for i in range(n):if i == 0:self.features.append(block(input_channel, output_channel, s, expand_ratio=t))else:self.features.append(block(input_channel, output_channel, 1, expand_ratio=t))input_channel = output_channel# building last several layersself.features.append(conv_1x1_bn(input_channel, self.last_channel))# make it nn.Sequentialself.features = nn.Sequential(*self.features)# building classifierself.classifier = nn.Sequential(nn.Dropout(0.2),nn.Linear(self.last_channel, n_class),)self._initialize_weights()def forward(self, x):x = self.features(x)x = x.mean(3).mean(2)x = self.classifier(x)return xdef _initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))if m.bias is not None:m.bias.data.zero_()elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()elif isinstance(m, nn.Linear):n = m.weight.size(1)m.weight.data.normal_(0, 0.01)m.bias.data.zero_()

ShuffleNet

通道混洗

  • 当前先进的轻量化网络大都使用深度可分离卷积或者组卷积,以降低网络的计算量,但这两种操作都无法改变特征的通道数,因此还需要使用 1×11×11×1 卷积来促进通道之间信息的融合并改变通道至指定维度。因此,轻量化网络中 1×11×11×1 卷积占据了大量的计算,并且致使通道之间充满约束,一定程度上降低了模型的精度
  • 为了进一步降低计算量,ShuffleNet 提出了通道混洗来完成通道之间信息的融合:
    aaa 图代表了常规的两个组卷积操作,可以看到,如果没有逐点的 1×11×11×1 卷积或者通道混洗,最终输出的特征仅由一部分输入通道的特征计算得出,这种操作阻碍了信息的流通,进而降低了特征的表达能力。因此,我们希望在一个组卷积之后,能够将特征图之间的通道信息进行融合,类似于 bbb 图的操作,将每一个组的特征分散到不同的组之后,再进行下一个组卷积,这样输出的特征就能够包含每一个组的特征,而通道混洗恰好可以实现这个过程,如 ccc 图所示
  • 通道混洗可以通过几个常规的张量操作巧妙地实现。这里对输入通道做了 1~12 的编号,一共包含 3 个组,每个组包含 4 个通道:
def channel_shuffle(x, groups):batchsize, num_channels, height, width = x.data.size()  channels_per_group = num_channels // groups# Reshapex = x.view(batchsize, groups, channels_per_group, height, width)  # Transposex = torch.transpose(x, 1, 2).contiguous()# Flattenx = x.view(batchsize, -1, height, width)return x

ShuffleNet v1

  • ShuffleNet v1 code: https://github.com/jaxony/ShuffleNet

ShuffleNet v1 基本结构单元

  • aaa 图是一个带有深度可分离卷积的残差模块 (i.e. MobileNet v2 的基本单元)
  • bbb 图则是 ShuffleNet 的基本单元,可以看到 1×11×11×1 卷积采用的是组卷积,然后进行通道的混洗,这两步可以取代 1×11×11×1 的逐点卷积,并且大大降低了计算量。3×33×33×3 卷积仍然采用深度可分离的方式
  • ccc 图是带有降采样的 ShuffleNet 单元。由于降采样时通常要伴有通道数的增加,ShuffleNet 直接将两分支拼接在一起来实现了通道数的增加,而不是常规的逐点相加

ShuffleNet v1 网络整体结构

  • 深度可分离卷积虽然可以有效降低计算量,但其存储访问效率较差,因此 ShuffleNet 只在 Stage 2, 3, 4 内使用了其特殊的基本单元,这 3 个阶段的第一个 Block 的步长为 2 以完成降采样,下一个阶段的通道数是上一个的两倍
  • g∈[1,8]g\in[1,8]g∈[1,8] 代表组卷积的组数,以控制卷积连接的稀疏性。组数越多,计算量越少,因此在相同计算资源的条件下,可以使用更多的卷积核以获取更多的通道数

ShuffleNet v2

  • paper: ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design

建立高性能网络的 4 个基本规则

  • 原有的一些轻量化方法在衡量模型性能时,通常使用浮点运算量 FLOPs (Floating Point Operations) 作为主要指标,其中 FLOPs 是指模型在进行一次前向传播时所需的浮点计算次数。然而,ShuffleNet v2 的作者通过一系列实验发现仅仅将 FLOPs 作为评判模型复杂度的指标是有问题的,FLOPs 近似的网络会存在不同的速度,还有另外两个重要的指标:内存访问时间 (Memory Access Cost,MAC) 与网络的并行度
  • 以此作为出发点,ShuffleNet v2 做了大量的实验,分析影响网络运行速度的原因,提出了建立高性能网络的 4 个基本规则
    • (1) 卷积层的输入特征与输出特征通道数相等时,MAC 最小,此时模型速度最快:轻量化网络常采用深度可分离卷积,其中 1×11\times11×1 卷积的计算复杂度最大,因此下面主要考虑卷积核大小为 1×11\times11×1 时的情况。假设输入与输出特征图大小为 h×wh\times wh×w,通道数分别为 c1,c2c_1,c_2c1​,c2​,则 FLOPs 为 B=hwc1c2B=hwc_1c_2B=hwc1​c2​,MAC 为 hw(c1+c2)+c1c2hw(c_1+c_2)+c_1c_2hw(c1​+c2​)+c1​c2​ (两项分别为输入输出特征图的大小和 1×11\times 11×1 卷积核的大小)。当 FLOPs BBB 固定时,有 c1c2=Bhwc_1c_2=\frac{B}{hw}c1​c2​=hwB​,代入 MAC 表达式可得
      MAC≥2hwB+Bhw\mathrm{MAC} \geq 2 \sqrt{h w B}+\frac{B}{h w}MAC≥2hwB​+hwB​因此 FLOPs 不变时,当且仅当 c1=c2c_1=c_2c1​=c2​ 时 MAC 最小。虽然上述理论分析只适用于有足够大的 cache 能容纳输入/出特征图及卷积参数的情况,实际 MAC 可能会有所出入,但实验证明上述规律确实存在:
    • (2) 过多的组卷积会增加 MAC,导致模型的速度变慢:组卷积能在相同 FLOPs 的条件下输出更多通道数,但更多的通道数就意味着会增大 MAC。设组数为 ggg,则 FLOPs B=hwc1c2/gB=hwc_1c_2/gB=hwc1​c2​/g,因此
      MAC=hw(c1+c2)+c1c2g=hwc1+Bgc1+Bhw\begin{aligned} \mathrm{MAC} &=h w\left(c_{1}+c_{2}\right)+\frac{c_{1} c_{2}}{g} \\ &=h w c_{1}+\frac{B g}{c_{1}}+\frac{B}{h w} \end{aligned}MAC​=hw(c1​+c2​)+gc1​c2​​=hwc1​+c1​Bg​+hwB​​由此可见, ggg 的增加会使得 MAC 显著增加
    • (3) 网络的碎片化会降低可并行度,这表明模型中分支数量越少,模型速度会越快
    • (4) 逐元素 (Element Wise) 操作虽然 FLOPs 值较低,但其 MAC 较高,因此也应当尽可能减少逐元素操作 (逐元素操作包括 ReLU, AddTensor, AddBias…)。

ShuffleNet v1 的问题

以上述 4 个规则为基础,可以看出 ShuffleNet v1 有 3 点违反了此规则

  • (1) 在 Bottleneck 中使用了 1×11×11×1 组卷积与 1×11×11×1 的逐点卷积的 bottleneck 结构,导致输入输出通道数不同,违背了规则 1 与规则 2
  • (2) 整体网络中使用了大量的组卷积,造成了太多的分组,违背了规则 3
  • (3) 网络中存在大量的逐点相加操作,违背了规则 4

ShuffleNet v2

  • 如上图所示,(a) (b) 为 v1 的基础结构,(ccc) (d) 为 v2 的基础结构。v2 提出了 Channel Split 操作,如 (ccc) 所示,将输入特征分成两部分,一部分进行真正的深度可分离计算,将计算结果与另一部分进行通道 Concat,最后进行通道的混洗操作,完成信息的互通。同时,整个过程没有使用到 1×11×11×1 组卷积,也避免了逐点相加的操作在需要降采样与通道翻倍时,ShuffleNet v2 去掉了 Channel Split 操作,这样最后 Concat 时通道数会翻倍
  • 基于此基本单元,ShuffleNet v2 的整体结构如下表所示。与 ShuffleNet v1 相比,ShuffleNet v2 在全局平均池化之前增加了一个 1×11×11×1 卷积来融合特征

参考文献

  • 《深度学习之 PyTorch 物体检测实战》

经典网络结构 (八):轻量化网络 (SqueezeNet, MobileNet, ShuffleNet)相关推荐

  1. 轻量化网络-SqueezeNet(2016)

    A.为什么需要轻量化网络? 小模型有更高效的分布式训练效率.通信开销一直是分布式CNN训练的制约因素,在数据并行训练中,通信开销与模型参数是成比例的,模型越小,通信开销就越小. 推送一个新模型到客户端 ...

  2. 突破置换模块计算瓶颈,MSRA开源轻量版HRNet,超越主流轻量化网络!|CVPR2021...

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨happy 审稿丨邓富城 编辑丨极市平台 极市导读 本文从HRNet与轻量化网络ShuffleN ...

  3. 【论文解读】突破置换模块计算瓶颈,MSRA开源轻量版HRNet,超越主流轻量化网络!|CVPR2021...

    作者丨happy 审稿丨邓富城 编辑丨极市平台 极市导读 本文从HRNet与轻量化网络ShuffleNet的组合出发,针对置换模块存在的计算瓶颈问题,提出了一种高效条件通道加权单元替换1x1卷积,并得 ...

  4. 浅析轻量化网络mobilenet

    论文地址:https://arxiv.org/abs/1704.04861:https://arxiv.org/abs/1704.04861 1.背景 MobileNet是轻量化网络的代表之作,与VG ...

  5. 轻量化网络MobileNet解析

    论文题目:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications 论文链接:https:/ ...

  6. 轻量化网络:SqueezeNext

    <SqueezeNext: Hardware-Aware Neural Network Design> 于2018年3月公开在arXiv(美[ˈɑ:rkaɪv]) :https://arx ...

  7. 轻量化网络—ShuffleNet V1 V2理解

    轻量化网络-ShuffleNetV2理解 ShuffleNetV2原始论文:https://openaccess.thecvf.com/content_ECCV_2018/html/Ningning_ ...

  8. 实时互动下视频 QoE 端到端轻量化网络建模

    在实时视频互动中,影响观众对视频体验的有较多且复杂的因素,包括:画质.流畅度以及与其耦合的观看设备等.传统客观算法会利用网络传输或编解码参数拟合接收端人的感知体验,或者使用图像质量结合其他相关参数拟合 ...

  9. 深度学习之轻量化网络

    人工智能大力发展的趋势下,移动端和嵌入式设备上部署是迫切需求,由于现如今模型越来越深,越来越大,所以轻量化是有必要的. 轻量化网络要做什么呢?在尽量保持精度的前提下,从体积和速度两方面对网络进行轻量化 ...

最新文章

  1. ADT7410 ±0.5℃精度温度传感器
  2. 搞懂 Javascript 继承原理
  3. 我的第一个C#版GDI+程序
  4. linux 信号和信号量编程
  5. System.Text.Json 中的 JsonExtensionData
  6. LeetCode 372. 超级次方(快速幂)
  7. leetcode No.123 买卖股票的最佳时机 III
  8. java jdk安装 win10,Win10安装多个jdk,共存环境配置,自由切换
  9. 本机tomcat的server.xml被还原的问题及解决办法
  10. 关于ABAP事件的一张图
  11. 拉起客户端 Universal Links Scheme Open App iOS(Deep Link)
  12. 计算机代码大全喜欢你,微信示爱代码大全 七夕情人节微信翻译表白代码2021
  13. 还在愁csdn进不去吗,看这里
  14. 微信登录报错40125和-6签名秘钥问题解决方案
  15. 三种Perceptual_metric:VGG distance,Inception Score,FID Score的源码
  16. python正则表达式提取网页的图片链接
  17. 数据持久化(Json,二进制,PlayerPrefs)
  18. Nepxion Discovery(2) 全链路条件蓝绿发布
  19. mysql32位的能装在64位的电脑上吗,32位处理器能装64位系统吗
  20. 华为服务器开虚拟化,华为服务器虚拟化的随笔

热门文章

  1. Unity优化大全(八)之 GPU-Ligh和其他
  2. 四川农大2020计算机专业录取分数线,2020四川农业大学研究生分数线汇总(含2016-2019历年复试)...
  3. 2018-NIPS-论文网址
  4. 正则表达式--常用用法及lookahead、lookbehind
  5. Linux定时器和时间管理
  6. C语言学习教程之详解C语言中的字符串数组
  7. 中国大学MOOC-翁恺-C语言程序设计习题集 02-0 到 04-4
  8. e会学计算机课后作业答案,大学语文网课答案e会学
  9. 电脑微信关闭自动保存_微信自动保存图片怎么关闭
  10. python计算时间间隔_python计算时间差