自适应网站价格,安徽茶叶网站建设,wordpress 卢松松,东莞龙舟制作技艺MobileFormer
在本文中#xff0c;将介绍一种新的网络-MobileFormer#xff0c;它实现了 Transformer 全局特征与 CNN 局部特征的融合#xff0c;在较低的成本内#xff0c;创造一个高效的网络。通过本节#xff0c;让大家去了解如何将 CNN 与 Transformer 更好的结合起来…MobileFormer
在本文中将介绍一种新的网络-MobileFormer它实现了 Transformer 全局特征与 CNN 局部特征的融合在较低的成本内创造一个高效的网络。通过本节让大家去了解如何将 CNN 与 Transformer 更好的结合起来同时实现模型的轻量化。
MobileFormer
MobileFormer:一种通过双线桥将 MobileNet 和 Transformer 并行的结构。这种方式融合了 MobileNet 局部性表达能力和 Transformer 全局表达能力的优点这个桥能将局部性和全局性双向融合。和现有 Transformer 不同Mobile-Former 使用很少的 tokens(例如 6 个或者更少)随机初始化学习全局先验计算量更小。
并行结构
Mobile-Former 将 MobileNet 和 Transformer 并行化并通过双向交叉注意力连接下见图。Mobile指 MobileNet采用图像作为输入 X ∈ R H W × 3 X\in R^{HW \times 3} X∈RHW×3并应用反向瓶颈块提取局部特征。Former指 Transformers将可学习的参数或 tokens作为输入表示为 Z ∈ R M × d Z\in R^{M\times d} Z∈RM×d其中 M 和 d 分别是 tokens 的数量和维度这些 tokens 随机初始化。与视觉 TransformerViT不同其中 tokens 将局部图像 patch 线性化Former 的 tokens 明显较少M≤6每个代表图像的全局先验知识。这使得计算成本大大降低。 低成本双线桥
Mobile 和 Former 通过双线桥将局部和全局特征双向融合。这两个方向分别表示为 Mobile→Former 和 Mobile←Former。我们提出了一种轻量级的交叉注意力模型其中映射 W Q W^{Q} WQ, W K W^{K} WK, W V W^{V} WV)从 Mobile 中移除以节省计算但在 Former 中保留。在通道数较少的 Mobile 瓶颈处计算交叉注意力。具体而言从局部特征图 X 到全局 tokens Z 的轻量级交叉注意力计算如下 A X − Z [ A t t n ( z i ~ W i Q , x i ~ , x i ~ ) ] i 1 : h W o (1) A_{X-Z} [Attn(\widetilde{z_{i}}W_{i}^{Q},\widetilde{x_{i}},\widetilde{x_{i}})]_{i1:h}W^{o}\tag{1} AX−Z[Attn(zi WiQ,xi ,xi )]i1:hWo(1)
其中局部特征 X 和全局 tokens Z 被拆分进入 h 个头即 X [ x 1 ~ . . . x h ~ ] , Z [ z 1 ~ . . . z h ~ ] X[\widetilde{x_{1}}...\widetilde{x_{h}}],Z[\widetilde{z_{1}}...\widetilde{z_{h}}] X[x1 ...xh ],Z[z1 ...zh ] 表示多头注意力。第 i 个头的拆分 z 1 ~ ∈ R M × d h \widetilde{z_{1}}\in R^{M \times \frac {d}{h} } z1 ∈RM×hd 与第 i 个 token z 1 ~ ∈ R d \widetilde{z_{1}}\in R^{d} z1 ∈Rd 不同。 W i Q W_{i}^{Q} WiQ 是第 i 个头的查询映射矩阵。 W O W^{O} WO 用于将多个头组合在一起。Attn(Q,K,V)是查询 Q、键 K 和值 V 的标准注意力函数即 s o f t m a x ( Q K T d k ) softmax(\frac{QK^{T}}{\sqrt{d_{k}}}) softmax(dk QKT)
其中 [ . ] 1 : h [.]_{1:h} [.]1:h 表示将 h 个元素 concat 到一起。需要注意的是键和值的映射矩阵从 Mobile 中移除而查询的映射矩阵 W i Q W_{i}^{Q} WiQ 在 Former 中保留。类似地从全局到局部的交叉注意力计算如下 A Z − X [ A t t n ( x i ~ , z i ~ ⊙ W i K , z i ~ ⊙ W i V ) ] i 1 : h (2) A_{Z-X} [Attn(\widetilde{x_{i}},\widetilde{z_{i}}\odot W_{i}^{K},\widetilde{z_{i}}\odot W_{i}^{V})]_{i1:h}\tag{2} AZ−X[Attn(xi ,zi ⊙WiK,zi ⊙WiV)]i1:h(2)
其中 W i K W_{i}^{K} WiK 和 W i V W_{i}^{V} WiV 分别是 Former 中键和值的映射矩阵。而查询的映射矩阵从 Mobile 中移除。
Mobile-Former 块
Mobile-Former 由 Mobile-Former 块组成。每个块包含四部分Mobile 子块、Former 子块以及双向交叉注意力 Mobile←Former 和 Mobile→Former如下图所示。 输入和输出Mobile-Former 块有两个输入(a) 局部特征图 X ∈ R H W × C X\in R^{HW\times C} X∈RHW×C为 C 通道、高度 H 和宽度 W以及(b) 全局 tokens Z ∈ R M × d Z\in R^{M\times d} Z∈RM×d其中 M 和 d 是分别是 tokens 的数量和维度M 和 d 在所有块中一样。Mobile-Former 块输出更新的局部特征图 X X X 和全局 tokens Z Z Z用作下一个块的输入。
Mobile 子块如上图所示Mobile 子块将特征图 X X X 作为输入并将其输出作为 Mobile←Former 的输入。这和反向瓶颈块略有不同其用动态 ReLU 替换 ReLU 作为激活函数。不同于原始的动态 ReLU在平均池化特征图上应用两个 MLP 以生成参数。我们从 Former 的第一个全局 tokens 的输出 z 1 ′ z_{1} z1′ 应用两个 MLP 层上图中的θ保存平均池化。其中所有块的 depth-wise 卷积的核大小为 3×3。
class Mobile(nn.Module):def __init__(self, in_channel, expand_size, out_channel, token_demension, kernel_size3, stride1, k2):super(Mobile, self).__init__()self.in_channel, self.expand_size, self.out_channel in_channel, expand_size, out_channelself.token_demension, self.kernel_size, self.stride, self.k token_demension, kernel_size, stride, kif stride 2:self.strided_conv nn.Sequential(nn.Conv2d(self.in_channel, self.expand_size, kernel_size3, stride2, paddingint(self.kernel_size // 2), groupsself.in_channel).cuda(),nn.BatchNorm2d(self.expand_size).cuda(),nn.ReLU6(inplaceTrue).cuda())self.conv1 nn.Conv2d(self.expand_size, self.in_channel, kernel_size1, stride1).cuda()self.bn1 nn.BatchNorm2d(self.in_channel).cuda()self.ac1 DynamicReLU(self.in_channel, self.token_demension, kself.k).cuda() self.conv2 nn.Conv2d(self.in_channel, self.expand_size, kernel_size3, stride1, padding1, groupsself.in_channel).cuda()self.bn2 nn.BatchNorm2d(self.expand_size).cuda()self.ac2 DynamicReLU(self.expand_size, self.token_demension, kself.k).cuda() self.conv3 nn.Conv2d(self.expand_size, self.out_channel, kernel_size1, stride1).cuda()self.bn3 nn.BatchNorm2d(self.out_channel).cuda()else:self.conv1 nn.Conv2d(self.in_channel, self.expand_size, kernel_size1, stride1).cuda()self.bn1 nn.BatchNorm2d(self.expand_size).cuda()self.ac1 DynamicReLU(self.expand_size, self.token_demension, kself.k).cuda() self.conv2 nn.Conv2d(self.expand_size, self.expand_size, kernel_size3, stride1, padding1, groupsself.expand_size).cuda()self.bn2 nn.BatchNorm2d(self.expand_size).cuda()self.ac2 DynamicReLU(self.expand_size, self.token_demension, kself.k).cuda() self.conv3 nn.Conv2d(self.expand_size, self.out_channel, kernel_size1, stride1).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))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_ratio2):super(Former, self).__init__()self.d_model d_modelself.expand_ratio expand_ratioself.eps 1e-10self.head headassert self.d_model % self.head 0self.d_per_head self.d_model // self.headself.QVK MLP([self.d_model, self.d_model * 3], bnFalse).cuda()self.Q_to_heads MLP([self.d_model, self.d_model], bnFalse).cuda()self.K_to_heads MLP([self.d_model, self.d_model], bnFalse).cuda()self.V_to_heads MLP([self.d_model, self.d_model], bnFalse).cuda()self.heads_to_o MLP([self.d_model, self.d_model], bnFalse).cuda()self.norm nn.LayerNorm(self.d_model).cuda()self.mlp MLP([self.d_model, self.expand_ratio * self.d_model, self.d_model], bnFalse).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, hself.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, hself.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, hself.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 Mobile→Former文章提出的轻量级交叉注意力式 1用于将局部特征 X 融合到全局特征 tokens Z。与标准注意力相比映射矩阵的键 W K W^{K} WK 和值 W V W^{V} 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_channelself.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-10self.shortcut nn.Sequential().cuda()def forward(self, local_feature, x):_, c, _, _ local_feature.shapelocal_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)Mobile-Former这里的交叉注意力式 2与 Mobile→Former 的方向相反其将全局 tokens 融入本地特征。局部特征是查询全局 tokens 是键和值。因此我们保留键 W K W^{K} WK 和值 W V W^{V} WV 中的映射矩阵但移除查询 W Q W^{Q} WQ 的映射矩阵以节省计算如上图所示。
计算复杂度Mobile-Former 块的四个核心部分具有不同的计算成本。给定输入大小为 H W × C HW\times C HW×C 的特征图以及尺寸为 d 的 M 个全局 tokensMobile 占据了大部分的计算量 O ( H W C 2 ) O(HWC^{2}) O(HWC2)。Former 和双线桥是重量级的占据不到总计算成本的 20%。具体而言Former 的自注意力和 FFN 具有复杂度 O ( M 2 d M d 2 ) O(M^{2}dMd^{2}) O(M2dMd2)。Mobile→Former 和 Mobile←Former 共享交叉注意力的复杂度 O ( M H W C M d C ) O(MHWCMdC) O(MHWCMdC)。
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_channelself.project_KV MLP([self.d_model, 2 * self.in_channel], bnFalse).cuda()self.shortcut nn.Sequential().cuda()def forward(self, x, global_feature):res self.shortcut(x)n, c, h, w x.shapeproject_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, hh)return feature res网络结构
一个 Mobile-Former 架构图像大小为 224×224294M 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, stride1, k2, head8, expand_ratio2):super(MobileFormerBlock, self).__init__()self.in_channel, self.expand_size, self.out_channel in_channel, expand_size, out_channelself.d_model, self.stride, self.k, self.head, self.expand_ratio d_model, stride, k, head, expand_ratioself.mobile Mobile(self.in_channel, self.expand_size, self.out_channel, self.d_model, kernel_size3, strideself.stride, kself.k).cuda()self.former Former(self.head, self.d_model, expand_ratioself.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专业人士交流请立即访问昇腾社区官方网站https://www.hiascend.com/或者深入研读《AI系统原理与架构》一书这里汇聚了海量的AI学习资源和实践课程为您的AI技术成长提供强劲动力。不仅如此您还有机会投身于全国昇腾AI创新大赛和昇腾AI开发者创享日等盛事发现AI世界的无限奥秘~