【AI系统】MobileFormer

简介: 本文介绍了MobileFormer,一种创新的网络结构,通过双线桥将MobileNet的局部特征与Transformer的全局特征相结合,实现了高效且低计算成本的模型设计。MobileFormer使用少量tokens来学习全局先验,从而在保持高性能的同时,显著降低了计算量。通过本文,读者可以深入了解如何有效结合CNN和Transformer的优势,实现模型的轻量化。

在本文中,将介绍一种新的网络-MobileFormer,它实现了 Transformer 全局特征与 CNN 局部特征的融合,在较低的成本内,创造一个高效的网络。通过本文,让大家去了解如何将 CNN 与 Transformer 更好的结合起来,同时实现模型的轻量化。

MobileFormer

MobileFormer:一种通过双线桥将 MobileNet 和 Transformer 并行的结构。这种方式融合了 MobileNet 局部性表达能力和 Transformer 全局表达能力的优点,这个桥能将局部性和全局性双向融合。和现有 Transformer 不同,Mobile-Former 使用很少的 tokens(例如 6 个或者更少)随机初始化学习全局先验,计算量更小。

并行结构

Mobile-Former 将 MobileNet 和 Transformer 并行化,并通过双向交叉注意力连接(下见图)。Mobile(指 MobileNet)采用图像作为输入(XRHW×3),并应用反向瓶颈块提取局部特征。Former(指 Transformers)将可学习的参数(或 tokens)作为输入,表示为 ZRM×d,其中 M 和 d 分别是 tokens 的数量和维度,这些 tokens 随机初始化。与视觉 Transformer(ViT)不同,其中 tokens 将局部图像 patch 线性化,Former 的 tokens 明显较少(M≤6),每个代表图像的全局先验知识。这使得计算成本大大降低。

image

低成本双线桥

Mobile 和 Former 通过双线桥将局部和全局特征双向融合。这两个方向分别表示为 Mobile→Former 和 Mobile←Former。我们提出了一种轻量级的交叉注意力模型,其中映射(WQ,WK,WV)从 Mobile 中移除,以节省计算,但在 Former 中保留。在通道数较少的 Mobile 瓶颈处计算交叉注意力。具体而言,从局部特征图 X 到全局 tokens Z 的轻量级交叉注意力计算如下:

AX>Z=[Attn(~ziWQi,~xi,~xi)]i=1:hWo

其中局部特征 X 和全局 tokens Z 被拆分进入 h 个头,即 X=[~x1...~xh],Z=[~z1...~zh] 表示多头注意力。第 i 个头的拆分 ~z1RM×dh 与第 i 个 token ~z1Rd 不同。WQi 是第 i 个头的查询映射矩阵。WO 用于将多个头组合在一起。Attn(Q,K,V)是查询 Q、键 K 和值 V 的标准注意力函数,即:

softmax(QKTdk)

其中 [.]1:h 表示将 h 个元素 concat 到一起。需要注意的是,键和值的映射矩阵从 Mobile 中移除,而查询的映射矩阵 WQi 在 Former 中保留。类似地从全局到局部的交叉注意力计算如下:

AZ>X=[Attn(~xi,~ziWKi,~ziWVi)]i=1:h

其中 WKiWVi 分别是 Former 中键和值的映射矩阵。而查询的映射矩阵从 Mobile 中移除。

Mobile-Former 块

Mobile-Former 由 Mobile-Former 块组成。每个块包含四部分:Mobile 子块、Former 子块以及双向交叉注意力 Mobile←Former 和 Mobile→Former(如下图所示)。

image

输入和输出:Mobile-Former 块有两个输入:(a) 局部特征图 XRHW×C,为 C 通道、高度 H 和宽度 W,以及(b) 全局 tokens ZRM×d,其中 M 和 d 是分别是 tokens 的数量和维度,M 和 d 在所有块中一样。Mobile-Former 块输出更新的局部特征图 X 和全局 tokensZ,用作下一个块的输入。

Mobile 子块:如上图所示,Mobile 子块将特征图 X 作为输入,并将其输出作为 Mobile←Former 的输入。这和反向瓶颈块略有不同,其用动态 ReLU 替换 ReLU 作为激活函数。不同于原始的动态 ReLU,在平均池化特征图上应用两个 MLP 以生成参数。我们从 Former 的第一个全局 tokens 的输出 z1 应用两个 MLP 层(上图中的θ)保存平均池化。其中所有块的 depth-wise 卷积的核大小为 3×3。

class Mobile(nn.Module):

    def __init__(self, in_channel, expand_size, out_channel, token_demension, kernel_size=3, stride=1, k=2):
        super(Mobile, self).__init__()
        self.in_channel, self.expand_size, self.out_channel = in_channel, expand_size, out_channel
        self.token_demension, self.kernel_size, self.stride, self.k = token_demension, kernel_size, stride, k

        if stride == 2:
            self.strided_conv = nn.Sequential(
                nn.Conv2d(self.in_channel, self.expand_size, kernel_size=3, stride=2, padding=int(self.kernel_size // 2), groups=self.in_channel).cuda(),
                nn.BatchNorm2d(self.expand_size).cuda(),
                nn.ReLU6(inplace=True).cuda()
            )
            self.conv1 = nn.Conv2d(self.expand_size, self.in_channel, kernel_size=1, stride=1).cuda()
            self.bn1 = nn.BatchNorm2d(self.in_channel).cuda()
            self.ac1 = DynamicReLU(self.in_channel, self.token_demension, k=self.k).cuda()      
            self.conv2 = nn.Conv2d(self.in_channel, self.expand_size, kernel_size=3, stride=1, padding=1, groups=self.in_channel).cuda()
            self.bn2 = nn.BatchNorm2d(self.expand_size).cuda()
            self.ac2 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()          
            self.conv3 = nn.Conv2d(self.expand_size, self.out_channel, kernel_size=1, stride=1).cuda()
            self.bn3 = nn.BatchNorm2d(self.out_channel).cuda()
        else:
            self.conv1 = nn.Conv2d(self.in_channel, self.expand_size, kernel_size=1, stride=1).cuda()
            self.bn1 = nn.BatchNorm2d(self.expand_size).cuda()
            self.ac1 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()      
            self.conv2 = nn.Conv2d(self.expand_size, self.expand_size, kernel_size=3, stride=1, padding=1, groups=self.expand_size).cuda()
            self.bn2 = nn.BatchNorm2d(self.expand_size).cuda()
            self.ac2 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()          
            self.conv3 = nn.Conv2d(self.expand_size, self.out_channel, kernel_size=1, stride=1).cuda()
            self.bn3 = nn.BatchNorm2d(self.out_channel).cuda()

    def forward(self, x, first_token):
        if self.stride == 2:
            x = self.strided_conv(x)
        x = self.bn1(self.conv1(x))
        x = self.ac1(x, first_token)
        x = self.bn2(self.conv2(x))
        x = self.ac2(x, first_token)
        return self.bn3(self.conv3(x))
AI 代码解读

Former 子块:Former 子块是一个标准的 Transformer 块,包括一个多头注意力(MHA)和一个前馈网络(FFN)。在 FFN 中,膨胀率为 2(代替 4)。使用 post 层归一化。Former 在 Mobile→Former 和 Mobile←Former 之间处理(见上图)。

class Former(nn.Module):

    def __init__(self, head, d_model, expand_ratio=2):
        super(Former, self).__init__()
        self.d_model = d_model
        self.expand_ratio = expand_ratio
        self.eps = 1e-10
        self.head = head
        assert self.d_model % self.head == 0
        self.d_per_head = self.d_model // self.head

        self.QVK = MLP([self.d_model, self.d_model * 3], bn=False).cuda()
        self.Q_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()
        self.K_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()
        self.V_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()
        self.heads_to_o = MLP([self.d_model, self.d_model], bn=False).cuda()
        self.norm = nn.LayerNorm(self.d_model).cuda()
        self.mlp = MLP([self.d_model, self.expand_ratio * self.d_model, self.d_model], bn=False).cuda()
        self.mlp_norm = nn.LayerNorm(self.d_model).cuda()

    def forward(self, x):
        QVK = self.QVK(x)
        Q = QVK[:, :, 0: self.d_model]
        Q = rearrange(self.Q_to_heads(Q), 'n m ( d h ) -> n m d h', h=self.head)  
        K = QVK[:, :, self.d_model: 2 * self.d_model]
        K = rearrange(self.K_to_heads(K), 'n m ( d h ) -> n m d h', h=self.head)   
        V = QVK[:, :, 2 * self.d_model: 3 * self.d_model]
        V = rearrange(self.V_to_heads(V), 'n m ( d h ) -> n m d h', h=self.head)  
        scores = torch.einsum('nqdh, nkdh -> nhqk', Q, K) / (np.sqrt(self.d_per_head) + self.eps)   
        scores_map = F.softmax(scores, dim=-1)
        v_heads = torch.einsum('nkdh, nhqk -> nhqd', V, scores_map) 
        v_heads = rearrange(v_heads, 'n h q d -> n q ( h d )')
        attout = self.heads_to_o(v_heads)
        attout = self.norm(attout)  
        attout = self.mlp(attout)
        attout = self.mlp_norm(attout)  
        return attout
AI 代码解读

Mobile→Former:文章提出的轻量级交叉注意力(式 1)用于将局部特征 X 融合到全局特征 tokens Z。与标准注意力相比,映射矩阵的键 WK 和值 WV(在局部特征 X 上)被移除以节省计算(见上图)。


class Mobile_Former(nn.Module):
    '''局部特征 -> 全局特征'''
    def __init__(self, d_model, in_channel):
        super(Mobile_Former, self).__init__()
        self.d_model, self.in_channel = d_model, in_channel

        self.project_Q = nn.Linear(self.d_model, self.in_channel).cuda()
        self.unproject = nn.Linear(self.in_channel, self.d_model).cuda()
        self.eps = 1e-10
        self.shortcut = nn.Sequential().cuda()

    def forward(self, local_feature, x):
        _, c, _, _ = local_feature.shape
        local_feature = rearrange(local_feature, 'n c h w -> n ( h w ) c')   
        project_Q = self.project_Q(x)   
        scores = torch.einsum('nmc , nlc -> nml', project_Q, local_feature) * (c ** -0.5)
        scores_map = F.softmax(scores, dim=-1)  
        fushion = torch.einsum('nml, nlc -> nmc', scores_map, local_feature)
        unproject = self.unproject(fushion) 
        return unproject + self.shortcut(x)
AI 代码解读

Mobile-Former:这里的交叉注意力(式 2)与 Mobile→Former 的方向相反,其将全局 tokens 融入本地特征。局部特征是查询,全局 tokens 是键和值。因此,我们保留键 WK 和值 WV 中的映射矩阵,但移除查询 WQ 的映射矩阵以节省计算,如上图所示。

计算复杂度:Mobile-Former 块的四个核心部分具有不同的计算成本。给定输入大小为 HW×C 的特征图,以及尺寸为 d 的 M 个全局 tokens,Mobile 占据了大部分的计算量 O(HWC2)。Former 和双线桥是重量级的,占据不到总计算成本的 20%。具体而言,Former 的自注意力和 FFN 具有复杂度 O(M2d+Md2)。Mobile→Former 和 Mobile←Former 共享交叉注意力的复杂度 O(MHWC+MdC)

class Former_Mobile(nn.Module):
    '''全局特征 -> 局部特征'''
    def __init__(self, d_model, in_channel):
        super(Former_Mobile, self).__init__()
        self.d_model, self.in_channel = d_model, in_channel

        self.project_KV = MLP([self.d_model, 2 * self.in_channel], bn=False).cuda()
        self.shortcut = nn.Sequential().cuda()

    def forward(self, x, global_feature):
        res = self.shortcut(x)
        n, c, h, w = x.shape
        project_kv = self.project_KV(global_feature)
        K = project_kv[:, :, 0 : c]  
        V = project_kv[:, :, c : ]  
        x = rearrange(x, 'n c h w -> n ( h w ) c') 
        scores = torch.einsum('nqc, nkc -> nqk', x, K) 
        scores_map = F.softmax(scores, dim=-1) 
        v_agg = torch.einsum('nqk, nkc -> nqc', scores_map, V)  
        feature = rearrange(v_agg, 'n ( h w ) c -> n c h w', h=h)
        return feature + res
AI 代码解读

网络结构

一个 Mobile-Former 架构,图像大小为 224×224,294M FLOPs,以不同的输入分辨率堆叠 11 个 Mobile-Former 块。所有块都有 6 个维度为 192 的全局 tokens。它以一个 3×3 的卷积作为 stem 和第一阶段的轻量瓶颈块,首先膨胀,然后通过 3×3 depth-wise 卷积和 point-wise 卷积压缩通道数。第 2-5 阶段包括 Mobile-Former 块。每个阶段的下采样,表示为 Mobile-Former 分类头在局部特征应用平均池化,首先和全局 tokens concat 到一起,然后经过两个全连接层,中间是 h-swish 激活函数。Mobile-Former 有七种模型,计算成本从 26M 到 508M FLOPs。它们的结构相似,但宽度和高度不同。

class MobileFormerBlock(nn.Module):
    def __init__(self, in_channel, expand_size, out_channel, d_model, stride=1, k=2, head=8, expand_ratio=2):
        super(MobileFormerBlock, self).__init__()

        self.in_channel, self.expand_size, self.out_channel = in_channel, expand_size, out_channel
        self.d_model, self.stride, self.k, self.head, self.expand_ratio = d_model, stride, k, head, expand_ratio

        self.mobile = Mobile(self.in_channel, self.expand_size, self.out_channel, self.d_model, kernel_size=3, stride=self.stride, k=self.k).cuda()
        self.former = Former(self.head, self.d_model, expand_ratio=self.expand_ratio).cuda()
        self.mobile_former = Mobile_Former(self.d_model, self.in_channel).cuda()
        self.former_mobile = Former_Mobile(self.d_model, self.out_channel).cuda()

    def forward(self, local_feature, global_feature):
        z_hidden = self.mobile_former(local_feature, global_feature)
        z_out = self.former(z_hidden)
        x_hidden = self.mobile(local_feature, z_out[:, 0, :])
        x_out = self.former_mobile(x_hidden, z_out)
        return x_out, z_out
AI 代码解读

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

目录
打赏
0
7
7
0
144
分享
相关文章
使用AI进行系统调优:给系统装上“智能大脑”
使用AI进行系统调优:给系统装上“智能大脑”
59 10
“AI医生”入驻运维现场:聊聊系统健康检查的新姿势
“AI医生”入驻运维现场:聊聊系统健康检查的新姿势
137 78
Dify-Plus:企业级AI管理核弹!开源方案吊打SaaS,额度+密钥+鉴权系统全面集成
Dify-Plus 是基于 Dify 二次开发的企业级增强版项目,新增用户额度、密钥管理、Web 登录鉴权等功能,优化权限管理,适合企业场景使用。
161 3
Dify-Plus:企业级AI管理核弹!开源方案吊打SaaS,额度+密钥+鉴权系统全面集成
Agent TARS:一键让AI托管电脑!字节开源PC端多模态AI助手,无缝集成浏览器与系统操作
Agent TARS 是一款开源的多模态AI助手,能够通过视觉解析网页并无缝集成命令行和文件系统,帮助用户高效完成复杂任务。
2195 3
Agent TARS:一键让AI托管电脑!字节开源PC端多模态AI助手,无缝集成浏览器与系统操作
对话即服务:Spring Boot整合MCP让你的CRUD系统秒变AI助手
本文介绍了如何通过Model Context Protocol (MCP) 协议将传统Spring Boot服务改造为支持AI交互的智能系统。MCP作为“万能适配器”,让AI以统一方式与多种服务和数据源交互,降低开发复杂度。文章以图书管理服务为例,详细说明了引入依赖、配置MCP服务器、改造服务方法(注解方式或函数Bean方式)及接口测试的全流程。最终实现用户通过自然语言查询数据库的功能,展示了MCP在简化AI集成、提升系统易用性方面的价值。未来,“对话即服务”有望成为主流开发范式。
570 3
AI技术如何重塑客服系统?解析合力亿捷AI智能客服系统实践案例
本文探讨了人工智能技术在客服系统中的应用,涵盖技术架构、关键技术和优化策略。通过感知层、认知层、决策层和执行层的协同工作,结合自然语言处理、知识库构建和多模态交互技术,合力亿捷客服系统实现了智能化服务。文章还提出了用户体验优化、服务质量提升和系统性能改进的方法,并展望了未来发展方向,强调其在客户服务领域的核心价值与潜力。
51 6
AI对话网站一键生成系统源码
可以添加进自己的工具箱,也可以嵌入自己博客的页面中,引流效果杠杠的,新拟态设计风格,有能力的大佬可以进行二开,仅提供学习,用户可输入网站名称、AI默认的开场白、AI头像昵称、AI网站中引流的你的网站等等内容,所有生成的网页全部保存到你的服务器上
71 27
AI对话网站一键生成系统源码
凌晨急诊室诞生的疫苗系统:一个宝妈的AI破局之路
本文分享了一位妈妈在急诊室经历后,将技术与母爱结合的心路历程。从凌晨抱着高烧儿子就医,同时处理工作告警的崩溃时刻,到意识到妈妈和程序员都是“运维工程师”,作者逐步构建了宝宝疫苗管理系统。文章介绍了系统从静态命令行工具升级为动态智能预警系统的全过程,包括环境搭建、核心代码解析及家庭协同功能实现,并总结了碎片时间开发法与防坑指南。最终,作者通过技术赋予母爱温度,为其他妈妈提供了实用资源包,展现了代码背后的人文关怀。
64 5
【最佳实践系列】AI程序员让我变成全栈:基于阿里云百炼DeepSeek的跨语言公告系统实战
本文介绍了如何在Java开发中通过跨语言编程,利用阿里云百炼服务平台的DeepSeek大模型生成公告内容,并将其嵌入前端页面。
算法系统协同优化,vivo与港中文推出BlueLM-V-3B,手机秒变多模态AI专家
BlueLM-V-3B是由vivo与香港中文大学共同研发的多模态大型语言模型,专为移动设备优化。它通过算法和系统协同优化,实现了高效部署和快速生成速度(24.4 token/s),并在OpenCompass基准测试中取得优异成绩(66.1分)。模型小巧,语言部分含27亿参数,视觉编码器含4000万参数,适合移动设备使用。尽管如此,低端设备可能仍面临资源压力,实际应用效果需进一步验证。论文链接:https://arxiv.org/abs/2411.10640。
43 9

热门文章

最新文章