RepVGG与结构重参数化

参考:RepVGG网络简介

一、RepVGG概览

RepVGG通过"训练时复杂、推理时简单"的 trick,让神经网络在保持高速推理的同时拥有更高精度,更适合实际应用中的硬件加速和部署。

  1. 设计思路
  • 传统VGG网络结构简单,就是一堆3×3卷积叠起来,好处是推理速度快,但精度不如复杂的ResNet这类带"分支"的网络(比如ResNet的残差连接)。
  • 而RepVGG想了个办法:训练的时候用复杂的多分支结构(类似ResNet,有主路、1×1卷积分支、恒等映射分支),这样容易训练出高精度;
    y = Conv3x3(x) + Conv1x1(x) + Identity(x)
    但推理的时候,把这些分支通过数学技巧合并成单一的3×3卷积,变回简单的VGG式结构,保证速度。
  1. 关键技术
  • 这个"数学技巧"叫结构重参数化:把训练时多个分支的参数(比如3×3卷积、1×1卷积、恒等分支的参数)通过代数运算,合并成一个3×3卷积的参数。就像把不同的零件拆了重组,变成一个更简单的零件,但功能不变。
  1. 效果如何
  • 在ImageNet图像分类任务上,RepVGG的精度超过了80%,这是简单结构的网络首次达到这个水平。
  • 速度上,在GPU上比ResNet-50快83%,比ResNet-101快101%,而且参数更少,性价比很高。

训练时,在卷积核的结构上增加了分支结构,引入了类似 ResNet 的残差结构和 1×1 的卷积分支,具体如下:

  • 主分支:保留 3×3 卷积作为主分支,用于提取特征,是主要的特征提取路径。例如在对图像进行分类任务时,3×3 卷积可以捕捉图像中不同尺度的局部特征。
  • 1×1 卷积分支:增加 1×1 的卷积作为一个分支。1×1 卷积可以在不改变特征图尺寸的情况下,调整通道数,实现跨通道的信息交互和整合 。比如,当需要对特征进行降维或升维操作时,1×1 卷积能高效地完成任务,在减少计算量的同时,帮助网络更好地学习特征表示。
  • 恒等映射(Identity)分支:即残差结构中的恒等映射分支。当输入和输出的特征图维度相匹配时,直接将输入添加到输出中,这有助于解决梯度消失问题,使得网络能够更好地训练,学习到更复杂的特征。在深层网络中,随着层数增加,梯度在反向传播过程中容易逐渐消失,而恒等映射分支可以让梯度更顺畅地传播,让网络训练更加稳定。

在这里插入图片描述
在这里插入图片描述

在RepVGG中,训练时每个3×3卷积层都有平行的1×1卷积分支和恒等映射分支,进行等价转换为3×3卷积核,推理时还是简单的VGG的卷积块堆叠。但3乘3的卷积核不是直接将训练时的3×3 的卷积核保留下来这么简单。3×3 卷积核是转换后的重要组成部分,但还需要对其他分支的参数进行处理,并与原 3×3 卷积核参数合并。

通过结构重参数化技术,将这些分支的参数(包括 3×3 卷积、1×1 卷积、恒等映射分支的参数以及各分支后的 BN 层参数)进行等价转换,合并为推理时单一的 3×3 卷积核参数。

  • 需先把1×1卷积只需在原来权重周围补一圈零,转换为3×3卷积形式
  • 恒等映射则转换为以单位矩阵为卷积核的特殊1×1卷积,再进一步转换为3×3卷积形式。
  • 同时,每个分支后的BN层在推理时也可转换为带偏置的卷积层相关参数。
  • 最后,将这三个分支转换后的卷积核和偏置分别相加,得到最终推理时单一的3×3卷积核参数。

结构重参数化(structural re-parameterization technique)

第一步主要是将Conv2d算子和BN算子融合以及将只有BN的这三个分支,分别转换成一个Conv2d矩阵,
第二步将每个分支上的3x3卷积层融合成一个卷积层,合并的过程其实也很简单,直接将这三个卷积层的参数相加即可。

具体融合过程如图

在这里插入图片描述

二、实验

卷积层和批归一化层BN的融合实验

import torch
import torch.nn as nn
from collections import OrderedDict
import numpy as np

def create_model():
    """创建包含卷积层和BN层的模型"""
    model = nn.Sequential(OrderedDict([
        ('conv', nn.Conv2d(
            in_channels=2, 
            out_channels=2,
            kernel_size=3,
            stride=1,
            padding=1,
            bias=False
        )),
        ('bn', nn.BatchNorm2d(num_features=2))
    ]))
    return model

def print_model_parameters(model, prefix="Original"):
    """打印模型参数信息"""
    print(f"\n{
     
     prefix} Model Parameters:")
    for name, param in model.named_parameters():
        if param.requires_grad:
            print(f"  {
     
     name}: shape={
     
     param.shape}")

def fuse_conv_bn(conv, bn):
    """融合卷积层和BN层"""
    # 获取卷积核和BN参数
    kernel = conv.weight
    running_mean = bn.running_mean
    running_var = bn.running_var
    gamma = bn.weight
    beta = bn.bias
    eps = bn.eps
    
    # 计算融合参数
    std = (running_var + eps).sqrt()
    t = (gamma / std).reshape(-1, 1, 1, 1)
    fused_kernel = kernel * t
    fused_bias = beta - running_mean * gamma / std
    
    # 创建融合后的卷积层
    fused_conv = nn.Conv2d(
        in_channels=conv.in_channels,
        out_channels=conv.out_channels,
        kernel_size=conv.kernel_size,
        stride=conv.stride,
        padding=conv.padding,
        bias=True
    )
    
    # 加载融合参数
    fused_conv.load_state_dict(OrderedDict([
        ('weight', fused_kernel),
        ('bias', fused_bias)
    ]))
    
    return fused_conv

def main():
    # 设置随机种子以确保结果可复现
    torch.manual_seed(0)
    np.random.seed(0)
    
    # 创建输入张量
    input_tensor = torch.randn(1, 2, 3, 3)
    print(f"Input shape: {
     
     input_tensor.shape}")
    
    # 创建并初始化模型
    model = create_model()
    model.eval()  # 设置为评估模式
    
    # 打印模型结构
    print("\nModel Architecture:")
    print(model)
    print_model_parameters(model)
    
    # 原始模型前向传播
    with torch.no_grad():
        output_before_fusion = model(input_tensor)
        print(f"\nOutput shape before fusion: {
     
     output_before_fusion.shape}")
        print(f"Sample output values before fusion:\n{
     
     output_before_fusion[0, 0, :2
### RepVGG模型的重参数化技术 RepVGG是一种高效的神经网络结构设计方法,其核心在于通过训练阶段和推理阶段的不同形式来提升性能。具体而言,在训练过程中,RepVGG采用多分支结构(multi-branch architecture),而在推理阶段则将其转换为单路径等价网络(single-path equivalent network)。这种转换过程被称为 **reparameterization** 技术。 #### 训练阶段的设计 在训练阶段,RepVGG引入了多个并行的操作路径,包括逐点卷积(pointwise convolution)、深度可分离卷积(depthwise separable convolutions)以及恒等映射(identity mapping)。这些操作共同构成了一个多分支架构,能够增强特征表达能力,并有助于优化收敛[^1]。 #### 推理阶段的简化 当进入推理阶段时,上述复杂的多分支结构会被重新参数化为单一的标准卷积层。这一过程涉及将所有分支中的权重融合到一起,形成一个新的等效卷积核。这样做的好处是可以显著减少计算开销,从而提高运行效率,尤其是在资源受限设备上表现尤为突出[^2]。 以下是实现该重参数化的Python伪代码示例: ```python import torch.nn as nn def repvgg_model_convert(train_time_model, save_path=None): deployed_model = create_deployed_model() # 创建用于部署的简单模型 for layer in train_time_model.layers: if isinstance(layer, RepVGGBlock): kernel, bias = compute_equivalent_kernel_bias(layer) deploy_layer = nn.Conv2d( in_channels=layer.in_channels, out_channels=layer.out_channels, kernel_size=layer.kernel_size, stride=layer.stride, padding=layer.padding ) deploy_layer.weight.data = kernel deploy_layer.bias.data = bias replace_module(deployed_model, layer, deploy_layer) if save_path is not None: torch.save(deployed_model.state_dict(), save_path) return deployed_model ``` 此函数展示了如何从训练模式下的复杂模块转换成适合实际应用环境的紧凑型版本。 #### 性能评估指标 为了衡量经过重参数化后的RepVGG模型效果,通常会关注以下几个方面: - **Precision**: 衡量预测结果中有多少比例是真正阳性的样本。 - **Recall**: 反映所有真实阳性样本中有多少被成功检测出来。 - **mAP (mean Average Precision)**: 综合考虑不同类别下平均精度的表现情况。 - **FPS (Frames Per Second)**: 实际应用场景中每秒可以处理的画面帧数,特别是在嵌入式硬件如Jetson Nano上的执行速度。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值