
文档教程人工智能【免费下载链接】AISystemAISystem 主要是指AI系统包括AI芯片、AI编译器、AI推理和训练框架等AI全栈底层技术项目地址https://gitcode.com/GitHub_Trending/ai/AISystem点击查看免费下载FBNet 是 Facebook 提出的轻量级卷积神经网络系列本文基于 04Inference/02Mobilenet/025FBNet.md 系统梳理 FBNet V1/V2/V3 三代演进从 V1 的 DNAS 可微搜索与 Latency-Aware 损失到 V2 的 DMaskingNAS 通道/分辨率搜索再到 V3 的 JointNAS 架构与训练超参联合搜索。读完本文你将掌握 FBNet 系列的搜索空间设计、损失函数构造、Gumbel Softmax 松弛原理以及如何在推理系统模型小型化实践中理解搜索 约束的轻量网络设计范式。为什么需要 FBNet轻量网络与 NAS 的结合点在模型小型化场景中手工设计轻量网络如 MobileNet、ShuffleNet见 023Mobilenet.md依赖大量人工调优而传统 NAS 方法需要分别枚举并完整训练每种候选结构计算开销巨大。FBNet 系列的核心思路是把网络结构搜索问题转化为可微优化问题让超网supernet通过梯度下降自动学习每层的 block 分布同时把目标硬件上的时延、FLOPs 等资源约束直接编入损失函数一次性搜索出精度高且适配硬件的网络结构与训练参数。FBNet 系列完全基于 NAS 方法构建轻量级网络三代模型逐次分析前代搜索方法的缺点并增加创新性改进FBNetV1结合 DNASDifferentiable Neural Architecture Search与资源约束采用梯度优化卷积结构避免逐一枚举训练FBNetV2提出 DMaskingNAS将通道数与输入分辨率分别以 mask 和采样方式加入超网几乎不增加存储与计算成本就大幅扩大搜索空间FBNetV3提出 JointNAS在资源约束下联合搜索网络架构与训练超参数解决结构搜索正确但训练参数不合适导致性能下降的问题。FBNet V1基于 DNAS 的可微搜索 Latency-Aware 损失FBNetV1 的训练与网络构建方法基本沿用了 DARTS 的思路但关键区别在于DARTS 的搜索空间集中在 Cell 结构内部搜索 cell 内连接和路径上的操作而 FBNet 的连接是确定的只在网络主体上搜索路径上的操作因此可以逐层选择不同的 block。DNAS 方法把离散结构搜索变成梯度优化DNAS 将网络结构搜索问题形式化为双层最小化$$\underset {a∈A}{min} \underset {w_{a}}{min} L(a,w_{a}) \tag{1}$$给定结构空间 A寻找最优结构 $a∈A$在训练好权值 $w_{a}$ 后使损失 $L(a,w_{a})$ 最小。论文主要围绕三个因素展开搜索空间、考虑实际时延的损失函数以及高效的搜索算法。流程上DNAS 将整体搜索空间表示为超网把寻找最优网络结构转化为寻找最优候选 block 分布通过梯度下降训练 block 分布且可以为网络每层选择不同 block。为了准确估计时延作者预先测量并记录每个候选 block 在实际目标硬件上的时延估算时直接按网络结构累计各 block 时延即可。搜索空间layer-wise 的固定整体结构之前的方法大都搜索单元结构再堆叠成完整网络但相同的单元结构在不同层对准确率和时延的影响差别很大。FBNet 构造了整体网络结构macro-architecture固定的 layer-wise 搜索空间每层可选择不同结构的 block网络第一层和最后三层结构固定其余层参与搜索前面的层由于特征分辨率较大人工设定较小的核数量以保证轻量性。候选 block 基于 MobileNetV2 和 ShuffleNet 的经典结构设计对应本仓库 023Mobilenet.md 与 022Shufflenet.md通过设定不同的卷积核大小3 或 5、扩展率以及分组数构造成不同候选 block。规则如下若 block 的输入和输出分辨率一致则添加 element-wise 的 shortcut残差连接若使用了分组卷积则需要对卷积输出做 channel shuffle。Latency-Aware 损失把硬件时延编入目标函数公式 (1) 中的损失函数不仅要反映准确率也要反映目标硬件上的时延因此定义$$L(a,w_{a}) CE(a,w_{a})\cdot αlog(LAT(a)^{β})\tag{2}$$其中 $CE(a,w_{a})$ 表示交叉熵损失LAT(a) 表示当前结构在目标硬件上的时延α 控制整体损失函数的幅值β 调整时延项的幅值。时延计算比较耗时论文使用block 时延 lookup 表格估计网络整体时延$$LAT(a) \sum_{l}LAT(b_{l}^{(a)})\tag{3} $$$b_{l}^{(a)}$ 为结构 a 中第 l 层的 block。该估计假设 block 间计算相互独立对 CPUs、DSPs 等串行计算设备有效据此可以快速估计 $10^{21}$ 量级网络的实际时延。对应的损失实现如下class SupernetLoss(nn.Module): def __init__(self): super(SupernetLoss, self).__init__() 损失函数中的超参设置以及有关函数初始化 self.alpha CONFIG_SUPERNET[loss][alpha] self.beta CONFIG_SUPERNET[loss][beta] self.weight_criterion nn.CrossEntropyLoss() def forward(self, outs, targets, latency, losses_ce, losses_lat, N): 根据公式 2 ce self.weight_criterion(outs, targets) lat torch.log(latency ** self.beta) losses_ce.update(ce.item(), N) losses_lat.update(lat.item(), N) loss self.alpha * ce * lat return loss #.unsqueeze(0)其中alpha、beta分别对应公式 (2) 的 α、βlatency即由时延 lookup 表累计得到的 LAT(a)。Gumbel Softmax 松弛让结构变量可导论文将搜索空间表示为随机超网每层包含表 2 中的并行 block每层 9 个候选。推理时候选 block 被执行的概率为$$P_{θ_{l}(b_{l}b_{l,i})} softmax(θ_{l,i};θ_{l}) \frac{exp(θ_{l,i})} {\sum_{i1}exp(θ_{l,i})}\tag{4}$$$θ_{l}$ 包含决定 l 层每个候选 block 采样概率的参数。l 层的输出可表示为$$x_{l1} \sum_{i}m_{l,i} \cdot b_{l,i}(x_{l}) \tag{5}$$$m_{l,i}$ 是 {0,1} 随机变量根据采样概率随机赋值层输出为所有 block 输出之和。于是网络结构 a 的采样概率可表示为$$P_{θ}(a)\mathop{\prod}\limits_lP_{θ_{l}} (b_{l}b_{l,i}^{(a)}) \tag{6} $$$θ$ 包含所有 block 的 $θ_{l,i}$。基于上述定义公式 (1) 的离散优化问题被转化为$$ \mathop{min}\limits_θ \mathop{min}\limits_{w_{a}} E_{a}~P_{θ}{L((a,w_{a}))}\tag{7} $$此时权值 $w_{a}$ 可导但 $m_{l,i}$ 是离散定义θ 仍不可导。为此用Gumbel Softmax重参数化 $m_{l,i}$$$ m_{l,i}GumbelSoftmax(θ_{l,i}|θ_{l}) \frac{exp[(θ_{l,i}g_{l,i})/ τ]}{\sum_{i}exp[(θ_{l,i}g_{l,i})/ τ} \tag{8} $$$g_{l,i}\sim Gumbel(0,1)$ 为 Gumbel 分布的随机噪声τ 为温度参数τ 接近 0 时 $m_{l,i}$ 类似 one-shot接近离散选择τ 越大 $m_{l,i}$ 越接近连续随机变量。这样公式 (2) 的交叉熵损失可对 $w_{a}$ 和 θ 求导时延项 LAT 也可改写为$$LAT(a) \sum_{l}\sum_{i}m_{l,i}\cdot LAT(b_{l,i}) \tag{9}$$由于使用 lookup 表格$LAT(b_{l,i})$ 是常量因子网络整体时延对结构变量同样可导。至此损失函数对权值 $w_{a}$ 和结构变量 θ 都完全可导可以用 SGD 高效优化。搜索过程等同于随机超网的训练训练时计算 $∂L/∂w_{a}$ 更新超网每个 block 的权值block 训练完成后各 block 对准确率和时延的贡献不同再计算 $∂L/∂θ$ 更新每个 block 的采样概率 $P_{θ}$。超网训练结束后通过采样网络分布 $P_{θ}$ 得到最优网络结构。核心搜索过程实现如下class MixedOperation(nn.Module): 搜索算法过程 def __init__(self, layer_parameters, proposed_operations, latency, layer_num): super(MixedOperation, self).__init__() ops_names [op_name for op_name in proposed_operations] self.ops nn.ModuleList(proposed_operations[op_name for idx, op_name in enumerate(ops_names)]) self.latency [latency[op_name] for op_name in ops_names] self.thetas nn.Parameter(torch.Tensor([1.0 / len(ops_names) for i in range(len(ops_names))])) def forward(self, x, temperature, latency_to_accumulate): 根据上述公式的代码实现 soft_mask_variables nn.functional.gumbel_softmax(self.thetas, temperature) output sum(m * op(x) for m, op in zip(soft_mask_variables, self.ops)) latency sum(m * lat for m, lat in zip(soft_mask_variables, self.latency)) latency_to_accumulate latency_to_accumulate latency return output, latency_to_accumulate其中self.thetas即公式 (4) 的架构参数 $θ_{l}$temperature对应 τlatency_to_accumulate按公式 (9) 逐层累计时延。网络结构基于 MobileNetV2 反向残差块FBNet 是通过 DNAS 搜索发现的卷积神经架构采用受 MobileNetV2 启发的基本图像模型块深度卷积 反向残差结构见下图。FBNet-A、FBNet-B、FBNet-C 三者的区别在于最后一个卷积的输出 channel 不同。FBNets-B 在 ImageNet 上达到 74.1% 的 top-1 准确率仅需 295M FLOPs。FBNet V2DMaskingNAS 的通道与输入分辨率搜索FBNetV2 提出DMaskingNAS把 channel 数和输入分辨率分别以 mask 和采样方式加入超网在带来少量内存和计算量开销的同时大幅增加搜索空间。其核心机制包括Channel masking特征映射重用使得搜索空间扩大时存储和计算成本几乎保持不变有效的形状传播Efficient Shape Propagation最大化每个 FLOPs 或每个参数的精度搜索出的 FBNetV2s 在同等预算下具有一流性能。通道搜索把不同 channel 融入超网把不同 channel 加入搜索空间时若沿用 DNAS 把每个选项实例化进超网的做法会带来接近 $O(N^2)$ 种选择计算量不可接受。为此作者构造channel masking 机制把不同 channel 的最终输出表征为与一个 mask 向量相乘的形式。具体而言作者假设不同层通道路径共享同一个卷积核参数不同 channel 的输出取决于 mask 向量g1、g2、g3 是不同 channel 选择的架构参数对应白蓝条状 mask 向量白色表示 1蓝色表示 0分别与卷积相乘——白色部分表示该路径保留的输出 channel蓝色部分表示该路径不包含这部分 channel但整体计算维度保持一致。不同 mask 向量分别与卷积核参数相乘再用 channel 架构参数加权求和这样在搜索过程中就能通过架构参数获知每个 stage 卷积核该选择多少个输出 channel。加权求和首先会遇到 Step A 的问题channel 不同则 tensor shape 不同无法直接相加。解决办法是 Step B对输出做 zero padding 使 shape 对齐图中蓝色部分然后加权求和。Step B 与 Step C 等价Step C 相当于对卷积 filter 做 mask随后作者做简化假设——所有 weighting 共享即 Step DStep E 与 Step D 等效就是最终的 channel masking 机制。数学上给定输入 xGumbel Softmax 输出为$$ y \sum^{k}{i1}g{i}P_{AD}(b_{i}(x),k) \tag{1} $$这等价于把所有卷积的滤波器数量增加到 k并屏蔽掉额外通道步骤 C。$l_{i} \in R^{k}$ 是一个列向量以 1 开头、k-i 个 0 结尾搜索方法对 1 和 0 的排序保持不变。由于所有 block $b_i$ 具有相同数量的滤波器可以共享权重近似使 $b_i b$步骤 D$$ y \sum^{k}{i1}g{i}(b(x)\circ l_{i}) \tag{2} $$利用该近似可处理原始通道搜索的计算复杂性相当于计算集合掩码并只运行 block b 一次步骤 E$$ yb(x)\circ \underbrace{\sum^{k}{i1}g{i}l_{i}}_{M} \tag{3} $$该近似只需一次正向传递和一个特征映射除公式 (3) 中可忽略的 M 项外不引起额外 FLOPs 或内存成本。需要说明这种近似并不严格等价只是因为权重共享而权重共享在 DNAS 中被证明能减少训练时间并提高准确率。这使 FBNetV2 能搜索任何模块的输出通道数包括反向残差模块中的扩展速率等关联架构决策。输入分辨率搜索处理像素错位与感受野错位对于空间维度FBNetV2 同时搜索输入分辨率。若沿用 DNAS 为每种输入分辨率实例化每个 block会有两个缺点内存成本增加、维度不兼容。与通道维度一样可通过对结果做 zero padding 解决维度问题但有两点需要特别处理像素错位Pixel Misalignment对图像外围做零填充没有意义会导致像素错位——只有把零点在空间上散布interspersing才能让不同分辨率的特征图正确对齐求和。空间搜索挑战A不同空间维度的张量因维度不兼容无法求和B沿较小特征图外围零填充使求和成为可能但右上角像素未正确对齐C在空间上散布零填充两个特征图的右上角像素在总和中正确重叠D用 3×3 核卷积包含子集灰色的特征图会导致该子集的感受野2×2蓝色减小E为保留所有被搜索输入分辨率的感受野卷积前必须对输入做二次采样感受野仍保持 3×3。此外不构造更小张量也能实现相同效果采用具有适当步长的膨胀卷积从而避免修改 F 运算。这种零填充模式是统一的除零点外等效于最近邻上采样。例如尺寸增大 2 倍将涉及每隔一行和一列进行零填充。补零而非上采样可以最小化输入分辨率的像素污染在最左侧是原始的 8×8 特征图蓝色的 4×4 是使用最近邻二次采样的特征图并均匀零填充黄色的 2×2 同样二次采样并零填充。2×2 与 4×4 相加得到最右边的组合特征图只有角落中的绿色像素保存两种特征图尺寸的值这些绿色值被较低分辨率特征图污染。处理完像素错位后还需处理感受野错位由于特征图的子集对应不同分辨率简单卷积整个特征图会导致感受野减小因此转而对二次采样输入进行卷积。使用 Gumbel Softmax 得到分辨率子采样结果。NASNet 曾引入组合隐藏状态的类似概念这些组合也被用于高效探索组合大的搜索空间但 NASNet 用于确定重复搜索单元的次数而 FBNetV2 用于搜索输入分辨率。这样输入分辨率搜索的存储成本与分辨率数量无关计算成本则随分辨率数量次线性增加。有效形状传播训练期的成本核算有效形状的计算仅在训练期间使用。在加权求和公式 (1) 中输出 y 保留最大数量的通道但会存在非整数数量有效通道假设 16 通道输出具有 Gumbel 权重 $g_i 0.8$12 通道输出具有权重 $g_i 0.2$则有效通道数为 $0.8 \times 16 0.2 \times 12 15.2$。有效通道对 FLOPs 和参数量计算都是必要的——把更高权重分配给更多通道会导致更大的成本损失。首先定义 Gumbel Softmax 权重$$ g^{l}{i} \frac{exp[\frac{\alpha_{l,i}{\epsilon_{l,i}}}{\mathcal{T}}]}{\sum{i}exp[\frac{\alpha_{l,i}{\epsilon_{l,i}}}{\mathcal{T}}]} \tag{4} $$采样参数为 αGumbel 噪声为 $\mathcal{E}$温度为 $\mathcal{T}$。对第 l 层中与 Gumbel Softmax 相关联的卷积定义其有效输出形状 $\overline{S}_{out}^l$$$ \overline{C}{out}^l \sum_ig^{l}{i}\cdot C^{l}_{i,out} \tag{5} $$$$ \overline{h}{out}^l \sum_ig^{l}{i}\cdot \overline{h}{in}^l \cdot \overline{w}{out}^l \sum_ig^{l}{i}\overline{w}{in}^l \tag{6} $$$$ \overline{S}{out}^l (n,\overline{C}{out}^l,\overline{h}{out}^l,\overline{S}{out}^l) \tag{7} $$其中批量大小为 n$\overline{w}{in}^l$ 和 $\overline{h}{in}^l$ 为有效输入宽度和高度。对于没有 Gumbel Softmax 的卷积层有效输出形状简化为公式 (8)有效通道数等于实际通道数对于深度卷积有效输出形状简化为公式 (9)有效通道数直接传播$$ \overline{C}{out}^l C^{l}{out}\tag{8} $$$$ \overline{C}{out}^l C^{l}{in}\tag{9} $$$C_{out}$ 为实际输出通道数$C_{in}$ 为有效输入通道数。于是第 l 层的成本函数定义为$$ cost^{l} \begin{cases} k^{2}\cdot \overline{h}{out}^l \cdot \overline{w}{out}^l \cdot \overline{C}{in}^l \cdot \overline{C}{out}^l / γ \text{if FLOP} \ k^{2} \cdot \overline{C}{in}^l \cdot \overline{C}{out}^l / γ \text{if param } \end{cases} \tag{10} $$γ 为卷积分组数第 (l1) 层的有效输入通道为 $\overline{C}^{l1}{in} \overline{C}^l{out}$。总训练损失由 (1) 交叉熵损失和 (2) 总成本组成总成本是各层成本之和$cost_{total} \sum_lcost^l$。在正向传播中所有卷积都计算并返回输出张量和有效输出形状。此外Gumbel Softmax 公式 (4) 中的温度 $\mathcal{T}$ 在整个训练期间下降迫使 $g^{l}$ 接近 one-hot 分布argmax将在超图中选择block 路径、每个 block 的通道与扩展速率选项、以及整个网络的单一输入分辨率。最终架构随后被完整训练且不使用 mask、也不需要有效形状。网络结构实现首先使用 DMaskingNAS 寻找低计算预算的紧凑模型搜索出的 FBNetV2 架构中颜色表示不同的内核大小高度表示不同的膨胀率按比例绘制。模型覆盖 50 MFLOPs 至 300 MFLOPs 预算对应实现中get_divisible_by用于把通道数规整为 8 的倍数对齐硬件加速InvertedResidual实现带 SESqueeze-and-Excitation的反向残差块FBNetV2按 stage 配置堆叠网络def py2_round(x): return math.floor(x 0.5) if x 0.0 else math.ceil(x - 0.5) def get_divisible_by(num, divisible_by8, min_valNone): ret int(num) if min_val is None: min_val divisible_by if divisible_by 0 and num % divisible_by ! 0: ret int((py2_round(num / divisible_by) or 1) * divisible_by) if ret 0.95 * num: ret divisible_by if ret min_val: ret min_val return ret class InvertedResidual(Layer): def __init__(self, in_channels, channels, out_channels, kernel_size, stride, actrelu, with_seTrue, drop_path0.0): super().__init__() self.with_se with_se if in_channels ! channels: self.expand Conv2d(in_channels, channels, kernel_size1, normbn, actact) else: self.expand Identity() self.dwconv Conv2d(channels, channels, kernel_size, stride, groupschannels, normbn, actact) if self.with_se: self.se SELayer(channels, reduction4, actact, gating_fnhsigmoid, min_se_channels8, divisible8) self.project Conv2d(channels, out_channels, kernel_size1, normbn) self.use_res_connect stride 1 and in_channels out_channels self.drop_path DropPath(drop_path) if drop_path and self.use_res_connect else Identity() def forward(self, x): identity x x self.expand(x) x self.dwconv(x) if self.with_se: x self.se(x) x self.project(x) if self.use_res_connect: x self.drop_path(x) x identity return x class FBNetV2(Model): def __init__(self, setting, num_classes1000, dropout0, drop_path0): super().__init__() in_channels setting[init_channels] last_channels setting[last_channels] self.stem Conv2d(3, in_channels, kernel_size3, stride2, normbn, acthswish) for i, stage_setting in enumerate(setting[stages]): stage [] for k, c, s, n, e, se, nl in stage_setting: mid_channels get_divisible_by(in_channels * e, 8) out_channels c if k 1: stage.append(Conv2d( in_channels, out_channels, kernel_size1, strides, normbn, actnl)) else: stage.append(InvertedResidual( in_channels, mid_channels, out_channels, k, s, nl, se, drop_path)) in_channels out_channels name fstage{i1} setattr(self, name, Sequential(stage)) if drop_path: init_layer_ascending_drop_path(self, drop_path) self.last_pw Conv2d(in_channels, in_channels * 6, kernel_size1, normbn, acthswish) self.avgpool GlobalAvgPool(keep_dimTrue) self.last_fc Conv2d(in_channels * 6, last_channels, kernel_size1, acthswish) self.dropout Dropout(dropout) if dropout else None self.fc Conv2d(last_channels, num_classes, kernel_size1, kernel_initRandomNormal(stddev0.01), bias_initzeros) def forward(self, x): x self.stem(x) x self.stage1(x) x self.stage2(x) x self.stage3(x) x self.stage4(x) x self.stage5(x) x self.last_pw(x) x self.avgpool(x) x self.last_fc(x) if self.dropout is not None: x self.dropout(x) x self.fc(x) return x值得注意的实现细节stage_setting中每个元素(k, c, s, n, e, se, nl)依次为卷积核大小、输出通道、步长、block 重复次数、扩展率、是否使用 SE、激活函数中间通道mid_channels用get_divisible_by(in_channels * e, 8)计算保证通道数为 8 的倍数便于移动端硬件高效执行k 1时退化为 1×1 卷积无深度卷积分支否则走InvertedResidual残差连接仅在stride 1 and in_channels out_channels时生效配合drop_path随机深度实现训练正则化。FBNet V3JointNAS 联合搜索架构与训练参数FBNetV3 观察到此前 NAS 方法大都只搜索网络结构而没有在意网络性能验证时训练参数设置是否合适这可能导致模型性能下降。为此论文提出JointNAS在资源约束下同时搜索最准确的训练参数与网络结构。联合搜索粗粒度 细粒度两阶段JointNAS 分粗粒度和细粒度两个阶段对网络架构和训练超参都进行搜索优化目标可形式化为$$ \underset{(A,h)∈Ω}{max} acc(A,h),subject to g_{i}(A)\leqslant C_{i} for i1,..,τ \tag{1} $$A、h、Ω 分别表示网络架构、训练策略以及搜索空间$g_{i}(A)$ 表示资源约束的信息资源消耗计算τ 表示资源数量acc 计算当前结构和训练参数下的准确率。粗粒度阶段coarse-grained迭代式寻找高性能的候选网络结构-超参数对并训练准确率预测器细粒度阶段fine-grained借助粗粒度阶段训练的准确率预测器对候选网络进行快速进化算法搜索该搜索集成了论文提出的超参数优化器 Auto Train。粗粒度阶段训练双 head 准确率预测器粗粒度搜索生成准确率预测器和一个高性能候选网络集。该预测器是一个多层感知器构成的小型网络包含两部分一个代理预测器proxy predictor和一个准确率预测器accuracy predictor。预测器包含一个结构编码器以及两个 headAuxiliary proxy head辅助代理 head用于预训练编码架构预测架构统计信息如 FLOPs 与参数量。网络架构通过 one-hot 方式编码准确率 head接收训练策略与网络架构迭代优化给出架构的精度评估。图中左边的 architecture presentation 是网络架构的编码描述one-hot 或 int 形式的矩阵向量用来表示网络结构参考 DARTS 的架构参数architecture encoder 是提取架构描述特征的多层感知器生成低维架构嵌入architecture embedding。该嵌入首先用于 Proxy Predictor 训练——由于任何网络架构描述都能对应实际网络模型及其计算量、参数量数值这个阶段不需要额外标注数据。预训练好第一排网络后迭代训练第二排的准确率预测器输入为训练超参表示 低维特征向量输出为网络架构 训练超参的结果准确率。迭代优化步骤如下基于已预测的准确率选择一组候选集选择方法为准蒙特卡洛QMCquasi-Monte Carlo训练并评估候选集的网络模型得到评估准确率使用所有历史候选集的准确率与表示输入架构 超参更新预测器。在第一步迭代时还要确定早停方案早停用于找到样本训练网络本身的训练而非 Predictor 的训练的 epoch 参数确定方法为选取 n 个网络对完整训练结果和早停训练结果分别排序计算两种排序的相关性若早停 epoch 达到某值时两种排序的相关性达到阈值文中为 0.92即确定该早停 epoch否则加大 epoch 重新进入步骤 1。使用早停策略得到的网络准确率可用来训练更新预测器更新时还有几点 tricks使用Huber Loss减少不正常样本的影响开始时冻结 embedding 层只训练 accuracy Predictor50 个 epoch最后再训练整个 Predictor逐步减小学习率50 个 epoch。细粒度阶段自适应遗传算法搜索细粒度搜索的空间是网络架构 训练超参搜索方法是自适应遗传算法步骤为选择最好的几个样本作为种群第一代从粗粒度阶段结果中选取在给定约束条件下对这些样本使用变异方法产生一个子代种群使用准确率预测器生成子代种群的得分如果最好的个体不再更新则停止迭代否则回到步骤 1。需要注意当资源约束改变时预测器依然可以重复使用能快速用细粒度阶段搜索到合适的网络结构和训练参数。搜索空间训练超参 网络架构FBNetV3 的搜索空间包括训练超参和网络架构两部分训练超参优化器类型、初始学习率、参数正则化比例、mixup 比例、dropout 比例、随机深度 drop 比例、是否使用 EMA 等网络架构逆残差模型的参数包括输入分辨率、卷积核大小、中间通道放大比例、每一 stage 的通道数和深度等。对应实现中V3 的InvertedResidual相比 V2 增加了对 SE 通道数的精细控制se_channels可选来自in_channels // 4或channels // 4以及zero_last_bn_gamma对残差连接的最后一层 BN 用零初始化 γ等训练技巧FBNetV3则在每个 stage 内按n重复InvertedResidual并支持drop_path逐层递增初始化class InvertedResidual(Layer): def __init__(self, in_channels, channels, out_channels, kernel_size, stride, actrelu, with_seTrue, drop_path0.0): super().__init__() self.with_se with_se self.use_res_connect stride 1 and in_channels out_channels if in_channels ! channels: self.expand Conv2d(in_channels, channels, kernel_size1, normbn, actact) else: self.expand Identity() self.dwconv Conv2d(channels, channels, kernel_size, stride, groupschannels, normbn, actact) if self.with_se: se_channels int(in_channels // 4) if less_se_channels else int(channels // 4) if less_se_channels: self.se SELayer(channels, se_channelsse_channels, actact, gating_fnhsigmoid, min_se_channels8, divisible8) self.project Conv2d(channels, out_channels, kernel_size1, normbn, gamma_initzeros if zero_last_bn_gamma and self.use_res_connect else ones) self.drop_path DropPath(drop_path) if drop_path and self.use_res_connect else Identity() def forward(self, x): identity x x self.expand(x) x self.dwconv(x) if self.with_se: x self.se(x) x self.project(x) if self.use_res_connect: x self.drop_path(x) x identity return x class FBNetV3(Model): def __init__(self, setting, num_classes1000, dropout0, drop_path0): super().__init__() in_channels setting[init_channels] last_channels setting[last_channels] self.stem Conv2d(3, in_channels, kernel_size3, stride2, normbn, acthswish) for i, stage_setting in enumerate(setting[stages]): stage [] for k, c, s, n, e, se, nl in stage_setting: mid_channels get_divisible_by(in_channels * e, 8) out_channels c if k 1: stage.append(Conv2d( in_channels, out_channels, kernel_size1, strides, normbn, actnl)) else: stage.append(InvertedResidual( in_channels, mid_channels, out_channels, k, s, nl, se, drop_path)) in_channels out_channels mid_channels get_divisible_by(in_channels * e, 8) for j in range(n-1): stage.append(InvertedResidual( in_channels, mid_channels, out_channels, k, 1, nl, se)) name fstage{i1} setattr(self, name, Sequential(stage)) if drop_path: init_layer_ascending_drop_path(self, drop_path) self.last_pw Conv2d(in_channels, in_channels * 6, kernel_size1, normbn, acthswish) self.avgpool GlobalAvgPool(keep_dimTrue) self.last_fc Conv2d(in_channels * 6, last_channels, kernel_size1, acthswish) self.dropout Dropout(dropout) if dropout else None self.fc Conv2d(last_channels, num_classes, kernel_size1, kernel_initRandomNormal(stddev0.01), bias_initzeros) def forward(self, x): x self.stem(x) x self.stage1(x) x self.stage2(x) x self.stage3(x) x self.stage4(x) x self.stage5(x) x self.last_pw(x) x self.avgpool(x) x self.last_fc(x) if self.dropout is not None: x self.dropout(x) x self.fc(x) return x与 V2 实现对比V3 的核心差异在于stage 内部第一个InvertedResidual负责下采样stride s后续n-1个InvertedResidual使用 stride 1 堆叠深度这正对应搜索空间中每一 stage 的通道数和深度的联合搜索维度。小结与思考FBNet 系列是完全基于 NAS 方法的轻量级网络系列通过分析当前搜索方法的缺点逐步增加创新性改进FBNetV1结合 DNAS 与资源约束用 Gumbel Softmax 松弛 时延 lookup 表把硬件时延编入可微损失一次搜索同时优化结构与权值FBNetV2以 DMaskingNAS 把 channel 和输入分辨率搜索以 mask / 采样方式融入超网用零填充解决维度不兼容与像素错位用有效形状传播精确核算 FLOPs 与参数量成本FBNetV3使用准确率预测器代理 head 准确率 head 的双头 MLP进行快速的网络结构搜索配合粗粒度 QMC 采样与细粒度自适应遗传算法实现结构 训练超参的联合优化期待官方更完整的代码开源。对推理系统与模型小型化实践而言FBNet 系列的价值在于给出了一套以硬件实测时延为约束、以可微结构搜索为手段、以精度为最终目标的端到端轻量网络生产范式。更完整的 CNN 模型小型化背景可进一步阅读 02CNN.md并与 MobileNet 系列的深度可分离卷积基础023Mobilenet.md对照理解其 block 设计来源。赞分享文档教程人工智能【免费下载链接】AISystemAISystem 主要是指AI系统包括AI芯片、AI编译器、AI推理和训练框架等AI全栈底层技术项目地址https://gitcode.com/GitHub_Trending/ai/AISystem点击查看免费下载相关推荐从MobileNet到GhostNet轻量级视觉模型的进化之路从MobileNet到GhostNet轻量级视觉模型的进化之路 在移动设备和边缘计算快速发展的今天轻量级视觉模型已成为人工智能领域的研究热点。 PyTorc人工智能计算机视觉深度学习预训练从MobileNet到EfficientNet轻量级视觉模型的十年进化之路从MobileNet到EfficientNet轻量级视觉模型的十年进化之路 huggingface/pytorch image models是一个由Huggi人工智能计算机视觉深度学习预训练OpenProject完整指南从部署到甘特图排期与看板协作的实战路径OpenProject完整指南从部署到甘特图排期与看板协作的实战路径 OpenProject 是一款开源的项目管理工具把任务管理工作包、甘特图排期、看板后端前端项目管理企业应用协同办公上一篇3步跑通SkyReels-V2本地无限长视频生成实战指南下一篇HPSv2 项目使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考