【人工智能笔记】第二十六节 tensorflow 2.0 实现 RepVGG 高效卷积

RepVGG:让VGG风格的ConvNet再次伟大起来 RepVGG:让VGG风格的ConvNet再次伟大起来(RepVGG: Making VGG-style ConvNets Great Again) 阅读详情

该版本基于PyTouch版本改写。

作者提出了一个简单但功能强大的卷积神经网络架构,该架构具有类似于VGG的推理时间主体,该主体仅由3x3卷积和ReLU的堆栈组成,而训练时间模型具有多分支拓扑。训练时间和推理时间架构的这种解耦是通过结构性重新参数化技术实现的,因此该模型称为RepVGG。在ImageNet上,据我们所知,RepVGG的top-1准确性达到80%以上,这是纯模型首次实现该精度。在NVIDIA 1080Ti GPU上,RepVGG模型的运行速度比ResNet-50快83%,比ResNet-101快101%,具有更高的精度,并且与诸如EfficientNet和RegNet的最新模型相比,显示出良好的精度-速度折衷。

如下图,网络结构分成种,图中B结构是训练时的结构,C结构是推理时的结构。推理时按卷积原理,把3个分支的权重合并成1个卷积权重,以提高推理速度。

效率与精度如下:

实现代码如下,结果由于权重合并时的精度影响,输出值会有稍微的差异:

import tensorflow as tf

class ConvBn(tf.keras.layers.Layer):
  def __init__(self, filters, kernel_size, strides=1, padding='same', groups=1, **kwargs):
    super(ConvBn, self).__init__(**kwargs)
    self.conv = tf.keras.layers.Conv2D(filters, kernel_size, strides=strides, padding=padding,
                                       groups=groups, use_bias=False)
    self.bn = tf.keras.layers.BatchNormalization()

  def call(self, inputs, training):
    x = inputs
    x = self.conv(x)
    x = self.bn(x, training=training)
    return x

class RepVGGBlock(tf.keras.layers.Layer):
  def __init__(self, filters, kernel_size, strides=1, padding='same', groups=1, deploy=False, **kwargs):
    super(RepVGGBlock, self).__init__(**kwargs)
    self.filters = filters
    self.kernel_size = kernel_size
    self.strides = strides
    self.padding = padding
    self.groups = groups
    self.deploy = deploy

  def build(self, input_shape):
    self.in_channels = input_shape[-1]
    if self.deploy:
        # 部署
        self.rbr_reparam = tf.keras.layers.Conv2D(self.filters, self.kernel_size, strides=self.strides, padding=self.padding,
                                                  groups=self.groups, use_bias=True)
    else:
        # 训练
        self.rbr_identity = tf.keras.layers.BatchNormalization() if self.in_channels == self.filters and self.strides == 1 else None
        self.rbr_dense = ConvBn(self.filters, kernel_size=self.kernel_size, strides=self.strides, padding=self.padding, groups=self.groups)
        self.rbr_1x1 = ConvBn(self.filters, kernel_size=1, strides=self.strides, padding=self.padding, groups=self.groups)
        tf.print('RepVGG Block, identity = ', self.rbr_identity)
    super(RepVGGBlock, self).build(input_shape)

  def call(self, inputs, training):
    x = inputs
    if hasattr(self, 'rbr_reparam'):
      return tf.nn.relu(self.rbr_reparam(x))

    if self.rbr_identity:
      id_out = self.rbr_identity(x, training=training)
    else:
      id_out = 0

    x = tf.nn.relu(self.rbr_dense(x, training=training) + self.rbr_1x1(x, training=training) + id_out)
    return x
  
  def get_equivalent_kernel_bias(self):
    '''计算等价kernel与bias'''
    kernel3x3, bias3x3 = self._fuse_bn_tensor(self.rbr_dense)
    kernel1x1, bias1x1 = self._fuse_bn_tensor(self.rbr_1x1)
    kernelid, biasid = self._fuse_bn_tensor(self.rbr_identity)
    return kernel3x3 + tf.pad(kernel1x1, [[1,1],[1,1],[0,0],[0,0]]) + kernelid, bias3x3 + bias1x1 + biasid

  def _fuse_bn_tensor(self, branch):
    if branch is None:
      return 0, 0
    if isinstance(branch, ConvBn):
      kernel = branch.conv.kernel
      moving_mean = branch.bn.moving_mean
      moving_variance = branch.bn.moving_variance
      gamma = branch.bn.gamma
      beta = branch.bn.beta
      eps = branch.bn.epsilon
    else:
      assert isinstance(branch, tf.keras.layers.BatchNormalization)
      if not hasattr(self, 'id_tensor'):
        input_dim = self.in_channels // self.groups
        kernel_value = tf.zeros((3, 3, input_dim, self.in_channels), dtype=tf.float32)
        for i in range(self.in_channels):
          kernel_value = tf.tensor_scatter_nd_update(kernel_value, [[1, 1, i % input_dim, i]], [1])
        self.id_tensor = kernel_value
      kernel = self.id_tensor
      moving_mean = branch.moving_mean
      moving_variance = branch.moving_variance
      gamma = branch.gamma
      beta = branch.beta
      eps = branch.epsilon
    std = tf.math.sqrt(moving_variance + eps)
    t = tf.reshape(gamma / std, (1, 1, 1, -1))
    return kernel * t, beta - moving_mean * gamma / std

  def repvgg_convert(self):
    kernel, bias = self.get_equivalent_kernel_bias()
    return kernel, bias

class RepVGG(tf.keras.Model):
  def __init__(self, num_blocks, num_classes=1000, width_multiplier=None, override_groups_map=None, deploy=False, **kwargs):
    super(RepVGG, self).__init__(**kwargs)
    self.num_blocks = num_blocks
    self.num_classes = num_classes
    self.width_multiplier = width_multiplier
    self.override_groups_map = override_groups_map or dict()
    self.deploy = deploy

    assert len(self.width_multiplier) == 4
    assert 0 not in self.override_groups_map

    self.in_planes = min(64, int(64 * self.width_multiplier[0]))

  def build(self, input_shape):
    self.stage0 = RepVGGBlock(self.in_planes, kernel_size=3, strides=2, padding='same', deploy=self.deploy)
    self.cur_layer_idx = 1
    self.stage1 = self._make_stage(int(64 * self.width_multiplier[0]), self.num_blocks[0], stride=2)
    self.stage2 = self._make_stage(int(128 * self.width_multiplier[1]), self.num_blocks[1], stride=2)
    self.stage3 = self._make_stage(int(256 * self.width_multiplier[2]), self.num_blocks[2], stride=2)
    self.stage4 = self._make_stage(int(512 * self.width_multiplier[3]), self.num_blocks[3], stride=2)
    
    if self.num_classes:
      self.gap = tf.keras.layers.GlobalAveragePooling2D()
      self.dense = tf.keras.layers.Dense(self.num_classes)
    super(RepVGG, self).build(input_shape)


  def _make_stage(self, planes, num_blocks, stride):
    strides = [stride] + [1]*(num_blocks-1)
    blocks = []
    for stride in strides:
      cur_groups = self.override_groups_map.get(self.cur_layer_idx, 1)
      blocks.append(RepVGGBlock(planes, kernel_size=3,
                                strides=stride, padding='same', groups=cur_groups, deploy=self.deploy))
      self.in_planes = planes
      self.cur_layer_idx += 1
    return tf.keras.Sequential(blocks)


  def call(self, inputs, training):
    out = {}
    x = inputs
    x = self.stage0(x, training=training)
    out['stage0'] = x
    x = self.stage1(x, training=training)
    out['stage1'] = x
    x = self.stage2(x, training=training)
    out['stage2'] = x
    x = self.stage3(x, training=training)
    out['stage3'] = x
    x = self.stage4(x, training=training)
    out['stage4'] = x
    if self.num_classes:
      x = self.gap(x, training=training)
      x = self.dense(x)
      return x
    else:
      return out

  def get_all_layers(self):
    layers = {}
    for layer in self.layers:
      if isinstance(layer, tf.keras.Sequential):
        for l in layer.layers:
          layers[layer.name+'/'+l.name]=l
      else:
        layers[layer.name]=layer
    return layers

optional_groupwise_layers = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26]
g2_map = {l: 2 for l in optional_groupwise_layers}
g4_map = {l: 4 for l in optional_groupwise_layers}

def create_RepVGG_A0(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[2, 4, 14, 1], num_classes=num_classes,
                width_multiplier=[0.75, 0.75, 0.75, 2.5], override_groups_map=None, deploy=deploy)

def create_RepVGG_A1(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[2, 4, 14, 1], num_classes=num_classes,
                width_multiplier=[1, 1, 1, 2.5], override_groups_map=None, deploy=deploy)

def create_RepVGG_A2(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[2, 4, 14, 1], num_classes=num_classes,
                width_multiplier=[1.5, 1.5, 1.5, 2.75], override_groups_map=None, deploy=deploy)

def create_RepVGG_B0(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[1, 1, 1, 2.5], override_groups_map=None, deploy=deploy)

def create_RepVGG_B1(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[2, 2, 2, 4], override_groups_map=None, deploy=deploy)

def create_RepVGG_B1g2(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[2, 2, 2, 4], override_groups_map=g2_map, deploy=deploy)

def create_RepVGG_B1g4(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[2, 2, 2, 4], override_groups_map=g4_map, deploy=deploy)


def create_RepVGG_B2(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[2.5, 2.5, 2.5, 5], override_groups_map=None, deploy=deploy)

def create_RepVGG_B2g2(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[2.5, 2.5, 2.5, 5], override_groups_map=g2_map, deploy=deploy)

def create_RepVGG_B2g4(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[2.5, 2.5, 2.5, 5], override_groups_map=g4_map, deploy=deploy)


def create_RepVGG_B3(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[3, 3, 3, 5], override_groups_map=None, deploy=deploy)

def create_RepVGG_B3g2(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[3, 3, 3, 5], override_groups_map=g2_map, deploy=deploy)

def create_RepVGG_B3g4(num_classes=1000, deploy=False):
  return RepVGG(num_blocks=[4, 6, 16, 1], num_classes=num_classes,
                width_multiplier=[3, 3, 3, 5], override_groups_map=g4_map, deploy=deploy)


func_dict = {
  'RepVGG-A0': create_RepVGG_A0,
  'RepVGG-A1': create_RepVGG_A1,
  'RepVGG-A2': create_RepVGG_A2,
  'RepVGG-B0': create_RepVGG_B0,
  'RepVGG-B1': create_RepVGG_B1,
  'RepVGG-B1g2': create_RepVGG_B1g2,
  'RepVGG-B1g4': create_RepVGG_B1g4,
  'RepVGG-B2': create_RepVGG_B2,
  'RepVGG-B2g2': create_RepVGG_B2g2,
  'RepVGG-B2g4': create_RepVGG_B2g4,
  'RepVGG-B3': create_RepVGG_B3,
  'RepVGG-B3g2': create_RepVGG_B3g2,
  'RepVGG-B3g4': create_RepVGG_B3g4,
}
def get_RepVGG_func_by_name(name):
  return func_dict[name]

#   Use like this:
#   train_model = get_RepVGG_func_by_name('RepVGG-A0')(deploy=False)
#   train train_model
#   deploy_model = repvgg_convert(train_model, 'RepVGG-A0', save_path='repvgg_deploy.pth')
def repvgg_model_convert(model:RepVGG, model_name, save_path=None):
  converted_weights = {}
  for name, layer in model.get_all_layers().items():
    if hasattr(layer, 'repvgg_convert'):
      kernel, bias = layer.repvgg_convert()
      converted_weights[name + '/conv2d/kernel:0'] = kernel.numpy()
      converted_weights[name + '/conv2d/bias:0'] = bias.numpy()
    elif isinstance(layer, tf.keras.layers.Dense):
      converted_weights[name + '/kernel:0'] = layer.kernel.numpy()
      converted_weights[name + '/bias:0'] = layer.bias.numpy()
    else:
      print(name, type(layer))
  build_func = get_RepVGG_func_by_name(model_name)
  deploy_model = build_func(deploy=True)
  deploy_model.build((None, 160, 160, 3))
  trainable_variables = deploy_model.trainable_variables
  for i, var in enumerate(converted_weights.values()):
    deploy_var = trainable_variables[i]
    deploy_var.assign(var)
    tf.print('deploy param: ', deploy_var.name, deploy_var.shape, tf.math.reduce_mean(deploy_var))

  if save_path is not None:
    deploy_model.save(save_path)

  return deploy_model

def main():
  '''发布demo'''
  m = get_RepVGG_func_by_name('RepVGG-A0')(deploy=False)
  x = tf.random.uniform((1, 160, 160, 3), dtype=tf.float32)
  m.build((None, 160, 160, 3))
  m_deploy = repvgg_model_convert(m, 'RepVGG-A0')
  out1 = m(x, training=False)
  out2 = m_deploy(x, training=False)
  tf.print('out1:', out1['classes'])
  tf.print('out2:', out2['classes'])

if __name__ == '__main__':
  main()

本节内容到此结束,谢谢关注! 

参考资料:

置顶必读(2) | 《YOLOv11实战:从入门到深度优化》目录导航篇(持续更新中) 🏆 本文收录于 《YOLOv11实战:从入门到深度优化》 专栏。 本专栏系统梳理并持续复现全网各类 YOLOv11 / YOLO系列改进方案与实战案例,目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。 内容坚持 持续更新 + 深度拆解 + 工程落地导向,不仅讲“怎么改”,更讲“为什么这样改、如何真正落地到项目中”。 阅读详情

相关推荐

Poly Loss 这一新型损失函数在 YOLOv11 目标检测模型中的应用,从数学原理、代码实现到工程实践,提供了全面的解析和优化指南

摘要 本文深入探讨了YOLOv11目标检测框架中Poly Loss损失函数的创新应用。针对传统交叉熵损失在目标检测任务中的三大困境:前景-背景极度不平衡、难易样本处理不均衡以及收敛速度缓慢,Poly Loss通过多项式展开的数学方法提供了更优解决方案。文章详细解析了Poly Loss的核心原理——基于泰勒展开的对数函数多项式近似,展示了其在梯度调节和样本权重分配上的优势。通过代码示例和可视化分析,对比了Poly Loss与交叉熵损失的性能差异,证实Poly Loss能更有效地处理难样本并加速模型收敛。该技术

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1119

CVPR 2021 速览 | 旷视研究院入选学术成果盘点(下)

在近日正式揭晓论文接收情况的CVPR 2021中,旷视研究院共入选论文22篇,其中Oral论文2篇,研究领域涵盖激活函数、神经网络、神经网络架构搜索、光流估计、无监督学习、人体姿态估计、目...

旷视开发者技术社区 1718

RepVGG:RepVGG

RepVGG:使VGG样式的ConvNets再次变得出色(CVPR-2021)(PyTorch) 这是一个超级简单的ConvNet架构,通过3x3 conv和ReLU的堆栈在ImageNet上实现了80%的top-1精度! 此存储库包含预训练的模型,用于构建模型,训练的代码以及从训练时模型到推理时的转换。 MegEngine版本: : 。 @upczww 使用C ++ API进行TensorRT实现。 做得好! @zjykzj 另一个不错的PyTorch实现。 包含在一个著名的模型动物园中(超过7k星) 。 更新(2021年1月13日):您可以随时以不同的方式获得等效的内核和偏差(repvgg.py中的get_equivalent_kernel_bias)。 这可能有助于基于训练的修剪或量化。 更新(2021年1月31日):此训练脚本(超简单的PyTorch官方示例样式

pytorch实现Parnet猫狗识别

前言 深度是深度神经网络的标志,但深度越大意味着顺序计算越多延迟也越大。这就引出了一个问题——是否有可能构建高性能的“非深度”神经网络?作者实现了一个12层的网络结构实现了top-1 accuracy over 80%on ImageNet的效果。分析网络设计的伸缩规则,并展示如何在不改变网络深度的情况下提高性能。 下面我们就看看作者在论文中是怎么说的吧! 论文地址:https://arxiv.org/abs/2110.07641 1. Introduction(介绍) 人们普遍认为,大深度是高性能网络的重

qq_42025868的博客 1944

RepVGG-Tensorflow-2-main.zip

RepVGG-Tensorflow-2-main.zip

keras vgg 代码实例

keras vgg 训练自己的数据.详细的观看 https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

揭秘RepVGG_b2.rvgg_in1k:让VGG风格卷积网络焕发新生的完整教程

在深度学习计算机视觉领域,**RepVGG_b2.rvgg_in1k** 是一款革命性的图像分类模型,它巧妙地将传统VGG架构与现代深度学习技术相结合,为经典的卷积神经网络注入了全新的活力。这款模型通过创新的结构重参数化技术,在保持推理时单分支结构简单性的同时,实现了训练时多分支结构的优势,是计算机视觉研究和实际应用的理想选择。 ## 🔥 为什么RepVGG_b2.rvgg_in1k如此重要?

gitblog_00308的博客 322

RepVgg实战:使用RepVgg实现图像分类

所谓“VGG式”指的是: 1. 没有任何分支结构。即通常所说的plain或feed-forward架构。 2. 仅使用3x3卷积。 3. 仅使用ReLU作为激活函数。 详见: https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/126516646

RepVGG-B1g4在边缘设备上的部署:移动端和嵌入式系统的优化策略

RepVGG-B1g4是一款基于VGG架构改进的图像分类模型,由论文作者在ImageNet-1k数据集上训练而成。该模型通过timm库的BYOBNet架构实现,兼具高性能与部署灵活性,非常适合在移动端和嵌入式等边缘设备上应用。本文将详细介绍如何针对边缘环境优化RepVGG-B1g4的部署流程,帮助开发者快速实现模型在资源受限设备上的高效运行。 ## 为什么选择RepVGG-B1g4进行边缘部署?

gitblog_01183的博客 442

手把手教你用nRF52832+RFX2401C设计远距离蓝牙模块(附完整原理图/PCB文件)

本文详细介绍了如何利用nRF52832 SoC与RFX2401C射频前端芯片设计远距离蓝牙模块,涵盖芯片选型、阻抗匹配、PCB布局等关键环节。通过实战指南和完整原理图/PCB文件,帮助工程师实现输出功率可达20dBm的蓝牙模块设计,适用于智能家居、运动追踪等物联网应用。

weixin_29214199的博客 287

OPA(运放)与MOS管组成的恒流源电路

电路图 这是一种由运放组成的恒流源电路。 原理分析: 1. OPA OPA (集成运算放大器)具有开源增益高,输入阻抗大,输出阻抗小的特点。 2. MOS管工作原理 我们知道三极管是利用 Ib 的电流控制 IC 的电流,属于电流控制电流器件。 而MOS则是利用Ugs的电压去控制电流 Id 的,所以说 MOS 管是电压控制电流的器件。 对于N沟道增强型的MOS管,当Ugs>Ugs(th)时,MOS就会开始导通,如果在D极和S极之间加上一定的电压,就会有电流Id产生。 在一定的Uds下,D极电流Id的

暖暖_的_纠结的博客 3万+

基于改进YOLO11-EfficientViT的岩石类型识别系统

计算机视觉在物体检测领域取得了显著进展,其中YOLO系列算法因其高效性广泛应用于实时检测场景。本文探讨如何通过结合EfficientViT的注意力机制改进YOLOv11模型,解决传统CNN在岩石识别任务中感受野受限、计算复杂度高等问题。关键技术包括窗口注意力机制、多尺度特征融合和轻量化设计,在保持高精度的同时显著提升推理速度。这类技术在野外地质勘探、矿产资源评估等场景具有重要应用价值,特别是对辉长岩、角闪岩等岩石的自动化识别,能有效提升地质工作效率。实验表明改进后的模型在移动端部署时,推理速度达到95FPS

weixin_30315905的博客 348

华大HC32F460 ADC+DMA高效数据采集实战解析

本文深入解析了华大HC32F460微控制器中ADC与DMA协同工作的高效数据采集方案。通过实战代码演示,详细阐述了如何配置硬件触发、序列扫描及AOS事件联动,实现后台自动采集,从而解放CPU资源,提升系统实时性与可靠性,适用于传感器数据采集、音频处理等多种场景。

weixin_29189373的博客 177

清华开源ResRep:剪枝SOTA!用结构重参数化实现CNN无损压缩 | ICCV 2021

点击下方卡片,关注“CVer”公众号AI/CV重磅干货,第一时间送达作者:丁霄汉 |已授权转载(源:知乎)https://zhuanlan.zhihu.com/p/402106979...

阿木寺的博客 1142

ArcGIS Pro实战:用时空立方体分析共享单车轨迹数据(含3D可视化技巧)

本文详细介绍了在ArcGIS Pro中利用时空立方体技术分析共享单车轨迹数据的全流程。从数据预处理、构建时空立方体,到执行新兴时空热点分析,并最终实现动态3D可视化,手把手教你挖掘城市骑行活动的时空规律。文章重点解析了工具参数设置、常见报错解决方案,并提供了可复用的Python脚本,助力城市规划与交通研究者高效完成时空模式挖掘。

weixin_28323057的博客 137

DIC新手避坑指南:压缩实验中的应变测量常见错误与数据校验技巧

本文为DIC技术新手提供了压缩实验中应变测量的全面避坑指南。文章系统梳理了从试样尺寸录入、散斑质量到数据后处理中应变方向与符号混淆、数据插值对齐等常见错误,并分享了基于MATLAB的自动化数据校验与可视化对比技巧,帮助建立可靠的实验数据分析SOP,确保DIC测量结果的准确性。

weixin_29313423的博客 113

基于YOLO的行人车辆目标检测:从YOLOv5到YOLOv8的全栈实战指南

本文全面介绍了基于YOLO系列模型的行人车辆检测系统构建方法。主要内容包括: YOLO算法原理深度解析 详细讲解了YOLOv1-v8各版本的演进历程和核心创新点 对比分析了不同版本的性能特点和适用场景 完整实践指南 数据集准备与标注转换 模型训练调优全流程 验证评估指标解读 模型导出与部署方案 系统实现 提供可运行的核心代码(train.py/val.py/detect.py等) 基于PyQt5的GUI界面开发 性能优化技巧(FP16/量化/剪枝等) 对比实验 在相同数据集上测试YOLOv5-v8的表现 给

m0_51689679的博客 705

从安装到出图:一份给振动测试新手的LMS Test.Lab 2021完整避坑手册(含许可证更新和常见弹窗解决)

本文为振动测试新手提供LMS Test.Lab 2021的完整使用指南,涵盖安装配置、许可证更新、数据采集到频域后处理的全流程。特别针对常见弹窗错误提供解决方案,并详细讲解Colormap时频图分析技巧,帮助用户快速掌握振动数据分析核心技能。

weixin_29268331的博客 985

CVPR 2021 | RepVGG: Making VGG-style ConvNets Great Again阅读分享(keras实现)

RepVGG: Making VGG-style ConvNets Great Again paper:https://arxiv.org/pdf/2101.03697.pdf code:https://github.com/DingXiaoH/RepVGG 摘要 提出了一个简单而强大的卷积神经网络结构,它具有一个类似VGG的推理时间体,只由3×3卷积和ReLU组成,而训练时间模型有一个多分支拓扑。训练时间和推理时间体系结构的解耦是通过结构再参数化技术实现的,因此该模型被命名为RepVGG。在Ima

u011447962的博客 877

【学习笔记】计算机网络 第八章 无线局域网(WLAN)

计算机网络 第八章 无线局域网(WLAN)

Vera_shsf的博客 1243

PCL 点云按强度渲染颜色【2025最新版】

点云按反射强度渲染颜色,博客长期更新,本文最近更新时间为:2025年1月6日。

点云侠的博客 2万+

keras代码集锦

keras代码集锦

左手coding,右手cooking 839

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

RepVGG:算法简介及repvgg.py代码解析

Make VGG-Style Great Again !

weixin_44808161的博客 3545

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Repvgg详解及其实现(pytorch)

原论文中的结构图很直观的展示了repvgg到底是什么意思,对比Resnet它仍然有着类似残差的结构,就是在3*3的卷积基础上弄了一个1*1的分支和一个identity分支(在步长不等于2且输入输出通道相等的情况下),这样除了方便推理过程的融合,似乎还有多分支的好处,因为有丰富的梯度信息(狗头保命),但是这好像会在训练时增加参数量,但是推理速度快就ok了。这样我们就将三个分支融合成了一个分支,这样的在推理的时候就会非常快,而且很省内存。写这边博客也是为了做一个记录,如果有错误或者不足,请各位大佬提出。

qq_44992785的博客 9748

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【深度学习】经典网络-VGG复现(使用Tensorflow实现)

论文地址:https://arxiv.org/abs/1409.1556 本文所包含代码GitHub地址:https://github.com/shankezh/DL_HotNet_Tensorflow 如果对机器学习有兴趣,不仅仅满足将深度学习模型当黑盒模型使用的,想了解为何机器学习可以训练拟合最佳模型,可以看我过往的博客,使用数学知识推导了机器学习中比较经典的案例,并且使用了python撸...

shankezh的博客 2580
上一篇: 【人工智能笔记】第二十五节 tensorflow 2.0 实现卷积注意力模块
下一篇: 【人工智能笔记】第二十七节 tensorflow 2.0 中保存模型的方式及注意事项
PPHT-H
博客等级 码龄18年 6254粉丝 84原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PPHT-H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值