当前位置: 首页 > news >正文

【RT-DETR有效改进】华为 | Ghostnetv1一种专为移动端设计的特征提取网络

前言

大家好,这里是RT-DETR有效涨点专栏

本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。

专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持ResNet32、ResNet101和PPHGNet版本,其中ResNet为RT-DETR官方版本1:1移植过来的,参数量基本保持一致(误差很小很小),不同于ultralytics仓库版本的ResNet官方版本,同时ultralytics仓库的一些参数是和RT-DETR相冲的所以我也是会教大家调好一些参数和代码,真正意义上的跑ultralytics的和RT-DETR官方版本的无区别。

👑欢迎大家订阅本专栏,一起学习RT-DETR👑   

一、本文介绍

本文给大家带来的特征提取网络是华为 | Ghostnetv1其是一种专为移动端设计的特征提取网络,网络模型非常的小,其推理速度非常快,对于追求极致FPS的读者来说其是一个非常好的选择,其网络效果也是完爆经典模型MobileNet系列的特征提取网络,同时我也将该模型进行了实验其GFLOPs相对于ResNet18的2KW参数下降了接近一半,精度却没有下降太多。同时欢迎大家订阅本专栏,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家。

专栏链接:RT-DETR剑指论文专栏,持续复现各种顶会内容——论文收割机RT-DETR

目录

一、本文介绍

二、GhostNetV1卷积原理

2.1 GhostNet的基本原理

2.2 Ghost Module

 2.3 线性变换

2.4 Ghost Bottlenecks

三、 GhsetNetV1的核心代码

四、手把手教你添加GhsetNetV1

4.1 修改一

4.2 修改二 

4.3 修改三 

4.4 修改四

4.5 修改五

4.6 修改六

4.7 修改七 

4.8 修改八

4.9 RT-DETR不能打印计算量问题的解决

4.10 可选修改

五、GhsetNetV1的yaml文件

5.1 yaml文件

5.2 运行文件

5.3 成功训练截图

六、全文总结


二、GhostNetV1卷积原理

论文地址: 官方论文地址

代码地址: 官方代码地址


2.1 GhostNet的基本原理

华为的GhostNet是一种轻量级卷积神经网络,旨在在计算资源有限的嵌入式设备上实现高性能的图像分类。GhostNet的基本原理包括以下关键概念:

1. Ghost Module(幽灵模块):GhostNet引入了Ghost模块,这是其核心组件。Ghost模块的主要目标是生成更多的特征图,而不会增加过多的计算负担。Ghost模块的设计允许在特征图中引入额外的信息,以提高模型性能。

2. 线性变换:Ghost模块通过应用一系列廉价的线性变换(例如,卷积和标准化)来生成所谓的“幽灵”特征图。这些变换具有较低的计算成本,但可以生成额外的特征图,以丰富模型的表示能力。

3. Ghost Bottlenecks:为了构建GhostNet,可以堆叠多个Ghost模块,形成所谓的Ghost Bottlenecks。这样可以创建深度轻量级网络,适用于嵌入式设备和移动应用。

GhostNet的关键思想在于通过引入Ghost模块,以较低的计算成本增加了特征图的数量,从而提高了模型的性能。这种方法在计算资源有限的情况下,尤其适用于图像分类任务,并在一些基准测试中表现出了很好的性能。 


2.2 Ghost Module

GhostNet中的Ghost Module(幽灵模块)是该网络的关键组件之一,旨在以低计算成本生成更多的特征图,从而提高模型的性能。以下是Ghost Module的主要特点和原理

1. 生成额外特征图:Ghost Module的主要目标是生成额外的特征图,而不会增加大量的计算负担。这些额外的特征图有助于丰富模型的表示能力,提高图像分类性能。

2. 线性变换:Ghost Module使用一系列线性变换来生成这些额外的特征图。这些线性变换通常包括卷积和其他简单的操作,其计算成本远低于传统的卷积操作。这些线性操作 Φ 作用于每个通道,从而生成更多的特征图。

3. 输出特征图:Ghost Module的输出数据Y包括了生成的n个特征图,其中n = m · s,m是Ghost Module输入数据的通道数,s是线性变换的数量。这些特征图可以用于后续的任务,如图像分类。

4. 多种线性操作:在实际应用中,Ghost Module可以包含多种不同的线性操作,例如3×3和5×5的线性核。这些不同的操作可以在实验中进行分析和比较,以确定哪种操作在特定任务上表现最佳。

下图对比了卷积层和提出的Ghost模块:

可以看出Ghost模块与现有的高效卷积方案存在以下差异 :

i) 与1×1逐点卷积单元相比,Ghost模块中的主要卷积可以具有自定义的核大小

ii) 现有方法采用逐点卷积来处理跨通道的特征,然后采用深度卷积来处理空间信息。相比之下,Ghost模块采用普通卷积首先生成一些内在特征图,然后利用廉价的线性操作来增强特征并增加通道数。

iii) 处理每个特征图的操作在先前的高效架构中通常限于深度卷积或移位操作,而Ghost模块中的线性操作可以具有较大的多样性

iv) 此外,在Ghost模块中,恒等映射与线性变换并行使用,以保留内在特征图。

总结:GhostNet中的Ghost Module是一种旨在以低计算成本生成更多特征图的创新组件。它通过引入额外的特征图,丰富了模型的表示能力,提高了性能,特别适用于在计算资源有限的环境中实现高性能的图像分类模型。


 2.3 线性变换

GhostNet中的线性变换用于生成幽灵特征图。Ghost Module通过一系列廉价的线性变换来增强模型的表示能力。

我总结其主要特点和原理如下:

1. 应用于内在特征:线性变换是应用于Ghost Module中已生成的内在特征图(Intrinsic Feature Maps)的。这些内在特征图是由主要卷积操作生成的,通常包含有限数量的特征。

2. 生成幽灵特征:每个内在特征图都会经过一系列线性变换,以生成幽灵特征图。这些幽灵特征图是额外生成的,用于丰富模型的特征表示。

3. 自定义操作:Ghost Module中的线性操作可以具有不同的形式,例如3×3和5×5的线性核。这些不同的操作允许模型根据任务的需要自定义特征生成过程。

5. 保留内在特征:Ghost Module中的最后一个线性变换通常是恒等映射,用于保留内在特征。这确保了生成的幽灵特征与原始特征之间的一致性。

总结:GhostNet中的线性变换是为了通过低成本的操作生成额外的特征,从而提高模型的性能。这种方法在计算资源受限的情况下尤其有用,可以帮助模型更好地处理图像分类等任务。Ghost Module中的线性操作具有灵活性,可以根据具体任务进行调整和优化。


2.4 Ghost Bottlenecks

GhostNet的Ghost Bottlenecks(幽灵瓶颈)专门为小型卷积神经网络(CNNs)设计。Ghost Bottlenecks采用了Ghost Module的概念,并结合了残差块的思想,用于提高模型的性能。

GhostNet中Ghost Bottlenecks的主要特点:

1. 模块组成:Ghost Bottlenecks主要由两个堆叠的Ghost模块组成。这些Ghost模块在Ghost Bottleneck内进行堆叠,以实现更强大的特征提取和表示。

2. 扩展层:第一个Ghost模块充当扩展层,其主要功能是增加通道数。这个扩展层通过增加通道数来增强特征的表示能力,从而有助于提高模型性能。

3. 收缩层:第二个Ghost模块充当收缩层,其主要功能是减少通道数,以与快捷路径匹配。这个步骤有助于控制模型的复杂性,并确保模型在不增加计算负担的情况下能够保持高性能。

4. 快捷连接:Ghost Bottlenecks中还包括快捷连接,它连接在两个Ghost模块的输入和输出之间。这种连接有助于信息的传递和梯度的流动,以更好地训练模型。

5. 非线性激活:在每个Ghost Bottleneck内部,都应用批归一化(BN)和ReLU非线性激活函数。但是,根据MobileNetV2的建议,在第二个Ghost模块之后不使用ReLU。

接下来为大家展示Ghost瓶颈(G-bneck)示意图:

(左边:步幅为1的Ghost瓶颈;右边:步幅为2的Ghost瓶颈) 

Ghost瓶颈在外观上与ResNe中的基本残差块类似,其中集成了多个卷积层和快捷连接。

Ghost瓶颈主要由两个堆叠的Ghost模块组成。

第一个Ghost模块充当扩展层,增加通道数。我们将输出通道数与输入通道数之间的比率称为扩展比。

第二个Ghost模块将通道数减少以匹配快捷路径。然后,将快捷连接连接在这两个Ghost模块的输入和输出之间。在每个层之后都应用批归一化(BN)和ReLU非线性激活函数(但是根据MobileNetV2的建议,在第二个Ghost模块后不使用ReLU。)

总结:Ghost Bottlenecks的设计旨在在小型CNNs中提高性能,并通过Ghost Module的低成本特性减少计算开销。这使得GhostNet成为在计算资源有限的嵌入式设备上实现高性能图像分类的有力选择。 Ghost Bottlenecks的堆叠增加了模型的深度,从而提高了特征的抽象能力,有助于更好地适应各种视觉任务。

三、 GhsetNetV1的核心代码

代码的使用方式看章节四!

import torch
import torch.nn as nn
import torch.nn.functional as F
import math__all__ = ['Ghostnetv1']def _make_divisible(v, divisor, min_value=None):"""This function is taken from the original tf repo.It ensures that all layers have a channel number that is divisible by 8It can be seen here:https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py"""if min_value is None:min_value = divisornew_v = max(min_value, int(v + divisor / 2) // divisor * divisor)# Make sure that round down does not go down by more than 10%.if new_v < 0.9 * v:new_v += divisorreturn new_vdef hard_sigmoid(x, inplace: bool = False):if inplace:return x.add_(3.).clamp_(0., 6.).div_(6.)else:return F.relu6(x + 3.) / 6.class SqueezeExcite(nn.Module):def __init__(self, in_chs, se_ratio=0.25, reduced_base_chs=None,act_layer=nn.ReLU, gate_fn=hard_sigmoid, divisor=4, **_):super(SqueezeExcite, self).__init__()self.gate_fn = gate_fnreduced_chs = _make_divisible((reduced_base_chs or in_chs) * se_ratio, divisor)self.avg_pool = nn.AdaptiveAvgPool2d(1)self.conv_reduce = nn.Conv2d(in_chs, reduced_chs, 1, bias=True)self.act1 = act_layer(inplace=True)self.conv_expand = nn.Conv2d(reduced_chs, in_chs, 1, bias=True)def forward(self, x):x_se = self.avg_pool(x)x_se = self.conv_reduce(x_se)x_se = self.act1(x_se)x_se = self.conv_expand(x_se)x = x * self.gate_fn(x_se)return xclass ConvBnAct(nn.Module):def __init__(self, in_chs, out_chs, kernel_size,stride=1, act_layer=nn.ReLU):super(ConvBnAct, self).__init__()self.conv = nn.Conv2d(in_chs, out_chs, kernel_size, stride, kernel_size//2, bias=False)self.bn1 = nn.BatchNorm2d(out_chs)self.act1 = act_layer(inplace=True)def forward(self, x):x = self.conv(x)x = self.bn1(x)x = self.act1(x)return xclass GhostModule(nn.Module):def __init__(self, inp, oup, kernel_size=1, ratio=2, dw_size=3, stride=1, relu=True):super(GhostModule, self).__init__()self.oup = oupinit_channels = math.ceil(oup / ratio)new_channels = init_channels*(ratio-1)self.primary_conv = nn.Sequential(nn.Conv2d(inp, init_channels, kernel_size, stride, kernel_size//2, bias=False),nn.BatchNorm2d(init_channels),nn.ReLU(inplace=True) if relu else nn.Sequential(),)self.cheap_operation = nn.Sequential(nn.Conv2d(init_channels, new_channels, dw_size, 1, dw_size//2, groups=init_channels, bias=False),nn.BatchNorm2d(new_channels),nn.ReLU(inplace=True) if relu else nn.Sequential(),)def forward(self, x):x1 = self.primary_conv(x)x2 = self.cheap_operation(x1)out = torch.cat([x1,x2], dim=1)return out[:,:self.oup,:,:]class GhostBottleneck(nn.Module):""" Ghost bottleneck w/ optional SE"""def __init__(self, in_chs, mid_chs, out_chs, dw_kernel_size=3,stride=1, act_layer=nn.ReLU, se_ratio=0.):super(GhostBottleneck, self).__init__()has_se = se_ratio is not None and se_ratio > 0.self.stride = stride# Point-wise expansionself.ghost1 = GhostModule(in_chs, mid_chs, relu=True)# Depth-wise convolutionif self.stride > 1:self.conv_dw = nn.Conv2d(mid_chs, mid_chs, dw_kernel_size, stride=stride,padding=(dw_kernel_size-1)//2,groups=mid_chs, bias=False)self.bn_dw = nn.BatchNorm2d(mid_chs)# Squeeze-and-excitationif has_se:self.se = SqueezeExcite(mid_chs, se_ratio=se_ratio)else:self.se = None# Point-wise linear projectionself.ghost2 = GhostModule(mid_chs, out_chs, relu=False)# shortcutif (in_chs == out_chs and self.stride == 1):self.shortcut = nn.Sequential()else:self.shortcut = nn.Sequential(nn.Conv2d(in_chs, in_chs, dw_kernel_size, stride=stride,padding=(dw_kernel_size-1)//2, groups=in_chs, bias=False),nn.BatchNorm2d(in_chs),nn.Conv2d(in_chs, out_chs, 1, stride=1, padding=0, bias=False),nn.BatchNorm2d(out_chs),)def forward(self, x):residual = x# 1st ghost bottleneckx = self.ghost1(x)# Depth-wise convolutionif self.stride > 1:x = self.conv_dw(x)x = self.bn_dw(x)# Squeeze-and-excitationif self.se is not None:x = self.se(x)# 2nd ghost bottleneckx = self.ghost2(x)x += self.shortcut(residual)return xclass GhostNet(nn.Module):def __init__(self, cfgs, num_classes=1000, width=1.0, dropout=0.2):super(GhostNet, self).__init__()# setting of inverted residual blocksself.cfgs = cfgsself.dropout = dropout# building first layeroutput_channel = _make_divisible(16 * width, 4)self.conv_stem = nn.Conv2d(3, output_channel, 3, 2, 1, bias=False)self.bn1 = nn.BatchNorm2d(output_channel)self.act1 = nn.ReLU(inplace=True)input_channel = output_channel# building inverted residual blocksstages = []block = GhostBottleneckfor cfg in self.cfgs:layers = []for k, exp_size, c, se_ratio, s in cfg:output_channel = _make_divisible(c * width, 4)hidden_channel = _make_divisible(exp_size * width, 4)layers.append(block(input_channel, hidden_channel, output_channel, k, s,se_ratio=se_ratio))input_channel = output_channelstages.append(nn.Sequential(*layers))output_channel = _make_divisible(exp_size * width, 4)stages.append(nn.Sequential(ConvBnAct(input_channel, output_channel, 1)))input_channel = output_channelself.blocks = nn.Sequential(*stages)self.width_list = [i.size(1) for i in self.forward(torch.randn(1, 3, 640, 640))]def forward(self, x):unique_tensors = {}x = self.conv_stem(x)x = self.bn1(x)x = self.act1(x)for model in self.blocks:x = model(x)if self.dropout > 0.:x = F.dropout(x, p=self.dropout, training=self.training)width, height = x.shape[2], x.shape[3]unique_tensors[(width, height)] = xresult_list = list(unique_tensors.values())[-4:]return result_listdef Ghostnetv1(**kwargs):"""Constructs a GhostNet model"""cfgs = [# k, t, c, SE, s# stage1[[3,  16,  16, 0, 1]],# stage2[[3,  48,  24, 0, 2]],[[3,  72,  24, 0, 1]],# stage3[[5,  72,  40, 0.25, 2]],[[5, 120,  40, 0.25, 1]],# stage4[[3, 240,  80, 0, 2]],[[3, 200,  80, 0, 1],[3, 184,  80, 0, 1],[3, 184,  80, 0, 1],[3, 480, 112, 0.25, 1],[3, 672, 112, 0.25, 1]],# stage5[[5, 672, 160, 0.25, 2]],[[5, 960, 160, 0, 1],[5, 960, 160, 0.25, 1],[5, 960, 160, 0, 1],[5, 960, 160, 0.25, 1]]]return GhostNet(cfgs, **kwargs)if __name__=='__main__':model = Ghostnetv1()model.eval()input = torch.randn(16,3,224,224)y = model(input)print(y.size())


四、手把手教你添加GhsetNetV1

下面教大家如何修改该网络结构,主干网络结构的修改步骤比较复杂,我也会将task.py文件上传到CSDN的文件中,大家如果自己修改不正确,可以尝试用我的task.py文件替换你的,然后只需要修改其中的第1、2、3、5步即可。

⭐修改过程中大家一定要仔细⭐


4.1 修改一

首先我门中到如下“ultralytics/nn”的目录,我们在这个目录下在创建一个新的目录,名字为'Addmodules'(此文件之后就用于存放我们的所有改进机制),之后我们在创建的目录内创建一个新的py文件复制粘贴进去 ,可以根据文章改进机制来起,这里大家根据自己的习惯命名即可。


4.2 修改二 

第二步我们在我们创建的目录内创建一个新的py文件名字为'__init__.py'(只需要创建一个即可),然后在其内部导入我们本文的改进机制即可,其余代码均为未发大家没有不用理会!


4.3 修改三 

第三步我门中到如下文件'ultralytics/nn/tasks.py'然后在开头导入我们的所有改进机制(如果你用了我多个改进机制,这一步只需要修改一次即可)


4.4 修改四

添加如下两行代码!!!


4.5 修改五

找到七百多行大概把具体看图片,按照图片来修改就行,添加红框内的部分,注意没有()只是函数名(此处我的文件里已经添加很多了后期都会发出来,大家没有的不用理会即可)。

        elif m in {自行添加对应的模型即可,下面都是一样的}:m = m(*args)c2 = m.width_list  # 返回通道列表backbone = True


4.6 修改六

用下面的代码替换红框内的内容。 

if isinstance(c2, list):m_ = mm_.backbone = True
else:m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args)  # modulet = str(m)[8:-2].replace('__main__.', '')  # module type
m.np = sum(x.numel() for x in m_.parameters())  # number params
m_.i, m_.f, m_.type = i + 4 if backbone else i, f, t  # attach index, 'from' index, type
if verbose:LOGGER.info(f'{i:>3}{str(f):>20}{n_:>3}{m.np:10.0f}  {t:<45}{str(args):<30}')  # print
save.extend(x % (i + 4 if backbone else i) for x in ([f] if isinstance(f, int) else f) if x != -1)  # append to savelist
layers.append(m_)
if i == 0:ch = []
if isinstance(c2, list):ch.extend(c2)if len(c2) != 5:ch.insert(0, 0)
else:ch.append(c2)


4.7 修改七 

修改七这里非常要注意,不是文件开头YOLOv8的那predict,是400+行的RTDETR的predict!!!初始模型如下,用我给的代码替换即可!!!

代码如下->

 def predict(self, x, profile=False, visualize=False, batch=None, augment=False, embed=None):"""Perform a forward pass through the model.Args:x (torch.Tensor): The input tensor.profile (bool, optional): If True, profile the computation time for each layer. Defaults to False.visualize (bool, optional): If True, save feature maps for visualization. Defaults to False.batch (dict, optional): Ground truth data for evaluation. Defaults to None.augment (bool, optional): If True, perform data augmentation during inference. Defaults to False.embed (list, optional): A list of feature vectors/embeddings to return.Returns:(torch.Tensor): Model's output tensor."""y, dt, embeddings = [], [], []  # outputsfor m in self.model[:-1]:  # except the head partif m.f != -1:  # if not from previous layerx = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layersif profile:self._profile_one_layer(m, x, dt)if hasattr(m, 'backbone'):x = m(x)if len(x) != 5:  # 0 - 5x.insert(0, None)for index, i in enumerate(x):if index in self.save:y.append(i)else:y.append(None)x = x[-1]  # 最后一个输出传给下一层else:x = m(x)  # runy.append(x if m.i in self.save else None)  # save outputif visualize:feature_visualization(x, m.type, m.i, save_dir=visualize)if embed and m.i in embed:embeddings.append(nn.functional.adaptive_avg_pool2d(x, (1, 1)).squeeze(-1).squeeze(-1))  # flattenif m.i == max(embed):return torch.unbind(torch.cat(embeddings, 1), dim=0)head = self.model[-1]x = head([y[j] for j in head.f], batch)  # head inferencereturn x

4.8 修改八

我们将下面的s用640替换即可,这一步也是部分的主干可以不修改,但有的不修改就会报错,所以我们还是修改一下。


4.9 RT-DETR不能打印计算量问题的解决

计算的GFLOPs计算异常不打印,所以需要额外修改一处, 我们找到如下文件'ultralytics/utils/torch_utils.py'文件内有如下的代码按照如下的图片进行修改,大家看好函数就行,其中红框的640可能和你的不一样, 然后用我给的代码替换掉整个代码即可。

def get_flops(model, imgsz=640):"""Return a YOLO model's FLOPs."""try:model = de_parallel(model)p = next(model.parameters())# stride = max(int(model.stride.max()), 32) if hasattr(model, 'stride') else 32  # max stridestride = 640im = torch.empty((1, 3, stride, stride), device=p.device)  # input image in BCHW formatflops = thop.profile(deepcopy(model), inputs=[im], verbose=False)[0] / 1E9 * 2 if thop else 0  # stride GFLOPsimgsz = imgsz if isinstance(imgsz, list) else [imgsz, imgsz]  # expand if int/floatreturn flops * imgsz[0] / stride * imgsz[1] / stride  # 640x640 GFLOPsexcept Exception:return 0


4.10 可选修改

有些读者的数据集部分图片比较特殊,在验证的时候会导致形状不匹配的报错,如果大家在验证的时候报错形状不匹配的错误可以固定验证集的图片尺寸,方法如下 ->

找到下面这个文件ultralytics/models/yolo/detect/train.py然后其中有一个类是DetectionTrainer class中的build_dataset函数中的一个参数rect=mode == 'val'改为rect=False


五、GhsetNetV1的yaml文件

5.1 yaml文件

大家复制下面的yaml文件,然后通过我给大家的运行代码运行即可,RT-DETR的调参部分需要后面的文章给大家讲,现在目前免费给大家看这一部分不开放。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# RT-DETR-l object detection model with P3-P5 outputs. For details see https://docs.ultralytics.com/models/rtdetr# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n-cls.yaml' will call yolov8-cls.yaml with scale 'n'# [depth, width, max_channels]l: [1.00, 1.00, 1024]backbone:# [from, repeats, module, args]- [-1, 1, GhsetNetV1, []]  # 4head:- [-1, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 5 input_proj.2- [-1, 1, AIFI, [1024, 8]] # 6- [-1, 1, Conv, [256, 1, 1]]  # 7, Y5, lateral_convs.0- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 8- [3, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 9 input_proj.1- [[-2, -1], 1, Concat, [1]] # 10- [-1, 3, RepC3, [256, 0.5]]  # 11, fpn_blocks.0- [-1, 1, Conv, [256, 1, 1]]   # 12, Y4, lateral_convs.1- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 13- [2, 1, Conv, [256, 1, 1, None, 1, 1, False]]  # 14 input_proj.0- [[-2, -1], 1, Concat, [1]]  # 15 cat backbone P4- [-1, 3, RepC3, [256, 0.5]]    # X3 (16), fpn_blocks.1- [-1, 1, Conv, [256, 3, 2]]   # 17, downsample_convs.0- [[-1, 12], 1, Concat, [1]]  # 18 cat Y4- [-1, 3, RepC3, [256, 0.5]]    # F4 (19), pan_blocks.0- [-1, 1, Conv, [256, 3, 2]]   # 20, downsample_convs.1- [[-1, 7], 1, Concat, [1]]  # 21 cat Y5- [-1, 3, RepC3, [256, 0.5]]    # F5 (22), pan_blocks.1- [[16, 19, 22], 1, RTDETRDecoder, [nc, 256, 300, 4, 8, 3]]  # Detect(P3, P4, P5)


5.2 运行文件

大家可以创建一个train.py文件将下面的代码粘贴进去然后替换你的文件运行即可开始训练。

import warnings
from ultralytics import RTDETR
warnings.filterwarnings('ignore')if __name__ == '__main__':model = RTDETR('替换你想要运行的yaml文件')# model.load('') # 可以加载你的版本预训练权重model.train(data=r'替换你的数据集地址即可',cache=False,imgsz=640,epochs=72,batch=4,workers=0,device='0',project='runs/RT-DETR-train',name='exp',# amp=True)


5.3 成功训练截图

下面是成功运行的截图(确保我的改进机制是可用的),已经完成了有1个epochs的训练,图片太大截不全第2个epochs了。 


六、全文总结

从今天开始正式开始更新RT-DETR剑指论文专栏,本专栏的内容会迅速铺开,在短期呢大量更新,价格也会乘阶梯性上涨,所以想要和我一起学习RT-DETR改进,可以在前期直接关注,本文专栏旨在打造全网最好的RT-DETR专栏为想要发论文的读者进行服务。

 专栏链接:RT-DETR剑指论文专栏,持续复现各种顶会内容——论文收割机RT-DETR

相关文章:

【RT-DETR有效改进】华为 | Ghostnetv1一种专为移动端设计的特征提取网络

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…...

45个经典Linux面试题!赶紧收藏!

问题一&#xff1a; 绝对路径用什么符号表示&#xff1f;当前目录、上层目录用什么表示&#xff1f;主目录用什么表示? 切换目录用什么命令&#xff1f; 答案&#xff1a;绝对路径&#xff1a;如/etc/init.d当前目录和上层目录&#xff1a;./ …/主目录&#xff1a;~/切换目…...

将字符串中可能被视为正则表达式的特殊字符进行转义re.escape()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将字符串中可能被视为 正则表达式的特殊字符 进行转义 re.escape() [太阳]选择题 请问以下代码最后输出的结果是&#xff1f; import re s [a-z] print("【显示】s ",s) print(&q…...

C语言:函数指针的使用

在C语言中&#xff0c;函数指针是指向函数的指针变量。它可以存储函数的地址&#xff0c;使得可以通过该指针来调用函数。以下是函数指针的基本概念和用法&#xff1a; 一、基本概念&#xff1a; 声明函数指针&#xff1a; returnType (*pointerName)(parameterTypes); 这里 r…...

「实战应用」如何用DHTMLX Gantt构建类似JIRA式的项目路线图(二)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 在web项目中使用DHTMLX Gantt时&#xff0c;开发人员经常需要满足与UI外观相关的各种需求。因此他们必须确定JavaScript甘特图库的…...

Webpack5入门到原理18:Plugin 原理

Plugin 的作用 通过插件我们可以扩展 webpack&#xff0c;加入自定义的构建行为&#xff0c;使 webpack 可以执行更广泛的任务&#xff0c;拥有更强的构建能力。 Plugin 工作原理 webpack 就像一条生产线&#xff0c;要经过一系列处理流程后才能将源文件转换成输出结果。 这条…...

PWM之舵机

舵机又称直流电机&#xff0c;如下图 本节承接上节&#xff0c;具体的PWM技术已经在上一节讲的很详细了&#xff0c;本节就不再讲了&#xff0c;那么我们的重点就放在直流电机的工作原理上了。 一、工作原理 我们研究直流电机&#xff0c;主要式研究直流电机旋转速度的调节&a…...

Python并发与多线程:IO并发(阻塞IO、非阻塞IO、IO多路复用、异步IO)

在Python中&#xff0c;有多种处理并发的方式&#xff0c;其中之一就是使用多线程进行IO并发操作。在IO操作中&#xff0c;有四种常见的方式&#xff1a;阻塞IO、非阻塞IO、IO多路复用和异步IO。 阻塞IO&#xff08;Blocking IO&#xff09;&#xff1a;当执行一个IO操作时&…...

React16源码: React中的IndeterminateComponent的源码实现

IndeterminateComponent 1 &#xff09;概述 这是一个比较特殊的component的类型&#xff0c; 就是还没有被指定类型的component在一个fibrer被创建的时候&#xff0c;它的tag可能会是 IndeterminateComponent在 packages/react-reconciler/src/ReactFiber.js 中&#xff0c;有…...

SpringBoot:详解Bean生命周期和作用域

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、生命周期二…...

【图解数据结构】顺序表实战指南:手把手教你详细实现(超详细解析)

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;图解数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️线性表1.1 &#x1f514;线性表的定义1.2 &#x1f514;线性表的存储结构 二. ⛳️顺序表…...

WordPress怎么禁用文章和页面古腾堡块编辑器?如何恢复经典小工具?

现在下载WordPress最新版来搭建网站&#xff0c;默认的文章和页面编辑器&#xff0c;以及小工具都是使用古腾堡编辑器&#xff08;Gutenberg块编辑器&#xff09;。虽然有很多站长说这个编辑器很好用&#xff0c;但是仍然有很多站长用不习惯&#xff0c;觉得操作太难了&#xf…...

【HarmonyOS】掌握布局组件,提升应用体验

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…...

第4周:Pytorch——综合应用和实战项目 Day 28-30: 学习资源和社区参与

第4周&#xff1a;综合应用和实战项目 Day 28-30: 学习资源和社区参与 在这个阶段&#xff0c;我们将探索更多的学习资源并鼓励参与PyTorch和TensorFlow的社区&#xff0c;以进一步提升技术和融入开发者社群。 学习资源&#xff1a; 论文&#xff1a;阅读最新的机器学习和深度…...

TypeScript教程(一)在vscode中的配置TypeScript环境

TypeScript教程&#xff08;一&#xff09;在vscode中的配置TypeScript环境 文章目录 TypeScript教程&#xff08;一&#xff09;在vscode中的配置TypeScript环境一、前言二、具体步骤1、Node.js安装2、TypeScript安装3、helloworld 一、前言 未来的开发者们请上座&#xff0c…...

sshpass的安装与使用

一.简介 1.定义&#xff1a; ssh 登陆不能在命令行中指定密码&#xff0c;sshpass 的出现则解决了这一问题。它允许你用 -p 参数指定明文密码&#xff0c;然后直接登录远程服务器&#xff0c;它支持密码从命令行、文件、环境变量中读取。 2.使用 sshpass 原因 使用 sshpass…...

Excel·VBA合并工作簿2

其他合并工作簿的方法&#xff0c;见之前的文章《ExcelVBA合并工作簿》 目录 8&#xff0c;合并文件夹下所有工作簿中所有工作表&#xff0c;按表头汇总举例 8&#xff0c;合并文件夹下所有工作簿中所有工作表&#xff0c;按表头汇总 与之前的文章《ExcelVBA合并工作簿&#x…...

linux内核原理--分页,页表,内核线性地址空间,伙伴系统,内核不连续页框分配,内核态小块内存分配器

1.分页&#xff0c;页表 linux启动阶段&#xff0c;最初运行于实模式&#xff0c;此阶段利用段寄存器&#xff0c;段内偏移&#xff0c;计算得到物理地址直接访问物理内存。 内核启动后期会切换到保护模式&#xff0c;此阶段会开启分页机制。一旦开启分页机制后&#xff0c;内…...

【MongoDB】下载安装、指令操作

目录 1.下载安装 2.指令 2.1.基础操作指令 2.2.增加 2.3.查询 2.4.修改 2.5.删除 前言&#xff1a; 关于MongoDB的核心概念请移步&#xff1a; 【文档数据库】ES和MongoDB的对比-CSDN博客 1.下载安装 本文以安装Windows版本的mongodb为例&#xff0c;Linux版本的其实…...

k8s-pvc/pv扩容记录

背景 一次聊天过程中&#xff0c;对方提及pvc的扩容&#xff0c;虽然有注意过 storageclass 有个AllowVolumeExpansion的配置&#xff08;有些csi插件是不支持该配置的&#xff0c;比如local-volume-provisoner&#xff09;&#xff0c;但是没有实际用过&#xff0c;所以还是心…...

关于Unity插件TriLib使用的一点儿心得

最近做一个项目的时候&#xff0c;由于要求动态加载fbx或者glb等格式文件&#xff0c;而我们自己开发加载插件难度又有点大&#xff0c;所以最后使用了TriLib这个插件&#xff0c;现在说一点使用心得。 由于文件加载之后要对加载的内容进行复制&#xff0c;比如加载一个柱子&am…...

计算机二级Python基本排序题-序号45(补充)

1. 文件"singup.txt”中保存了若干条参加运动会学生的报名记录&#xff0c;每条记录的形式为“班级号_学号”&#xff0c;例如"A1_12”&#xff0c;将每个班级报名情按参加运动会人数从多到少排列&#xff08;假设不存在人数相同的情况&#xff09;并输出&#xff0c…...

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-6 fieldset

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>fieldset</title> </head><body> <form action"#"><fieldset><legend>学生信息</legend>姓名&#xff1a;&…...

html渲染优先级

在前端开发中&#xff0c;优先布局是指在设计和构建页面时&#xff0c;将页面的各个部分按照其重要性和优先级进行排序&#xff0c;并依次进行布局和开发。这种方法可以帮助开发团队在项目初期就确定页面结构的核心部分&#xff0c;从而更好地掌控项目的整体进度和优先级。且确…...

linux 更新镜像源

打开终端&#xff0c;备份一下旧的 源 文件&#xff0c;以防万一 cd /etc/apt/ ls sudo cp sources.list sources.list.bak ls然后打开清华大学开源软件镜像站 搜索一下你的linux发行版本&#xff0c;我这里是ubuntu发行版本 点击这个上面图中的问号 查看一下自己的版本号&a…...

【征服Redis12】redis的主从复制问题

从现在开始&#xff0c;我们来讨论redis集群的问题&#xff0c;在前面我们介绍了RDB和AOF两种同步机制&#xff0c;那你是否考虑过这两个机制有什么用呢&#xff1f;其中的一个重要作用就是为了集群同步设计的。 Redis是一个高性能的键值存储系统&#xff0c;广泛应用于Web应用…...

php函数 一

一 自动加载 1.1 __autoload(string $class) 类自动加载&#xff0c;7.2版本之后废弃。可使用sql_autoload_register()注册方法实现。 类自动加载&#xff0c;无返回值。 #php7.2之前function __autoload($class) {if(strpos($class, CI_) ! 0){if (file_exists(APPPATH . …...

监督学习 - 梯度提升回归(Gradient Boosting Regression)

什么是机器学习 梯度提升回归&#xff08;Gradient Boosting Regression&#xff09;是一种集成学习方法&#xff0c;用于解决回归问题。它通过迭代地训练一系列弱学习器&#xff08;通常是决策树&#xff09;来逐步提升模型的性能。梯度提升回归的基本思想是通过拟合前一轮模…...

【工具】使用ssh进行socket5代理

文章目录 shellssh命令详解正向代理&#xff1a;反向代理&#xff1a;本地 socks5 代理 shell ssh -D 3333 root192.168.0.11 #输入密码 #3333端口已经使用远程机进行转发设置Windows全局代理转发 socks127.0.0.1 3333如果远程机为公网ip&#xff0c;可通过搜索引擎查询出网…...

(delphi11最新学习资料) Object Pascal 学习笔记---第2章第六节(类型转换)

Object Pascal 学习笔记&#xff0c;Delphi 11 编程语言的完整介绍 作者: Marco Cantu 笔记&#xff1a;豆豆爸 2.6 类型转换和类型转换 ​ 正如我们所见&#xff0c;不能将一种数据类型的变量赋值给另一种类型的变量。原因在于&#xff0c;根据数据的实际表示&#xff0c;你…...