【AI系统】ESPNet 系列

简介: 本文介绍了ESPNet系列,专注于高分辨率图像的语义分割,强调了其高效的计算性能和低内存、功耗特性。ESPNet V1提出了ESP模块,通过分解标准卷积为point-wise卷积和空洞卷积金字塔,大幅减少了参数量和计算成本。ESPNet V2则进一步优化,采用了分组卷积和深度空洞分离卷积,增强了模型的有效感受野,同时降低了浮点计算量,适用于多种视觉任务。

本文将会介绍 ESPNet 系列,该网络主要应用在高分辨率图像下的语义分割,在计算内存占用、功耗方面都非常高效,重点介绍一种高效的空间金字塔卷积模块(ESP Module);而在 ESPNet V2 上则是会更进一步给大家呈现如何利用分组卷积核,深度空洞分离卷积学习巨大有效感受野,进一步降低浮点计算量和参数量。

ESPNet V1 模型

ESPNet V1:应用在高分辨图像下的语义分割,在计算、内存占用、功耗方面都非常高效。主要贡献在于基于传统卷积模块,提出高效空间金子塔卷积模块(ESP Module),有助于减少模型运算量和内存、功率消耗,来提升终端设备适用性,方便部署到移动端。

ESP 模块

基于卷积因子分解的原则,ESP(Efficient spatial pyramid)模块将标准卷积分解成 point-wise 卷积和空洞卷积金字塔(spatial pyramid of dilated convolutions)。point-wise 卷积将输入的特征映射到低维特征空间,即采用 K 个 1x1xM 的小卷积核对输入的特征进行卷积操作,1x1 卷积的作用其实就是为了降低维度,这样就可以减少参数。空洞卷积金字塔使用 K 组空洞卷积的同时下采样得到低维特征,这种分解方法能够大量减少 ESP 模块的参数和内存,并且保证了较大的感受野(如下图 a 所示)。

ESPNet

上图 (b) 展示了 ESP 模块采用的减少-分裂-转换-合并策略。下面来计算下一共包含的参数,其实在效果上,以这种轻量级的网络作为 backbone 效果肯定不如那些参数量大的网络模型,比如 Resnet,但是在运行速度上有很大优势。

如上图所示,对 ESP 模块的第一部分来说,$d\quad$ 个 $1\times 1\times M \quad\quad\quad$ 的卷积核,将 M 维的输入特征降至 d 维。此时参数为:$M*N/K \quad\quad\quad$,第二部分参数量为 $K*n^{2}*(N/K)^{2}\quad\quad\quad\quad$,和标准卷积结构相比,参数数量降低很多。

为了减少计算量,又引入了一个简单的超参数 K,它的作用是统一收缩网络中各个 ESP 模块的特征映射维数。Reduce 对于给定 K,ESP 模块首先通过逐点卷积将特征映射从 m 维空间缩减到 $N/K$ 维空间(上图 a 中的步骤 1)。通过 Split 将低维特征映射拆分到 K 个并行分支上。

然后每个分支使用 $2^{k-1},k=1,...,k-1 \quad\quad\quad\quad$ 给出的 $n\times n \quad\quad$ 个扩张速率不同的卷积核同时处理这些特征映射(上图 a 中的步骤 2)。最后将 K 个并行扩展卷积核的输出连接起来,产生一个 n 维输出特征图。

下面代码使用 PyTorch 来实现具体的 ESP 模块:

class ESPModule(nn.Module):
    def __init__(self, in_channels, out_channels, K=5, ks=3, stride=1,act_type='prelu',):
        super(ESPModule, self).__init__()
        self.K = K
        self.stride = stride
        self.use_skip = (in_channels == out_channels) and (stride == 1)
        channel_kn = out_channels // K
        channel_k1 = out_channels - (K -1) * channel_kn
        self.perfect_divisor = channel_k1 == channel_kn

        if self.perfect_divisor:
            self.conv_kn = conv1x1(in_channels, channel_kn, stride)
        else:
            self.conv_kn = conv1x1(in_channels, channel_kn, stride)
            self.conv_k1 = conv1x1(in_channels, channel_k1, stride)

        self.layers = nn.ModuleList()
        for k in range(1, K+1):
            dt = 2**(k-1)       # dilation
            channel = channel_k1 if k == 1 else channel_kn
            self.layers.append(ConvBNAct(channel, channel, ks, 1, dt, act_type=act_type))

    def forward(self, x):
        if self.use_skip:
            residual = x

        transform_feats = []
        if self.perfect_divisor:
            x = self.conv_kn(x)     # Reduce
            for i in range(self.K):
                transform_feats.append(self.layers[i](x))   # Split --> Transform

            for j in range(1, self.K):
                transform_feats[j] += transform_feats[j-1]      # Merge: Sum
        else:
            x1 = self.conv_k1(x)    # Reduce
            xn = self.conv_kn(x)    # Reduce
            transform_feats.append(self.layers[0](x1))      # Split --> Transform
            for i in range(1, self.K):
                transform_feats.append(self.layers[i](xn))   # Split --> Transform

            for j in range(2, self.K):
                transform_feats[j] += transform_feats[j-1]      # Merge: Sum

        x = torch.cat(transform_feats, dim=1)               # Merge: Concat

        if self.use_skip:
            x += residual

        return x

HFF 特性

虽然将扩张卷积的输出拼接在一起会给 ESP 模块带来一个较大的有效感受野,但也会引入不必要的棋盘或网格假象,如下图所示。

ESPNet

上图(a)举例说明一个网格伪像,其中单个活动像素(红色)与膨胀率 r = 2 的 3×3 膨胀卷积核卷积。

上图(b)具有和不具有层次特征融合(Hierarchical feature fusion,HFF)的 ESP 模块特征图可视化。ESP 中的 HFF 消除了网格伪影。彩色观看效果最佳。

为了解决 ESP 中的网格问题,使用不同膨胀率的核获得的特征映射在拼接之前会进行层次化添加(上图 b 中的 HFF)。该解决方案简单有效,且不会增加 ESP 模块的复杂性,这与现有方法不同,现有方法通过使用膨胀率较小的卷积核学习更多参数来消除网格误差[Dilated residual networks,Understanding convolution for semantic segmentation]。为了改善网络内部的梯度流动,ESP 模块的输入和输出特征映射使用元素求和[Deep residual learning for image recognition]进行组合。

网络结构与实现

ESPNet 使用 ESP 模块学习卷积核以及下采样操作,除了第一层是标准的大步卷积。所有层(卷积和 ESP 模块)后面都有一个批归一化和一个 PReLU 非线性,除了最后一个点卷积,它既没有批归一化,也没有非线性。最后一层输入 softmax 进行像素级分类。

ESPNet 的不同变体如下图所示。第一个变体,ESPNet-A(图 a),是一种标准网络,它以 RGB 图像作为输入,并使用 ESP 模块学习不同空间层次的表示,以产生一个分割掩码。第二种 ESP - b(图 b)通过在之前的跨步 ESP 模块和之前的 ESP 模块之间共享特征映射,改善了 ESPNet-A 内部的信息流。第三种变体,ESPNet-C(图 c),加强了 ESPNet-B 内部的输入图像,以进一步改善信息的流动。这三种变量产生的输出的空间维度是输入图像的 1 / 8。第四种变体,ESPNet(图 d),在 ESPNet- c 中添加了一个轻量级解码器(使用 reduceupsample-merge 的原理构建),输出与输入图像相同空间分辨率的分割 mask。

ESPNet

从 ESPNet- a 到 ESPNet 的路径。红色和绿色色框分别代表负责下采样和上采样操作的模块。空间级别的 l 在(a)中的每个模块的左侧。本文将每个模块表示为(#输入通道,#输出通道)。这里,conv-n 表示 n × n 卷积。

为了在不改变网络拓扑结构的情况下构建具有较深计算效率的边缘设备网络,超参数α控制网络的深度;ESP 模块在空间层次 l 上重复 $α_{l} $ 次。在更高的空间层次(l = 0 和 l = 1),cnn 需要更多的内存,因为这些层次的特征图的空间维数较高。为了节省内存,ESP 和卷积模块都不会在这些空间级别上重复。

ESPNet V2 模型

ESPNet V2:是由 ESPNet V1 改进来的,一种轻量级、能耗高效、通用的卷积神经网络,利用分组卷积核深度空洞分离卷积学习巨大有效感受野,进一步降低浮点计算量和参数量。同时在图像分类、目标检测、语义分割等任务上检验了模型效果。

ESPNet V2 与 V1 版本相比,其特点如下:

  1. 将原来 ESPNet 的 point-wise convolutions 替换为 group point-wise convolutions;

  2. 将原来 ESPNet 的 dilated convolutions 替换为 depth-wise dilated convolution;

  3. HFF 加在 depth-wise dilated separable convolutions 和 point-wise (or 1 × 1)卷积之间,去除 gridding artifacts;

  4. 使用 group point-wise convolution 替换 K 个 point-wise convolutions;

  5. 加入平均池化(average pooling ),将输入图片信息加入 EESP 中;

  6. 使用级联(concatenation)取代对应元素加法操作(element-wise addition operation )

DDConv 模块

深度分离空洞卷积(Depth-wise dilated separable convolution,DDConv)分两步:

  • 对每个输入通道执行空洞率为 r 的 DDConv,从有效感受野学习代表性特征。

  • 标准 1x1 卷积学习 DDConv 输出的线性组合特征。

深度分离空洞卷积与其他卷积的参数量与感受野对比如下表所示。

Convolution type Parameters Eff.receptive field
Standard $n^{2}c\hat{c}$ $n\times n \quad$
Group $\frac{n^{2}c\hat{c}}{g}$ $n\times n \quad$
Depth-wise separable $n^{2}c+c\hat{c}$ $n\times n \quad$
Depth-wise dilated separable $n^{2}c+c\hat{c}$ $n_{r}\times n_{r} \quad$

EESP 模块

EESP 模块结构如下图,图 b 中相比于 ESPNet,输入层采用分组卷积,DDConv+Conv1x1 取代标准空洞卷积,依然采用 HFF 的融合方式,(c)是(b)的等价模式。当输入通道数 M=240,g=K=4, d=M/K=60,EESP 比 ESP 少 7 倍的参数。

ESPNet

描述了一个新的网络模块 EESP,它利用深度可分离扩张和组逐点卷积设计,专为边缘设备而设计。该模块受 ESPNet 架构的启发,基于 ESP 模块构建,使用了减少-分割-变换-合并的策略。通过组逐点和深度可分离扩张卷积,该模块的计算复杂度得到了显著的降低。进一步,描述了一种带有捷径连接到输入图像的分层 EESP 模块,以更有效地学习多尺度的表示。

如上图中 b 所示,能够降低 $\frac{Md+n^{2}d^{2}K}{\frac{Md}{g}+(n^{2}+d)dK}$ 倍计算复杂度,K 为空洞卷积金字塔层数。考虑到单独计算 K 个 point-wise 卷积等同于单个分组数为 K 的 point-wise 分组卷积,而分组卷积的在实现上更高效,于是改进为上图 c 的最终结构。

class EESP(nn.Module):
    '''
       按照 REDUCE ---> SPLIT ---> TRANSFORM --> MERGE 
    '''

    def __init__(self, nIn, nOut, stride=1, k=4, r_lim=7, down_method='esp'):                   
        super().__init__()
        self.stride = stride
        n = int(nOut / k)
        n1 = nOut - (k - 1) * n
        assert down_method in ['avg', 'esp']
        assert n == n1, "n(={}) and n1(={}) should be equal for Depth-wise Convolution ".format(n, n1)

        self.proj_1x1 = CBR(nIn, n, 1, stride=1, groups=k)

        #3x3 核的膨胀率和感受野之间的映射
        map_receptive_ksize = {
   3: 1, 5: 2, 7: 3, 9: 4, 11: 5, 13: 6, 15: 7, 17: 8}
        self.k_sizes = list()
        for i in range(k):
            ksize = int(3 + 2 * i)
            # 达到感受野极限后,回落到 3x3,膨胀率为 1 的基础卷积
            ksize = ksize if ksize <= r_lim else 3
            self.k_sizes.append(ksize)
        #根据感受野对这些核大小进行排序(升序)
        #这使我们能够忽略分层中具有相同有效感受野的核(在我们的例子中为 3×3)
        # 特征融合,因为 3x3 感受野的核不具有网格伪影。
        self.k_sizes.sort()
        self.spp_dw = nn.ModuleList()

        for i in range(k):
            d_rate = map_receptive_ksize[self.k_sizes[i]]
            self.spp_dw.append(CDilated(n, n, kSize=3, stride=stride, groups=n, d=d_rate))

        self.conv_1x1_exp = CB(nOut, nOut, 1, 1, groups=k)
        self.br_after_cat = BR(nOut)
        self.module_act = nn.PReLU(nOut)
        self.downAvg = True if down_method == 'avg' else False

    def forward(self, input):

        # Reduce --> 将高维特征映射投影到低维空间
        output1 = self.proj_1x1(input)
        output = [self.spp_dw[0](output1)]
        # 计算每个分支的输出并分层融合它们
        # i.e. Split --> Transform --> HFF
        for k in range(1, len(self.spp_dw)):
            out_k = self.spp_dw[k](output1)
            # HFF
            #我们不组合具有相同感受野的分支(在我们的例子中是 3x3)

            out_k = out_k + output[k - 1]
            #融合后应用批量定额,然后添加到列表中
            output.append(out_k)
        # Merge
        expanded = self.conv_1x1_exp( 
            self.br_after_cat( 
                torch.cat(output, 1) 
            )
        )
        del output
        # 如果下采样,则返回连接的向量
        # 因为下采样功能会将其与 avg 合并。合并特征图,然后对其进行阈值处理
        if self.stride == 2 and self.downAvg:
            return expanded

        # 如果输入向量和连接向量的维数相同,则将它们相加 (RESIDUAL LINK)
        if expanded.size() == input.size():
            expanded = expanded + input

        # 使用激活函数对特征图进行阈值处理 (PReLU in this case)
        return self.module_act(expanded)

Strided EESP 模块

为了在多尺度下能够有效地学习特征,对上图 1c 的网络做了四点改动(如下图所示):

1.对 DDConv 添加 stride 属性。

2.右边的 shortcut 中带了平均池化操作,实现维度匹配。

3.将相加的特征融合方式替换为 concat 形式,增加特征的维度。

4.融合原始输入图像的下采样信息,使得特征信息更加丰富。具体做法是先将图像下采样到与特征图的尺寸相同的尺寸,然后使用第一个卷积,一个标准的 3×3 卷积,用于学习空间表示。再使用第二个卷积,一个逐点卷积,用于学习输入之间的线性组合,并将其投影到高维空间。

05ESPNet05.png


class DownSampler(nn.Module):
    '''
   具有两个并行分支的下采样功能:平均池和步长为 2 的 EESP 块。然后,使用激活函数将这些分支的输出特征图连接起来并进行阈值处理,以产生最终输出。
    '''

    def __init__(self, nin, nout, k=4, r_lim=9, reinf=True):

        super().__init__()
        nout_new = nout - nin
        self.eesp = EESP(nin, nout_new, stride=2, k=k, r_lim=r_lim, down_method='avg')
        self.avg = nn.AvgPool2d(kernel_size=3, padding=1, stride=2)
        if reinf:
            self.inp_reinf = nn.Sequential(
                CBR(config_inp_reinf, config_inp_reinf, 3, 1),
                CB(config_inp_reinf, nout, 1, 1)
            )
        self.act =  nn.PReLU(nout)

    def forward(self, input, input2=None):

        avg_out = self.avg(input)
        eesp_out = self.eesp(input)
        output = torch.cat([avg_out, eesp_out], 1)
        if input2 is not None:

            w1 = avg_out.size(2)
            while True:
                input2 = F.avg_pool2d(input2, kernel_size=3, padding=1, stride=2)
                w2 = input2.size(2)
                if w2 == w1:
                    break
            output = output + self.inp_reinf(input2)

        return self.act(output)

如果您想了解更多AI知识,与AI专业人士交流,请立即访问昇腾社区官方网站https://www.hiascend.com/或者深入研读《AI系统:原理与架构》一书,这里汇聚了海量的AI学习资源和实践课程,为您的AI技术成长提供强劲动力。不仅如此,您还有机会投身于全国昇腾AI创新大赛和昇腾AI开发者创享日等盛事,发现AI世界的无限奥秘~

目录
相关文章
|
4天前
|
存储 编解码 人工智能
【AI系统】FBNet 系列
本文介绍了FBNet系列的三种版本,从FBNetV1基于NAS的轻量级网络设计,到FBNetV2通过DMaskingNAS增加搜索空间,再到FBNetV3联合搜索网络结构与训练参数,展示了如何利用NAS技术优化网络结构和提升模型性能。文章详细解释了各版本的技术特点和实现方法,为读者提供了深入了解和应用NAS技术的宝贵资料。
37 10
【AI系统】FBNet 系列
|
3天前
|
人工智能 编解码 算法
【AI系统】EfficientFormer 系列
本文介绍了一种名为 EfficientFormer 的轻量化 Transformer 模型,旨在优化移动设备上的推理速度。通过重新设计 ViT 及其变体,特别是针对移动设备的延迟优化,EfficientFormer 引入了维度一致的 Transformer Block,并通过网络模型搜索获得了多个系列的模型。EfficientFormer V2 进一步改进了模型设计,引入细粒度联合搜索策略,优化了延迟和参数量,实现了更高的性能和效率。
27 8
【AI系统】EfficientFormer 系列
|
3天前
|
机器学习/深度学习 人工智能 编解码
【AI系统】MobileFormer
本文介绍了MobileFormer,一种创新的网络结构,通过双线桥将MobileNet的局部特征与Transformer的全局特征相结合,实现了高效且低计算成本的模型设计。MobileFormer使用少量tokens来学习全局先验,从而在保持高性能的同时,显著降低了计算量。通过本文,读者可以深入了解如何有效结合CNN和Transformer的优势,实现模型的轻量化。
23 7
【AI系统】MobileFormer
|
4天前
|
机器学习/深度学习 人工智能 编解码
【AI系统】GhostNet 系列
本文介绍了GhostNet系列网络,重点讲解了GhostNet V1和V2的改进。V1提出了Ghost Module,通过廉价操作生成更多特征图,构建轻量级网络。V2在此基础上引入了解耦全连接注意力(DFC)机制,增强了模型捕捉长距离依赖的能力,同时保持了高效的计算性能,特别适合移动设备。文章详细对比了V2与V1的区别,包括结构改进和性能提升。
28 4
【AI系统】GhostNet 系列
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
影中的ai技术
【6月更文挑战第27天】电影中的ai技术
265 65
|
3天前
|
机器学习/深度学习 人工智能 算法
【AI系统】AI 框架基础介绍
本文介绍了AI算法、神经网络及AI框架的基础概念,探讨了神经网络的作用、训练目的以及AI框架如何简化模型设计、训练与验证过程。文章还概述了AI框架的发展历程和技术演进,强调了国内外主要AI框架的特点及其对AI技术发展的推动作用。
21 2
【AI系统】AI 框架基础介绍
|
9天前
|
机器学习/深度学习 人工智能 编译器
【AI系统】AI 芯片的思考
为了应对数据中心算力需求,谷歌自2014年起研发TPU,专为深度学习设计的硬件加速器。TPU加速了谷歌的机器学习任务,尤其在大模型训练和推理方面表现突出。大卫·帕特森教授加入谷歌TPU团队后,分享了TPU发展历程及技术心得,强调了AI模型对内存和算力需求的快速增长、模型结构的快速演变、生产部署中的多租户需求、SRAM与DRAM的权衡、内存优化的重要性、DSA的专业与灵活性、半导体供应链选型、编译器优化及AI应用兼容性等方面的关键挑战与解决方案。
25 2
|
12天前
|
人工智能 atlas 开发工具
【AI系统】昇腾 AI 架构介绍
昇腾计算产业基于华为昇腾系列处理器,涵盖硬件、基础软件、应用使能等,构建全栈AI计算基础设施。华为通过开放硬件、开源软件,支持多框架,推动AI技术在端、边、云的广泛应用,促进AI产业生态繁荣。
31 1
|
15天前
|
机器学习/深度学习 人工智能 算法
【AI系统】AI系统架构的组成
本文概述了AI系统的组成,从AI训练与推理框架、AI编译与计算架构到AI硬件与体系结构,详细介绍了各层的功能与技术细节。同时,探讨了AI系统生态的广泛领域,包括核心系统软硬件、AI算法和框架以及更广泛的生态组成部分,强调了在模型训练、推理、安全与隐私等方面的技术挑战与解决方案。
31 2
|
15天前
|
机器学习/深度学习 人工智能 自然语言处理
【AI系统】AI的领域、场景与行业应用
本文概述了AI的历史、现状及发展趋势,涵盖AI系统的初步设计原则,并深入探讨了AI在计算机视觉、自然语言处理和音频处理三个领域的具体应用。同时,文中还介绍了AI在金融、医疗、教育、互联网及自动驾驶等行业中的广泛应用,强调了AI基础设施的重要性及其对企业竞争力的影响。通过阅读本文,读者不仅可以获得系统的AI知识,还能激发对AI系统研究的兴趣,掌握相关的设计原则与方法。
44 1