神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(一)
带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。系。 2.YOLOv8介绍改进点:Backbone:使用的依旧是CSP的思想,不过YOLOv5中的C3模块被替换成了C2f模块,实现了进一步的轻量化,同时YOLOv8依旧使用了YOLOv5等架构中使用的SPPF模块;PAN-FPN:毫无疑问YOLOv8依旧使用了PAN的思想,不过通过对比YOLOv5与YOLOv8的结构图可以看到,YOLOv8将YOLOv5中PAN-FPN上采样阶段中的卷积结构删除了,同时也将C3模块替换为了C2f模块;Decoupled-Head:是不是嗅到了不一样的味道?是的YOLOv8走向了Decoupled-Head;YOLOv8抛弃了以往的Anchor-Base,使用了Anchor-Free的思想;损失函数:YOLOv8使用VFL Loss作为分类损失,使用DFL Loss+CIOU Loss作为分类损失;样本匹配:YOLOv8抛弃了以往的IOU匹配或者单边比例的分配方式,而是使用了Task-Aligned Assigner匹配方式。2.1 C2f模块介绍C2f模块就是参考了C3模块以及ELAN的思想进行的设计,让YOLOv8可以在保证轻量化的同时获得更加丰富的梯度流信息。 代码:class C2f(nn.Module):
# CSP Bottleneck with 2 convolutions
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
self.c = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).split((self.c, self.c), 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1))3.训练可视化分析YOLOv8 summary (fused): 168 layers, 3005843 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 10/10 [00:18<00:00, 1.90s/it]
all 582 6970 0.816 0.676 0.745 0.385训练结果如下:P_curve.png表示准确率与置信度的关系图线,横坐标置信度。由下图可以看出置信度越高,准确率越高。PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。 R_curve.png召回率与置信度之间关系,具体参照 P_curve。results.png(1,1),(2,1):该图分别表示训练时和验证时ClOU损失函数的均值,越小方框越准。(1,2),(2,2):推测为目标检测loss均值,越小目标越准。(2,4),(2,5):表示在不同IoU阈值时计算每一类中所有图片的AP然后所有类别求取均值。mAP_0.5:0.95表示从0.5到0.95以0.05的步长上的平均mAP.
神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(六):SPD-Conv,低分辨率图像和小物体等更困难任务
本文改进: 新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互;如何在YOLOv8下使用:1)作为注意力机制放在各个网络位置;2)与C2f结合替代原始的C2fMSCA多尺度特性在交通摄像头下车辆检测项目中, mAP50从原始的0.745提升至0.756学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。系。 2.论文简介 论文:https://arxiv.org/pdf/2208.03641v1.pdfgithub:SPD-Conv/YOLOv5-SPD at main · LabSAINT/SPD-Conv · GitHub摘要:卷积神经网络(CNNs)在计算即使觉任务中如图像分类和目标检测等取得了显著的成功。然而,当图像分辨率较低或物体较小时,它们的性能会灾难性下降。这是由于现有CNN常见的设计体系结构中有缺陷,即使用卷积步长和/或池化层,这导致了细粒度信息的丢失和较低效的特征表示的学习。为此,我们提出了一个名为SPD-Conv的新的CNN构建块来代替每个卷积步长和每个池化层(因此完全消除了它们)。SPD-Conv由一个空间到深度(SPD)层和一个无卷积步长(Conv)层组成,可以应用于大多数CNN体系结构。我们从两个最具代表性的计算即使觉任务:目标检测和图像分类来解释这个新设计。然后,我们将SPD-Conv应用于YOLOv5和ResNet,创建了新的CNN架构,并通过经验证明,我们的方法明显优于最先进的深度学习模型,特别是在处理低分辨率图像和小物体等更困难的任务时。1.1 SPD- convSPD- conv由一个空间到深度(SPD)层和一个非跨步卷积层组成。SPD组件推广了一种(原始)图像转换技术[29]来对CNN内部和整个CNN的特征映射进行下采样:1.2 Yolov5-SPD网络结构图只需更换YOLOv5 stride-2卷积层即可得到YOLOv5- SPD,用SPD-Conv构建块取代原有卷积。有7个这样的替换实例,因为YOLOv5在主干中使用5个stride-2卷积层对特征图进行25倍的下采样,在neck使用2个stride-2卷积层。在YOLOv5 neck中,每一次步长卷积后都有一个连接层;这并没有改变我们的方法,我们只是将其保持在SPD和Conv之间。YOLOv5-SPD提供多个版本:YOLOv5-SPD性能: 我们比较YOLOv5-SPD-m和YOLOv5m,因为后者是相应(中等)类别中所有基准模型中性能最好的。图5(a)(b)表明YOLOv5-SPD-m能够检测到被遮挡的长颈鹿,YOLOv5m没有检测到,图5(c)(d)显示YOLOv5-SPD-m检测到非常小的目标(一张脸和两个长凳),而YOLOv5m检测不到。源码详见:YOLOv8改进:小目标涨点系列篇 | SPD-Conv,低分辨率图像和小物体等更困难任务涨点明显-CSDN博客3.训练可视化分析 mAP50从原始的0.745提升至0.802YOLOv8_SPD summary (fused): 174 layers, 3451283 parameters, 0 gradients, 50.9 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 37/37 [00:22<00:00, 1.68it/s]
all 582 6970 0.828 0.742 0.802 0.416训练结果如下:PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。文章知识点与官方知识档案匹配,可进一步学习相关知识
神机妙算
halcon学习和实践(svm模型训练实战)
在halcon软件中,除了可以做传统的视觉分析、物体测量之外,另外一个重要的功能就是ocr。说到ocr,也就是光学字符识别,就不得不谈到机器学习和深度学习。虽然深度学习有着很好的识别效果,但是本身对样本的要求也很多,比如就需要足够多的训练样本。而传统的机器学习,识别的原理、方法具有很强的物理意义,也就是说方法本身是可以说清楚为什么会出现这个识别效果的,在特定的应用场景也同样发挥着重要的作用。 目前halcon软件中本身提供了很多的模型,当然这些模型不能覆盖所有的场景,所以本身也提供了模型训练的方法,这边可以找个例子看一下。事实上,开源软件中,比如python的sklearn同样提供了基础的机器学习算法,大家也可以学习一下。 这里不失一般性,可以选用train_characters_ocr.hdev这个文件来进行分析,* This example program trains a font that consists
* of the characters A to G. The font is used in
* the example program classify_characters_ocr.hdev
* to read the corresponding characters.
*
read_image (Image, 'ocr/chars_training_01.png')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
set_display_font (WindowHandle, 12, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (2)
dev_display (Image)
dev_update_window ('off')
dev_update_pc ('off')
dev_update_var ('off')
*
* Create an SVM classifier for the characters A to G
ClassNames := ['A','B','C','D','E','F','G']
create_ocr_class_svm (8, 10, 'constant', ['convexity','num_holes','projection_horizontal','projection_vertical'], ClassNames, 'rbf', 0.02, 0.05, 'one-versus-one', 'normalization', 10, OCRHandle)
*
* Read the training images and store the regions
* of the characters to a training file
for I := 1 to 7 by 1
read_image (Image, 'ocr/chars_training_' + I$'.2d')
dev_display (Image)
get_regions (Image, SortedRegions)
count_obj (SortedRegions, NumberObjects)
for J := 1 to NumberObjects by 1
select_obj (SortedRegions, ObjectSelected, J)
if (I == 1 and J == 1)
write_ocr_trainf (ObjectSelected, Image, ClassNames[J - 1], 'train_characters_ocr.trf')
else
append_ocr_trainf (ObjectSelected, Image, ClassNames[J - 1], 'train_characters_ocr.trf')
endif
dev_set_color ('gray')
dev_display (ObjectSelected)
disp_message (WindowHandle, ClassNames[J - 1], 'window', 10, 10 + (J * 20), 'black', 'true')
* stop ()
endfor
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endfor
*
* Check if the content of the training file is correct
read_ocr_trainf (Characters, 'train_characters_ocr.trf', CharacterNames)
count_obj (Characters, NumberCharacters)
for I := 1 to NumberCharacters by 1
select_obj (Characters, CharacterSelected, I)
dev_clear_window ()
dev_display (CharacterSelected)
disp_message (WindowHandle, CharacterNames[I - 1], 'window', 10, 10, 'black', 'true')
* stop ()
endfor
*
* Train the font, write the font to file,
* and clear the classifier from memory
trainf_ocr_class_svm (OCRHandle, 'train_characters_ocr.trf', 0.001, 'default')
reduce_ocr_class_svm (OCRHandle, 'bottom_up', 2, 0.001, OCRHandleReduced)
write_ocr_class_svm (OCRHandleReduced, 'font_characters_ocr')
*
clear_ocr_class_svm (OCRHandle)
clear_ocr_class_svm (OCRHandleReduced) 因为涉及到的代码较多,这里分析的主要是涉及svm的几个函数, 第20行,create_ocr_class_svm,准备创建一个svm模型, 第32行,write_ocr_trainf,将训练文件写入train_characters_ocr.trf, 第34行,append_ocr_trainf,将训练文件添加到append_ocr_trainf.trf, 第58行,trainf_ocr_class_svm,开始训练svm模型, 第59行,reduce_ocr_class_svm,优化裁剪svm模型, 第60行,write_ocr_class_svm,保存生成的svm模型,模型名为font_characters_ocr, 第62行,clear_ocr_class_svm,关闭初始生成svm模型句柄, 第63行,clear_ocr_class_svm,关闭优化裁剪svm模型句柄。 初始学习的时候,主要有两个方面需要注意下。第一个,就是训练svm模型的流程。一开始的时候可能难以理解,个中的参数也不知道什么意义,这个可以在后续的学习过程中不断演进。第二个,就是了解append_ocr_trainf.trf、font_characters_ocr这两个最重要的参数,前者是为了准备训练文件,后者是生成的模型名。模型生成之后,就不需要再次训练了,只需要每次加载font_characters_ocr这个模型,就可以开始分类预测了。以上就是需要注意的两个地方。
神机妙算
halcon学习和实践(ocr识别)
ocr是工业视觉里面重要的一个环节。大家可以试想一下,目前工业视觉里面,除了定位和测量、残次品识别之外,另外一个重要的应用领域就是ocr。ocr,全称是optical character recognition,也就是光学字符识别。比如,别人已经贴好的标签,打印好的文字、发票,身份证信息,这些都可以用ocr识别的算法来解决。 目前识别的方法主要有两种,一种是传统的机器学习算法,这部分有决策树、多层感知机、svm算法等等;另外一种就是基于cnn、rnn的深度学习,虽然算法本身类似于黑盒,但是识别效果很好,目前使用的也越来越多。当然,不管是哪种算法,都要包含这样几个步骤, 1、挑选好一定数量的样本,一般来说,样本越多越好; 2、将样本分成训练集和测试集,训练集是专门用于训练使用,测试集是训练后使用; 3、将训练好的模型部署到现场,进行实际生产的使用。 在halcon的样例代码中,也包含了很多的ocr用例,ocr_wafer_semi_font.hdev就是其中一个。今天可以分析一下这个算法,*
* This example describes one step from the semiconductor product chain.
* In the front-end-of-line step, the ICs are printed on the wafer. To
* tag a single wafer from the production life line, each wafer receives
* an ID number, printed with the SEMI font. This ID number is read here.
*
dev_update_off ()
dev_close_window ()
read_image (Image, 'ocr/wafer_semi_font_01')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_set_draw ('margin')
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (2)
dev_set_colored (12)
*
read_ocr_class_mlp ('SEMI_NoRej.omc', OCRHandle)
NumImages := 10
for Index := 1 to NumImages by 1
*
* Segment characters
read_image (Image, 'ocr/wafer_semi_font_' + Index$'02')
* Characters must be black-on-white, i.e., dark characters on a light background
invert_image (Image, ImageInvert)
mean_image (Image, ImageMean, 31, 31)
dyn_threshold (Image, ImageMean, RegionDynThresh, 7, 'light')
* Characters are often dotted. Therefore, we first merge close dots
* that belong to the same character just before calling the operator connection
closing_circle (RegionDynThresh, RegionClosing, 2.0)
connection (RegionClosing, ConnectedRegions)
* Filter out characters based on two facts:
* 1. Characters are printed in SEMI-12. Therefore we can make strong assumptions
* on the dimensions of the characters
* 2. Characters are printed along a straight line
select_shape (ConnectedRegions, SelectedRegions1, ['height','width'], 'and', [29,15], [60,40])
area_center (SelectedRegions1, Area, RowCh, ColumnCh)
MedianRow := median(RowCh)
select_shape (SelectedRegions1, Chars, 'row', 'and', MedianRow - 30, MedianRow + 30)
*
* Read out segmented characters
enhance_contrast (Chars, ImageInvert, ImageRead)
sort_region (Chars, CharsSorted, 'character', 'true', 'column')
do_ocr_multi_class_mlp (CharsSorted, ImageRead, OCRHandle, Class, Confidence)
*
dev_display (ImageInvert)
dev_display (CharsSorted)
area_center (CharsSorted, Area1, Row, Column)
MeanRow := mean(Row)
disp_message (WindowHandle, Class, 'image', MeanRow + 42, Column - 11, 'yellow', 'false')
disp_message (WindowHandle, Class, 'image', MeanRow + 40, Column - 10, 'slate blue', 'false')
if (Index != NumImages)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor
clear_ocr_class_mlp (OCRHandle) 整个代码有55行,下面开始逐步进行分析。 代码从第7行开始,第7行到第14行的部分主要是验证一下图片是否可以读出。这里挑选了一张图片进行读取检验。因为后续循环的时候会不断读取图片,所以在此之前先用一张图片试试水,确保图片的读取路径没有问题。当然,中间还对字体、线宽、颜色做了设置。 第16行,读入OCRHandle,可以理解为加载好训练的模型。 第17-18行,开始准备循环读入图片,总共10张, 第21行,读取图片, 第23行,反转图片,主要是像素反转, 第24行,中值滤波, 第25行,二值化处理, 第28行,闭运算, 第29行,图像分割, 第34行,根据高度和宽度筛选合适的区域, 第35-37行,先计算一个平均高度,然后在平均高度的(-30,30)范围内筛选, 第40行,图像增强, 第41行,对应区域根据列排序, 第42行,利用之前读到的OCRHandle识别, 第44-49行,显示图片,显示识别好的字符, 第51行,显示continue信息, 第52行,暂停运行,直到输入F5, 第55行,卸载识别模型OCRHandle。 上面就是识别的基本流程。如果有了对应的模型,那么识别是比较简单的一件事情,所要做的就是把对应的字符分割出来。如果没有这个模型,就需要自己训练模型了,这个相对来说是比较麻烦的一件事情。
神机妙算
YOLOv8优化:注意力系列篇 | 瓶颈注意力模块BAM,效果秒杀CBAM、SE
🚀🚀🚀本文改进:BAM注意力,引入到YOLOv8,多种实现方式🚀🚀🚀BAM在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.BAM介绍 摘要:提出了一种简单有效的注意力模块,称为瓶颈注意力模块(BAM),可以与任何前馈卷积神经网络集成。我们的模块沿着两条独立的路径,通道和空间,推断出一张注意力图。我们将我们的模块放置在模型的每个瓶颈处,在那里会发生特征图的下采样。我们的模块用许多参数在瓶颈处构建了分层注意力,并且它可以以端到端的方式与任何前馈模型联合训练。我们通过在CIFAR-100、ImageNet-1K、VOC 2007和MS COCO基准上进行大量实验来验证我们的BAM。我们的实验表明,各种模型在分类和检测性能上都有持续的改进,证明了BAM的广泛适用性。 作者将BAM放在了Resnet网络中每个stage之间。有趣的是,通过可视化我们可以看到多层BAMs形成了一个分层的注意力机制,这有点像人类的感知机制。BAM在每个stage之间消除了像背景语义特征这样的低层次特征,然后逐渐聚焦于高级的语义–明确的目标。 作者提出了新的Attention模型——瓶颈注意模块,通过分离的两个路径channel和spatial得到attention map,减少计算开销和参数开销。实验 BAM可以在大规模数据集中的各种模型上有很好的泛化能力,同时参数和计算的开销可以忽略不计,这表明提出的模块BAM可以有效地提高网络容量。另一个值得注意的是,改进的性能来自于只在网络中放置三个模块。 BAM提高了所有具有两个骨干网络的强大基线的准确性.BAM的准确率提高是以可忽略不计的参数开销实现的,这表明提高不是由于天真的容量增加,而是由于我们有效的特征细化。2.BAM加入YOLOv82.1加入ultralytics/nn/attention/attention.py
###################### BAM attention #### START ###############################
import torch
from torch import nn
import torch.nn.functional as F
class ChannelGate(nn.Module):
def __init__(self, channel, reduction=16):
super().__init__()
self.avgpool = nn.AdaptiveAvgPool2d(1)
self.mlp = nn.Sequential(
nn.Linear(channel, channel // reduction),
nn.ReLU(inplace=True),
nn.Linear(channel // reduction, channel)
)
self.bn = nn.BatchNorm1d(channel)
def forward(self, x):
b, c, h, w = x.shape
y = self.avgpool(x).view(b, c)
y = self.mlp(y)
y = self.bn(y).view(b, c, 1, 1)
return y.expand_as(x)
class SpatialGate(nn.Module):
def __init__(self, channel, reduction=16, kernel_size=3, dilation_val=4):
super().__init__()
self.conv1 = nn.Conv2d(channel, channel // reduction, kernel_size=1)
self.conv2 = nn.Sequential(
nn.Conv2d(channel // reduction, channel // reduction, kernel_size, padding=dilation_val,
dilation=dilation_val),
nn.BatchNorm2d(channel // reduction),
nn.ReLU(inplace=True),
nn.Conv2d(channel // reduction, channel // reduction, kernel_size, padding=dilation_val,
dilation=dilation_val),
nn.BatchNorm2d(channel // reduction),
nn.ReLU(inplace=True)
)
self.conv3 = nn.Conv2d(channel // reduction, 1, kernel_size=1)
self.bn = nn.BatchNorm2d(1)
def forward(self, x):
b, c, h, w = x.shape
y = self.conv1(x)
y = self.conv2(y)
y = self.conv3(y)
y = self.bn(y)
return y.expand_as(x)
class BAM(nn.Module):
def __init__(self, channel):
super(BAM, self).__init__()
self.channel_attn = ChannelGate(channel)
self.spatial_attn = SpatialGate(channel)
def forward(self, x):
attn = F.sigmoid(self.channel_attn(x) + self.spatial_attn(x))
return x + x * attn
###################### BAM attention #### END ############################### 2.2 修改tasks.py首先BAM进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 elif m is BAM:
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]] 2.3 yaml实现2.3.1 yolov8_BAM.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, BAM, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_BAM2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, BAM, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, BAM, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, BAM, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.3 yolov8_BAM3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, BAM, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, BAM, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, BAM, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, BAM, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
基于YOLOv8的人脸检测小目标识别算法
1.人脸识别小目标数据集介绍本文章主要通过小目标来进行优化,因此数据集只选择partA部分,总共 2000张,按照7:2:1随机进行分配;下图可以看出都是小目标人脸识别 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。2.YOLOv8介绍改进点:Backbone:使用的依旧是CSP的思想,不过YOLOv5中的C3模块被替换成了C2f模块,实现了进一步的轻量化,同时YOLOv8依旧使用了YOLOv5等架构中使用的SPPF模块;PAN-FPN:毫无疑问YOLOv8依旧使用了PAN的思想,不过通过对比YOLOv5与YOLOv8的结构图可以看到,YOLOv8将YOLOv5中PAN-FPN上采样阶段中的卷积结构删除了,同时也将 C3模块替换为了C2f模块;Decoupled-Head:是不是嗅到了不一样的味道?是的YOLOv8走向了Decoupled-Head;YOLOv8抛弃了以往的Anchor-Base,使用了Anchor-Free的思想;损失函数:YOLOv8使用VFL Loss作为分类损失,使用DFL Loss+CIOU Loss作为分类损失;样本匹配:YOLOv8抛弃了以往的IOU匹配或者单边比例的分配方式,而是使用了Task-Aligned Assigner匹配方式。2.1 C2f模块介绍C2f模块就是参考了C3模块以及ELAN的思想进行的设计,让YOLOv8可以在保证轻量化的同时获得更加丰富的梯度流信息。 代码:class C2f(nn.Module):
# CSP Bottleneck with 2 convolutions
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
self.c = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).split((self.c, self.c), 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1))3.训练可视化分析YOLOv8 summary (fused): 168 layers, 3005843 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 17/17 [00:37<00:00, 2.21s/it]
all 540 18086 0.912 0.885 0.929 0.43训练结果如下:P_curve.png表示准确率与置信度的关系图线,横坐标置信度。由下图可以看出置信度越高,准确率越高。PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。 R_curve.png召回率与置信度之间关系,具体参照 P_curve。results.png(1,1),(2,1):该图分别表示训练时和验证时ClOU损失函数的均值,越小方框越准。(1,2),(2,2):推测为目标检测loss均值,越小目标越准。(2,4),(2,5):表示在不同IoU阈值时计算每一类中所有图片的AP然后所有类别求取均值。mAP_0.5:0.95表示从0.5到0.95以0.05的步长上的平均mAP.
神机妙算
YOLOv8优化:注意力系列篇 |SimAM无参Attention,效果秒杀CBAM、SE
🚀🚀🚀本文改进:SimAM注意力,引入到YOLOv8,多种实现方式🚀🚀🚀SimAM在不同检测领域中应用广泛 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.SimAM链接: http://proceedings.mlr.press/v139/yang21o/yang21o.pdf SimAM(Simple Attention Mechanism)是一种轻量级的自注意力机制,其网络结构与Transformer类似,但是在计算注意力权重时使用的是线性层而不是点积。其网络结构如下:输入序列 -> Embedding层 -> Dropout层 -> 多层SimAM层 -> 全连接层 -> Softmax层 -> 输出结果其中,SimAM层由以下几个部分组成:多头注意力层:输入序列经过多个线性映射后,分成多个头,每个头计算注意力权重。残差连接层:将多头注意力层的输出与输入序列相加,保证信息不会丢失。前向传递层:对残差连接层的输出进行线性变换和激活函数处理,再与残差连接层的输出相加。归一化层:对前向传递层的输出进行层归一化处理,加速训练并提高模型性能。通过多层SimAM层的堆叠,模型可以学习到输入序列中的长程依赖关系,并生成对应的输出序列。2.SimAM加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### PolarizedSelfAttention #### start ###############################
import torch
import torch.nn as nn
from torch.nn import functional as F
class SimAM(torch.nn.Module):
def __init__(self, e_lambda=1e-4):
super(SimAM, self).__init__()
self.activaton = nn.Sigmoid()
self.e_lambda = e_lambda
def __repr__(self):
s = self.__class__.__name__ + '('
s += ('lambda=%f)' % self.e_lambda)
return s
@staticmethod
def get_module_name():
return "simam"
def forward(self, x):
b, c, h, w = x.size()
n = w * h - 1
x_minus_mu_square = (x - x.mean(dim=[2, 3], keepdim=True)).pow(2)
y = x_minus_mu_square / (4 * (x_minus_mu_square.sum(dim=[2, 3], keepdim=True) / n + self.e_lambda)) + 0.5
return x * self.activaton(y)
###################### PolarizedSelfAttention #### end ############################### 2.2 修改tasks.py首先SimAM进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 #####attention ####
elif m is SimAM:
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]]
#####attention #### 2.3 yaml实现2.3.1 yolov8_SimAM.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, SimAM, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.2 yolov8_SimAM2.yaml
neck里的连接Detect的3个C2f结合
# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, SimAM, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, SimAM, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, SimAM, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.3 yolov8_SimAM3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, SimAM, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, SimAM, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, SimAM, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, SimAM, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 | 全局注意力机制(GAM),CBAM升级版
🚀🚀🚀本文改进:GAM注意力,引入到YOLOv8,多种实现方式🚀🚀🚀GAM在不同检测领域中应用广泛 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.GAM注意力介绍摘要:人们已经研究了各种注意力机制来提高各种计算机视觉任务的性能。 然而,现有方法忽视了保留通道和空间方面的信息以增强跨维度交互的重要性。 因此,我们提出了一种全局注意力机制,通过减少信息减少和放大全局交互表示来提高深度神经网络的性能。 我们引入了具有多层感知器的 3D 排列,用于通道注意以及卷积空间注意子模块。 在 CIFAR-100 和 ImageNet-1K 上对所提出的图像分类任务机制的评估表明,我们的方法稳定优于最近使用 ResNet 和轻量级 MobileNet 的几种注意力机制。 2.GAM加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### CBAM #### start ###############################
import torch
import torch.nn as nn
from torch.nn import functional as F
class ChannelAttention(nn.Module):
# Channel-attention module https://github.com/open-mmlab/mmdetection/tree/v3.0.0rc1/configs/rtmdet
def __init__(self, channels: int) -> None:
super().__init__()
self.pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Conv2d(channels, channels, 1, 1, 0, bias=True)
self.act = nn.Sigmoid()
def forward(self, x: torch.Tensor) -> torch.Tensor:
return x * self.act(self.fc(self.pool(x)))
class SpatialAttention(nn.Module):
# Spatial-attention module
def __init__(self, kernel_size=7):
super().__init__()
assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
padding = 3 if kernel_size == 7 else 1
self.cv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
self.act = nn.Sigmoid()
def forward(self, x):
return x * self.act(self.cv1(torch.cat([torch.mean(x, 1, keepdim=True), torch.max(x, 1, keepdim=True)[0]], 1)))
def channel_shuffle(x, groups=2): ##shuffle channel
# RESHAPE----->transpose------->Flatten
B, C, H, W = x.size()
out = x.view(B, groups, C // groups, H, W).permute(0, 2, 1, 3, 4).contiguous()
out = out.view(B, C, H, W)
return out
class GAM_Attention(nn.Module):
# https://paperswithcode.com/paper/global-attention-mechanism-retain-information
def __init__(self, c1, c2, group=True, rate=4):
super(GAM_Attention, self).__init__()
self.channel_attention = nn.Sequential(
nn.Linear(c1, int(c1 / rate)),
nn.ReLU(inplace=True),
nn.Linear(int(c1 / rate), c1)
)
self.spatial_attention = nn.Sequential(
nn.Conv2d(c1, c1 // rate, kernel_size=7, padding=3, groups=rate) if group else nn.Conv2d(c1, int(c1 / rate),
kernel_size=7,
padding=3),
nn.BatchNorm2d(int(c1 / rate)),
nn.ReLU(inplace=True),
nn.Conv2d(c1 // rate, c2, kernel_size=7, padding=3, groups=rate) if group else nn.Conv2d(int(c1 / rate), c2,
kernel_size=7,
padding=3),
nn.BatchNorm2d(c2)
)
def forward(self, x):
b, c, h, w = x.shape
x_permute = x.permute(0, 2, 3, 1).view(b, -1, c)
x_att_permute = self.channel_attention(x_permute).view(b, h, w, c)
x_channel_att = x_att_permute.permute(0, 3, 1, 2)
# x_channel_att=channel_shuffle(x_channel_att,4) #last shuffle
x = x * x_channel_att
x_spatial_att = self.spatial_attention(x).sigmoid()
x_spatial_att = channel_shuffle(x_spatial_att, 4) # last shuffle
out = x * x_spatial_att
# out=channel_shuffle(out,4) #last shuffle
return out
###################### CBAM #### end ############################### 2.2 修改tasks.py首先GAM_Attention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3
,GAM_Attention):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_GAM_Attention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, GAM_Attention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_GAM_Attention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, GAM_Attention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, GAM_Attention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, GAM_Attention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_GAM_Attention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, GAM_Attention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, GAM_Attention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, GAM_Attention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, GAM_Attention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 | Involution内卷助力检测
🚀🚀🚀本文改进:Involution,引入到YOLOv8,多种实现方式🚀🚀🚀NAM在不同检测领域中应用广泛 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.Involution原理介绍论文链接:https://arxiv.org/abs/2103.06255作者认为卷积操作的两个特征虽然也有一定的优势,但同样也有缺点。所以提出了Involution,Involution所拥有的特征正好和卷积相对称,即 spatial-specific and channel-agnostic那就是通道无关和特定于空间。和卷积一样,内卷也有内卷核(involution kernels)。内卷核在空间范围上是不同的,但在通道之间共享。看到这里就有一定的画面感了。内卷的优点:1.可以在更大的空间范围中总结上下文信息,从而克服long-range interaction(本来的卷积操作只能在特定的小空间如3x3中集合空间信息)2.内卷可以将权重自适应地分配到不同的位置,从而对空间域中信息量最大的视觉元素进行优先级排序。(本来的卷积在空间的每一个地方都是用到同一个卷积核,用的同一套权重)重新考虑了视觉任务标准卷积的固有原理,特别是与空间无关和特定于通道的方法。取而代之的是,我们通过反转前述的卷积设计原理(称为卷积)提出了一种用于深度神经网络的新颖atomic操作。2.Involution加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### Involution#### start ###############################
import torch
import torch.nn as nn
from torch.nn import functional as F
from ultralytics.nn.modules import Conv
class Involution(nn.Module):
def __init__(self, c1, c2, kernel_size, stride):
super(Involution, self).__init__()
self.kernel_size = kernel_size
self.stride = stride
self.c1 = c1
reduction_ratio = 4
self.group_channels = 16
self.groups = self.c1 // self.group_channels
self.conv1 = Conv(
c1, c1 // reduction_ratio, 1)
self.conv2 = Conv(
c1 // reduction_ratio,
kernel_size ** 2 * self.groups,
1, 1)
if stride > 1:
self.avgpool = nn.AvgPool2d(stride, stride)
self.unfold = nn.Unfold(kernel_size, 1, (kernel_size - 1) // 2, stride)
def forward(self, x):
weight = self.conv2(self.conv1(x if self.stride == 1 else self.avgpool(x)))
b, c, h, w = weight.shape
weight = weight.view(b, self.groups, self.kernel_size ** 2, h, w).unsqueeze(2)
out = self.unfold(x).view(b, self.groups, self.group_channels, self.kernel_size ** 2, h, w)
out = (weight * out).sum(dim=3).view(b, self.c1, h, w)
return out
###################### Involution #### end ############################### 2.2 修改tasks.py首先NAMAttention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,
Involution):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_Involution.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, Involution, [1024, 1, 1]]
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8改进:注意力系列篇 | Triplet注意力模,效果优于cbam、se、BAM等,涨点明
🚀🚀🚀本文改进:TripletAttention,引入到YOLOv8,多种实现方式🚀🚀🚀TripletAttention在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.Triplet注意力介绍 本文提出了可以有效解决跨维度交互的triplet attention。相较于以往的注意力方法,主要有两个优点:1.可以忽略的计算开销2.强调了多维交互而不降低维度的重要性,因此消除了通道和权重之间的间接对应。 传统的计算通道注意力的方法为了计算这些通道的权值,输入张量在空间上通过全局平均池化分解为一个像素。这导致了空间信息的大量丢失,因此在单像素通道上计算注意力时,通道维数和空间维数之间的相互依赖性也不存在。后面提出基于Spatial和Channel的CBAM模型缓解了空间相互依赖的问题,但是通道注意和空间注意是分离的,计算是相互独立的。基于建立空间注意力的方法,本文提出了跨维度交互作用(cross dimension interaction)的概念,通过捕捉空间维度和输入张量通道维度之间的交互作用,解决了这一问题。 所提出的Triplet Attention如下图所示,Triplet Attention由3个平行的Branch组成,其中两个负责捕获通道C和空间H或W之间的跨维交互。最后一个Branch类似于CBAM,用于构建Spatial Attention,最终3个Branch的输出使用平均求和。 效果优于CBAM、SE 2.TripletAttention加入YOLOv82.1加入ultralytics/nn/attention/attention.py import torch
import torch.nn as nn
from torch.nn import functional as F
###################### TripletAttention #### start ###############################
class BasicConv(nn.Module): # https://arxiv.org/pdf/2010.03045.pdf
def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, relu=True,
bn=True, bias=False):
super(BasicConv, self).__init__()
self.out_channels = out_planes
self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding,
dilation=dilation, groups=groups, bias=bias)
self.bn = nn.BatchNorm2d(out_planes, eps=1e-5, momentum=0.01, affine=True) if bn else None
self.relu = nn.ReLU() if relu else None
def forward(self, x):
x = self.conv(x)
if self.bn is not None:
x = self.bn(x)
if self.relu is not None:
x = self.relu(x)
return x
class ZPool(nn.Module):
def forward(self, x):
return torch.cat((torch.max(x, 1)[0].unsqueeze(1), torch.mean(x, 1).unsqueeze(1)), dim=1)
class AttentionGate(nn.Module):
def __init__(self):
super(AttentionGate, self).__init__()
kernel_size = 7
self.compress = ZPool()
self.conv = BasicConv(2, 1, kernel_size, stride=1, padding=(kernel_size - 1) // 2, relu=False)
def forward(self, x):
x_compress = self.compress(x)
x_out = self.conv(x_compress)
scale = torch.sigmoid_(x_out)
return x * scale
class TripletAttention(nn.Module):
def __init__(self, no_spatial=False):
super(TripletAttention, self).__init__()
self.cw = AttentionGate()
self.hc = AttentionGate()
self.no_spatial = no_spatial
if not no_spatial:
self.hw = AttentionGate()
def forward(self, x):
x_perm1 = x.permute(0, 2, 1, 3).contiguous()
x_out1 = self.cw(x_perm1)
x_out11 = x_out1.permute(0, 2, 1, 3).contiguous()
x_perm2 = x.permute(0, 3, 2, 1).contiguous()
x_out2 = self.hc(x_perm2)
x_out21 = x_out2.permute(0, 3, 2, 1).contiguous()
if not self.no_spatial:
x_out = self.hw(x)
x_out = 1 / 3 * (x_out + x_out11 + x_out21)
else:
x_out = 1 / 2 * (x_out11 + x_out21)
return x_out
2.2 修改tasks.py首先TripletAttention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 elif m in (TripletAttention,):
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]] 2.3 yaml实现2.3.1 yolov8_TripletAttention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, TripletAttention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.2 yolov8_TripletAttention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, TripletAttention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, TripletAttention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, TripletAttention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_TripletAttention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, TripletAttention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, TripletAttention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, TripletAttention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, TripletAttention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 | CoTAttention,捕捉全局信息的能力与CNN捕捉临近局部
🚀🚀🚀本文改进:CoTAttention注意力,引入到YOLOv8,多种实现方式🚀🚀🚀CoTAttention在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.CoTAttention CoTAttention网络是一种用于多模态场景下的视觉问答(Visual Question Answering,VQA)任务的神经网络模型。它是在经典的注意力机制(Attention Mechanism)上进行了改进,能够自适应地对不同的视觉和语言输入进行注意力分配,从而更好地完成VQA任务。CoTAttention网络中的“CoT”代表“Cross-modal Transformer”,即跨模态Transformer。在该网络中,视觉和语言输入分别被编码为一组特征向量,然后通过一个跨模态的Transformer模块进行交互和整合。在这个跨模态的Transformer模块中,Co-Attention机制被用来计算视觉和语言特征之间的交互注意力,从而实现更好的信息交换和整合。在计算机视觉和自然语言处理紧密结合的VQA任务中,CoTAttention网络取得了很好的效果。 新加坡国立大学的Qibin Hou等人提出了一种为轻量级网络设计的新的注意力机制,该机制将位置信息嵌入到了通道注意力中,称为coordinate attention 京东AI Research提出新的主干网络CoTNet,在CVPR上2021获得开放域图像识别竞赛冠军 京东AI Research提出一种Contextual Transformer Networks结构,就是将Transformer捕捉全局信息的能力与CNN捕捉临近局部信息能力相结合,从而提高网络模型的特征表达能力。值得注意的是,该方法可以实现模块的“即插即用”,将ResNet网络中的3x3模块替换成CoTNet的核心模块即可使用,Res2Net网络也是基于这种思想实现的。 在相同深度(50层或101层)下,top-1和top-5结果都表明本文的方法比卷积网络和Attention-based网络性能更好。2.CoTAttention加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### CoTAttention #### start ###############################
import torch
from torch import flatten, nn
from torch.nn import functional as F
class CoTAttention(nn.Module):
def __init__(self, dim=512, kernel_size=3):
super().__init__()
self.dim = dim
self.kernel_size = kernel_size
self.key_embed = nn.Sequential(
nn.Conv2d(dim, dim, kernel_size=kernel_size, padding=kernel_size // 2, groups=4, bias=False),
nn.BatchNorm2d(dim),
nn.ReLU()
)
self.value_embed = nn.Sequential(
nn.Conv2d(dim, dim, 1, bias=False),
nn.BatchNorm2d(dim)
)
factor = 4
self.attention_embed = nn.Sequential(
nn.Conv2d(2 * dim, 2 * dim // factor, 1, bias=False),
nn.BatchNorm2d(2 * dim // factor),
nn.ReLU(),
nn.Conv2d(2 * dim // factor, kernel_size * kernel_size * dim, 1)
)
def forward(self, x):
bs, c, h, w = x.shape
k1 = self.key_embed(x) # bs,c,h,w
v = self.value_embed(x).view(bs, c, -1) # bs,c,h,w
y = torch.cat([k1, x], dim=1) # bs,2c,h,w
att = self.attention_embed(y) # bs,c*k*k,h,w
att = att.reshape(bs, c, self.kernel_size * self.kernel_size, h, w)
att = att.mean(2, keepdim=False).view(bs, c, -1) # bs,c,h*w
k2 = F.softmax(att, dim=-1) * v
k2 = k2.view(bs, c, h, w)
return k1 + k2
###################### CoTAttention #### end ############################### 2.2 修改tasks.py首先CoTAttention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 #####attention ####
elif m in (MHSA,ECAAttention,TripletAttention,BAM,CoTAttention):
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]]
#####attention #### 2.3 yaml实现2.3.1 yolov8_CoTAttention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, CoTAttention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_CoTAttention2.yamlneck里的连接Detect的3个C2f结合
# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, CoTAttention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, CoTAttention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, CoTAttention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_CoTAttention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, CoTAttention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, CoTAttention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, CoTAttention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, CoTAttention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 |PolarizedSelfAttention极化自注意力,效果秒杀
🚀🚀🚀本文改进:PolarizedSelfAttention注意力,引入到YOLOv8,多种实现方式🚀🚀🚀PolarizedSelfAttention在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.PolarizedSelfAttention Polarized self-attention是一种改进的自注意力机制,旨在提高自注意力模型的效率和准确性。传统的自注意力机制通常需要计算所有位置对所有位置的注意力,这会导致计算复杂度的增加和模型的训练时间的延长。Polarized self-attention通过引入极化因子来减少需要计算的位置对之间的注意力,从而提高自注意力模型的效率。极化因子是一个向量,可以将其与每个位置的向量点积,以确定哪些位置需要进行注意力计算。这种方法可以通过在保持准确度的同时减少计算量来提高自注意力模型的效率。 基于双重注意力机制,本文针对Pixel-wise regression的任务,提出了一种更加精细的双重注意力机制——极化自注意力(Polarized Self-Attention)。作为一个即插即用的模块,在人体姿态估计和语义分割任务上,作者将它用在了以前的SOTA模型上,并达到了新的SOTA性能,霸榜COCO人体姿态估计和Cityscapes语义分割。 注意力机制是一个被广泛应用在各种CV任务中的方法。注意力机制根据施加的维度大致可以分为两类:通道注意力和空间注意力。对于通道注意力机制,代表性的工作有SENet、ECANet;对于空间注意力机制,代表性的工作有Self-Attention。随着空间和通道注意力机制的提出,很自然的,结合空间和通道两个维度的双重注意力机制也被提出,代表工作有CBAM,DANet。 作者提出了一个即插即用的模块——极化自注意力机制( Polarized Self-Attention(PSA)),用于解决像素级的回归任务,相比于其他注意力机制,极化自注意力机制主要有两个设计上的亮点:1)极化滤波( Polarized filtering):在通道和空间维度保持比较高的resolution(在通道上保持C/2的维度,在空间上保持[H,W]的维度 ),这一步能够减少降维度造成的信息损失;2)增强(Enhancement):组合非线性直接拟合典型细粒度回归的输出分布。 2.PolarizedSelfAttention加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### PolarizedSelfAttention #### start ###############################
from torch import nn
from torch.nn import init
class PolarizedSelfAttention(nn.Module):
def __init__(self, channel=512):
super().__init__()
self.ch_wv = nn.Conv2d(channel, channel // 2, kernel_size=(1, 1))
self.ch_wq = nn.Conv2d(channel, 1, kernel_size=(1, 1))
self.softmax_channel = nn.Softmax(1)
self.softmax_spatial = nn.Softmax(-1)
self.ch_wz = nn.Conv2d(channel // 2, channel, kernel_size=(1, 1))
self.ln = nn.LayerNorm(channel)
self.sigmoid = nn.Sigmoid()
self.sp_wv = nn.Conv2d(channel, channel // 2, kernel_size=(1, 1))
self.sp_wq = nn.Conv2d(channel, channel // 2, kernel_size=(1, 1))
self.agp = nn.AdaptiveAvgPool2d((1, 1))
def forward(self, x):
b, c, h, w = x.size()
# Channel-only Self-Attention
channel_wv = self.ch_wv(x) # bs,c//2,h,w
channel_wq = self.ch_wq(x) # bs,1,h,w
channel_wv = channel_wv.reshape(b, c // 2, -1) # bs,c//2,h*w
channel_wq = channel_wq.reshape(b, -1, 1) # bs,h*w,1
channel_wq = self.softmax_channel(channel_wq)
channel_wz = torch.matmul(channel_wv, channel_wq).unsqueeze(-1) # bs,c//2,1,1
channel_weight = self.sigmoid(self.ln(self.ch_wz(channel_wz).reshape(b, c, 1).permute(0, 2, 1))).permute(0, 2,
1).reshape(
b, c, 1, 1) # bs,c,1,1
channel_out = channel_weight * x
# Spatial-only Self-Attention
spatial_wv = self.sp_wv(x) # bs,c//2,h,w
spatial_wq = self.sp_wq(x) # bs,c//2,h,w
spatial_wq = self.agp(spatial_wq) # bs,c//2,1,1
spatial_wv = spatial_wv.reshape(b, c // 2, -1) # bs,c//2,h*w
spatial_wq = spatial_wq.permute(0, 2, 3, 1).reshape(b, 1, c // 2) # bs,1,c//2
spatial_wq = self.softmax_spatial(spatial_wq)
spatial_wz = torch.matmul(spatial_wq, spatial_wv) # bs,1,h*w
spatial_weight = self.sigmoid(spatial_wz.reshape(b, 1, h, w)) # bs,1,h,w
spatial_out = spatial_weight * x
out = spatial_out + channel_out
return out
###################### PolarizedSelfAttention #### end ############################### 2.2 修改tasks.py首先PolarizedSelfAttention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 #####attention ####
elif m in (MHSA,ECAAttention,TripletAttention,BAM,PolarizedSelfAttention):
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]]
#####attention #### 2.3 yaml实现2.3.1 yolov8_PolarizedSelfAttention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, PolarizedSelfAttention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.2 yolov8_PolarizedSelfAttention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, PolarizedSelfAttention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, PolarizedSelfAttention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, PolarizedSelfAttention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_PolarizedSelfAttention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, PolarizedSelfAttention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, PolarizedSelfAttention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, PolarizedSelfAttention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, PolarizedSelfAttention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8实战:遥感目标检测(RSOD)系统
1.YOLOv8介绍改进点:1.Backbone:使用的依旧是CSP的思想,不过YOLOv5中的C3模块被替换成了C2f模块,实现了进一步的轻量化,同时YOLOv8依旧使用了YOLOv5等架构中使用的SPPF模块;2.PAN-FPN:毫无疑问YOLOv8依旧使用了PAN的思想,不过通过对比YOLOv5与YOLOv8的结构图可以看到,YOLOv8将YOLOv5中PAN-FPN上采样阶段中的卷积结构删除了,同时也将C3模块替换为了C2f模块;3.Decoupled-Head:是不是嗅到了不一样的味道?是的YOLOv8走向了Decoupled-Head;4.YOLOv8抛弃了以往的Anchor-Base,使用了Anchor-Free的思想;5.损失函数:YOLOv8使用VFL Loss作为分类损失,使用DFL Loss+CIOU Loss作为分类损失;6.样本匹配:YOLOv8抛弃了以往的IOU匹配或者单边比例的分配方式,而是使用了Task-Aligned Assigner匹配方式。1.1 C2f模块介绍C2f模块就是参考了C3模块以及ELAN的思想进行的设计,让YOLOv8可以在保证轻量化的同时获得更加丰富的梯度流信息。 代码:class C2f(nn.Module):
# CSP Bottleneck with 2 convolutions
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
self.c = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).split((self.c, self.c), 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1))2.遥感目标检测——RSOD2.1 RSOD数据集下载路径:https://github.com/RSIA-LIESMARS-WHU/RSOD-Dataset-本文选择aircraft dataset,oiltank数据集两个类别大小611张,随机按照8:1:1进行分配 3.训练结果可视化分析YOLOv8 summary (fused): 168 layers, 3006038 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 4/4 [00:06<00:00, 1.54s/it]
all 109 1153 0.962 0.945 0.984 0.728
aircraft 109 844 0.957 0.943 0.979 0.678
oiltank 109 309 0.967 0.947 0.989 0.778
Speed: 0.3ms preprocess, 2.3ms inference, 0.0ms loss, 2.0ms postprocess per image训练结果如下:P_curve.png表示准确率与置信度的关系图线,横坐标置信度。由下图可以看出置信度越高,准确率越高。PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。 R_curve.png召回率与置信度之间关系,具体参照 P_curve。results.png(1,1),(2,1):该图分别表示训练时和验证时ClOU损失函数的均值,越小方框越准。(1,2),(2,2):推测为目标检测loss均值,越小目标越准。(2,4),(2,5):表示在不同IoU阈值时计算每一类中所有图片的AP然后所有类别求取均值。mAP_0.5:0.95表示从0.5到0.95以0.05的步长上的平均mAP.
神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(二):多尺度空洞注意力(MSDA) | 中科院一区顶刊
🚀🚀🚀本文改进: 新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互;如何在YOLOv8下使用:1)作为注意力机制放在各个网络位置;2)与C2f结合替代原始的C2f🚀🚀🚀MSCA多尺度特性在交通摄像头下车辆检测项目中, mAP50从原始的0.745提升至0.756🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研;1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。2.DilateFormer介绍论文: 2302.01791.pdf (arxiv.org)本文提出了一种新颖的多尺度空洞 Transformer,简称DilateFormer,以用于视觉识别任务。原有的 ViT 模型在计算复杂性和感受野大小之间的权衡上存在矛盾。众所周知,ViT 模型使用全局注意力机制,能够在任意图像块之间建立长远距离上下文依赖关系,但是全局感受野带来的是平方级别的计算代价。同时,有些研究表明,在浅层特征上,直接进行全局依赖性建模可能存在冗余,因此是没必要的。为了克服这些问题,作者提出了一种新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互,这些发现源自于对 ViTs 在浅层次上全局注意力中图像块交互的分析。作者发现在浅层次上,注意力矩阵具有局部性和稀疏性两个关键属性,这表明在浅层次的语义建模中,远离查询块的块大部分无关,因此全局注意力模块中存在大量的冗余。如下图所示,MSDA 模块同样采用多头的设计,将特征图的通道分为 n 个不同的头部,并在不同的头部使用不同的空洞率执行滑动窗口膨胀注意力(SWDA)。这样可以在被关注的感受野内的各个尺度上聚合语义信息,并有效地减少自注意力机制的冗余,无需复杂的操作和额外的计算成本。总体来说,DilateFormer 通过这种混合使用多尺度空洞注意力和多头自注意力的方式,成功地处理了长距离依赖问题,同时保持了计算效率,并能够适应不同尺度和分辨率的输入。3.训练可视化分析 mAP50从原始的0.745提升至0.756YOLOv8_DilateBlock summary (fused): 182 layers, 3268755 parameters, 0 gradients, 8.3 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 10/10 [00:19<00:00, 1.97s/it]
all 582 6970 0.814 0.688 0.756 0.395
训练结果如下:PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。
神机妙算
YOLOv8优化:注意力系列篇 | 线性上下文变换LCT,性能优于SE等注意力
🚀🚀🚀本文改进:线性上下文变换LCT,引入到YOLOv8,多种实现方式🚀🚀🚀LCT在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.LCT介绍 AAAI 2020摘要: 在本研究中,我们首先重新审视了SE块,然后基于全局上下文和注意力分布之间的关系进行了详细的实证研究,基于此提出了一个简单而有效的模块,称为线性上下文变换(LCT)块。我们将所有通道分成不同的组,并在每个通道组内对全局聚合的上下文特征进行归一化,减少了来自无关通道的干扰。通过对归一化的上下文特征进行线性变换,我们独立地为每个通道建模全局上下文。LCT块非常轻量级,易于插入不同的主干模型,同时增加的参数和计算负担可以忽略不计。大量实验证明,在ImageNet图像分类任务和COCO数据集上的目标检测/分割任务中,LCT块在不同主干模型上的性能优于SE块。此外,LCT在现有最先进的检测架构上都能带来一致的性能提升,例如在COCO基准测试中,无论基线模型的容量如何,APbbox提升1.5∼1.7%,APmask提升1.0%∼1.2%。我们希望我们的简单而有效的方法能为基于注意力的模型的未来研究提供一些启示。 LCT结构图: 实验:分类任务很重,LCT优于SE 检测任务重,ap提升1.5∼1.7%2.LCT加入YOLOv82.1加入ultralytics/nn/attention/attention.py ###################### LCT attention #### start ###############################
"""
PyTorch implementation of Linear Context Transform Block
As described in https://arxiv.org/pdf/1909.03834v2
"""
import torch
from torch import nn
class LCTattention(nn.Module):
def __init__(self, channels, groups, eps=1e-5):
super().__init__()
assert channels % groups == 0, "Number of channels should be evenly divisible by the number of groups"
self.groups = groups
self.channels = channels
self.eps = eps
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.w = nn.Parameter(torch.ones(channels))
self.b = nn.Parameter(torch.zeros(channels))
self.sigmoid = nn.Sigmoid()
def forward(self, x):
batch_size = x.shape[0]
y = self.avgpool(x).view(batch_size, self.groups, -1)
mean = y.mean(dim=-1, keepdim=True)
mean_x2 = (y ** 2).mean(dim=-1, keepdim=True)
var = mean_x2 - mean ** 2
y_norm = (y - mean) / torch.sqrt(var + self.eps)
y_norm = y_norm.reshape(batch_size, self.channels, 1, 1)
y_norm = self.w.reshape(1, -1, 1, 1) * y_norm + self.b.reshape(1, -1, 1, 1)
y_norm = self.sigmoid(y_norm)
return x * y_norm.expand_as(x)
###################### LCT attention #### END ###############################
2.2 修改tasks.py首先LCTattention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,LCTattention):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_LCTattention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, LCTattention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_LCTattention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, LCTattention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, LCTattention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, LCTattention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_LCTattention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, LCTattention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, LCTattention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, LCTattention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, LCTattention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 | 全局多头自注意力MHSA,效果秒杀CBAM、SE
🚀🚀🚀本文改进:MHSA注意力,引入到YOLOv8,多种实现方式🚀🚀🚀MHSA在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1. BoTNet本文介绍了BoTNet,这是一个概念简单但功能强大的主干架构,它将自注意力整合到多个计算机视觉任务中,包括图像分类、对象检测和实例分割。通过在ResNet的最后三个瓶颈块中用全局自注意力替换空间卷积,而不做其他更改,本方法在实例分割和对象检测方面显著改进了基线,同时也减少了参数,延迟开销最小。作者还指出了如何将自注意力的ResNet瓶颈块视为转换器块。在没有任何提示的情况下,最后,作者还提出了一种简单的BoTNet网络图像分类设计。 下图给出了利用自注意力实现的深度学习体系结构的分类。在本节中,将重点介绍:(1)Transformer vs BoTNet;(2) DETR vs BoTNet;(3)Non-Local vs BoTNet。本文的一个关键信息是,具有多头自注意力(MHSA)层的ResNet瓶颈块可以被视为具有瓶颈结构的Transformer。下图直观地解释了这一点,作者将此块命名为瓶颈转换器(BoT)。除了图中已经可见的差异(残差连接和块连接)之外,还有一些差异:(1)Normalization:Transformer使用LN,而BoT 使用BN,这在ResNet瓶颈块中是典型的;(2) 非线性:Transformer在FFN块中使用一个非线性函数,而ResNet结构允许BoT块使用三个非线性函数;(3) 输出投影:Transformer中的MHSA块包含输出投影,而BoT块(图1)中的MHSA层(图4)不包含输出投影;(4) 使用SGD和动量优化器(通常用于计算机视觉),而Transformer通常使用Adam优化器]进行训练。 BoTNet(Bottleneck Transformer Network):一种基于Transformer的新骨干架构。BoTNet同时使用卷积和自注意力机制,即在ResNet的最后3个bottleneck blocks中使用全局多头自注意力(Multi-Head Self-Attention, MHSA)替换3 × 3空间卷积。 2.BoTNet、MHSA加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### MHSA#### start ###############################
import torch
import torch.nn as nn
import torch.nn.functional as F
class MHSA(nn.Module):
def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False):
super(MHSA, self).__init__()
self.heads = heads
self.query = nn.Conv2d(n_dims, n_dims, kernel_size=1)
self.key = nn.Conv2d(n_dims, n_dims, kernel_size=1)
self.value = nn.Conv2d(n_dims, n_dims, kernel_size=1)
self.pos = pos_emb
if self.pos:
self.rel_h_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, 1, int(height)]),
requires_grad=True)
self.rel_w_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, int(width), 1]),
requires_grad=True)
self.softmax = nn.Softmax(dim=-1)
def forward(self, x):
n_batch, C, width, height = x.size()
q = self.query(x).view(n_batch, self.heads, C // self.heads, -1)
k = self.key(x).view(n_batch, self.heads, C // self.heads, -1)
v = self.value(x).view(n_batch, self.heads, C // self.heads, -1)
# print('q shape:{},k shape:{},v shape:{}'.format(q.shape,k.shape,v.shape)) #1,4,64,256
content_content = torch.matmul(q.permute(0, 1, 3, 2), k) # 1,C,h*w,h*w
# print("qkT=",content_content.shape)
c1, c2, c3, c4 = content_content.size()
if self.pos:
# print("old content_content shape",content_content.shape) #1,4,256,256
content_position = (self.rel_h_weight + self.rel_w_weight).view(1, self.heads, C // self.heads, -1).permute(
0, 1, 3, 2) # 1,4,1024,64
content_position = torch.matmul(content_position, q) # ([1, 4, 1024, 256])
content_position = content_position if (
content_content.shape == content_position.shape) else content_position[:, :, :c3, ]
assert (content_content.shape == content_position.shape)
# print('new pos222-> shape:',content_position.shape)
# print('new content222-> shape:',content_content.shape)
energy = content_content + content_position
else:
energy = content_content
attention = self.softmax(energy)
out = torch.matmul(v, attention.permute(0, 1, 3, 2)) # 1,4,256,64
out = out.view(n_batch, C, width, height)
return out
class BottleneckTransformer(nn.Module):
# Transformer bottleneck
# expansion = 1
def __init__(self, c1, c2, stride=1, heads=4, mhsa=True, resolution=None, expansion=1):
super(BottleneckTransformer, self).__init__()
c_ = int(c2 * expansion)
self.cv1 = Conv(c1, c_, 1, 1)
# self.bn1 = nn.BatchNorm2d(c2)
if not mhsa:
self.cv2 = Conv(c_, c2, 3, 1)
else:
self.cv2 = nn.ModuleList()
self.cv2.append(MHSA(c2, width=int(resolution[0]), height=int(resolution[1]), heads=heads))
if stride == 2:
self.cv2.append(nn.AvgPool2d(2, 2))
self.cv2 = nn.Sequential(*self.cv2)
self.shortcut = c1 == c2
if stride != 1 or c1 != expansion * c2:
self.shortcut = nn.Sequential(
nn.Conv2d(c1, expansion * c2, kernel_size=1, stride=stride),
nn.BatchNorm2d(expansion * c2)
)
self.fc1 = nn.Linear(c2, c2)
def forward(self, x):
out = x + self.cv2(self.cv1(x)) if self.shortcut else self.cv2(self.cv1(x))
return out
class BoT3(nn.Module):
# CSP Bottleneck with 3 convolutions
def __init__(self, c1, c2, n=1, e=0.5, e2=1, w=20, h=20): # ch_in, ch_out, number, , expansion,w,h
super(BoT3, self).__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c1, c_, 1, 1)
self.cv3 = Conv(2 * c_, c2, 1) # act=FReLU(c2)
self.m = nn.Sequential(
*[BottleneckTransformer(c_, c_, stride=1, heads=4, mhsa=True, resolution=(w, h), expansion=e2) for _ in
range(n)])
# self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])
def forward(self, x):
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
###################### MHSA#### end ############################### 2.2 修改tasks.py首先BoTNet、MHSA进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改BoT定义 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3
,BoT3):
c1, c2 = ch[f], args[0]
if c2 != nc: # if c2 not equal to number of classes (i.e. for Classify() output)
c2 = make_divisible(min(c2, max_channels) * width, 8) MHSA定义 elif m in (MHSA,ECAAttention,TripletAttention,BAM,CoTAttention,PolarizedSelfAttention):
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]] 2.3 yaml实现2.3.1 yolov8_MHSA.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, MHSA, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.2 yolov8_BoT3.yaml# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, BoT3, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 | SEAttention注意力,效果秒杀CBAM
🚀🚀🚀本文改进:SEAttention注意力,引入到YOLOv8,多种实现方式🚀🚀🚀SEAttention在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.SENet Squeeze-and-Excitation Networks(SENet)是由自动驾驶公司Momenta在2017年公布的一种全新的图像识别结构,它通过对特征通道间的相关性进行建模,把重要的特征进行强化来提升准确率。这个结构是2017 ILSVR竞赛的冠军,top5的错误率达到了2.251%,比2016年的第一名还要低25%,可谓提升巨大。 SE是指"Squeeze-and-Excitation",是一种用于增强卷积神经网络(CNN)的注意力机制。SE网络结构由Jie Hu等人在2018年提出,其核心思想是在卷积神经网络中引入一个全局的注意力机制,以自适应地学习每个通道的重要性。 SE网络通过两个步骤来实现注意力机制:压缩和激励。在压缩步骤中,SE网络会对每个通道的特征图进行全局池化,将其压缩成一个标量。在激励步骤中,SE网络会通过一个全连接层,将压缩后的特征向量转换为一个权重向量,用于对每个通道的特征图进行加权。 通过引入SE模块,CNN可以自适应地学习每个通道的重要性,从而提高模型的表现能力。SE网络在多个图像分类任务中取得了很好的效果,并被广泛应用于各种视觉任务中。2.SEAttention加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### SENet #### start ###############################
import numpy as np
import torch
from torch import nn
from torch.nn import init
class SEAttention(nn.Module):
def __init__(self, channel=512,reduction=16):
super().__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Sequential(
nn.Linear(channel, channel // reduction, bias=False),
nn.ReLU(inplace=True),
nn.Linear(channel // reduction, channel, bias=False),
nn.Sigmoid()
)
def init_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
init.kaiming_normal_(m.weight, mode='fan_out')
if m.bias is not None:
init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
init.constant_(m.weight, 1)
init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
init.normal_(m.weight, std=0.001)
if m.bias is not None:
init.constant_(m.bias, 0)
def forward(self, x):
b, c, _, _ = x.size()
y = self.avg_pool(x).view(b, c)
y = self.fc(y).view(b, c, 1, 1)
return x * y.expand_as(x)
###################### SENet #### end ############################### 2.2 修改tasks.py首先SEAttention进行注册
from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,SEAttention):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_SEAttention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, SEAttention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_SEAttention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, SEAttention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, SEAttention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, SEAttention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5)
2.3.3 yolov8_SEAttention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, SEAttention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, SEAttention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, SEAttention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, SEAttention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
halcon学习和实践(颜色筛选)
图像处理中,颜色是一个很重要的属性。很多同学都以为颜色只有红、橙、黄、绿、青、蓝、紫这几种颜色。事实上并不是这样的。如果我们以红、蓝、绿为基色,其他颜色都是以这三种颜色为基础搭配而成的话,那么颜色的种类应该有256 * 256* 256这么多。这就是为什么,很多知名的消费品每一次在产品发布会的时候都要精心挑选几种颜色供大家挑选。 那么,作为图像处理来说,如果要识别筛选某种颜色的话,是不是直接从r、g、b里面筛选一个范围就可以实现这个目标呢?这样其实是可以的,但是不准确。一种更好的办法是先将图像从rgb转化为h、s、v。这里的h是色度,s是饱和度,v是亮度。如果需要挑选一个颜色的话,那么选择对应的h、s、v范围即可。 还记得在大学本科论文设计的时候,当时的论文题目叫彩色图像的增强显示。那个时候只是知道r、g、b,并不知道h、s、v,所以就在rgb通道上面做了各种增强方法,比如说直方图均衡等等,虽然也有一定的效果,但是那个效果真是惨不忍睹。 hsv本身是为了提取特定的区域范围,这部分相当于代替了算子运算、二值化运算,后期的区域分割、属性过滤、ocr识别、发送命令,这部分还是一样,和之前的流程没有什么差别。下面说说应该怎么做一个颜色提取,首先需要明确颜色范围,大家可以参考这篇blog,地址在这,https://blog.csdn.net/zhangdongren/article/details/98941445 接着就可以自己写一个python+opencv的代码来进行处理,比如像这样,原来代码的地址在这,https://www.cnblogs.com/puheng/p/9228473.htmlimport cv2
import numpy as np
lower_blue=np.array([110,50,50])
upper_blue=np.array([130,255,255])
img1=cv2.imread("car.png")
xsize,ysize,channel=img1.shape
img1=cv2.resize(img1,(ysize,xsize))
frame=cv2.cvtColor(img1,cv2.COLOR_BGR2HSV)
mask_blue=cv2.inRange(frame,lower_blue,upper_blue)
res_blue=cv2.bitwise_and(frame,frame,mask=mask_blue)
res_blue=cv2.cvtColor(res_blue,cv2.COLOR_HSV2BGR)
cv2.imshow("mask_blue",mask_blue)
cv2.imshow("res_blue",res_blue)
cv2.waitKey(0)
cv2.destroyAllWindows() 先准备一个有蓝色车牌的图片,命名为car.png,比如像这样 直接输入python执行语句,比如说python demo.py,不出意外就可以得到这样的结果, 这样,通过一个颜色,就可以比较容易的将需要的物体从图像中识别出来了。
神机妙算
YOLOv8优化:注意力系列篇 | ECA注意力,效果秒杀CBAM、SE
🚀🚀🚀本文改进:ECA注意力,引入到YOLOv8,多种实现方式🚀🚀🚀ECA在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK2.ECA论文:https://arxiv.org/pdf/1910.03151.pdf 本文的贡献总结如下:对SE模块进行了剖析,并分别证明了避免降维和适当的跨通道交互对于学习高性能和高效率的通道注意力是重要的。在以上分析的基础上,提出了一种高效通道注意模块(ECA),在CNN网络上提出了一种极轻量的通道注意力模块,该模块增加的模型复杂度小,提升效果显著。在ImageNet-1K和MS COCO上的实验结果表明,本文提出的方法具有比目前最先进的CNN模型更低的模型复杂度,与此同时,本文方法却取得了非常有竞争力的结果。 作者设计了一个高效的channel attention机制,该方法保留了原有的通道一对一权重更新,并且通过local cross-channel interaction来提升结果。此外作者还设计了一个自动调节kernel size的机制来决定交叉学习的覆盖率。通过该ECA模块,作者在几乎一样的参数上获得了分类top-1 acc 2%的提升 ECA(ECA-Net)是一种新的卷积神经网络结构,它的优势在于以下几点: 能够有效地捕捉长距离依赖关系。ECA-Net引入了一种新的通道注意力机制,可以对不同通道的特征进行加权,从而使网络能够更好地捕捉长距离依赖关系。 参数量小、计算效率高。ECA-Net的参数量比传统的卷积神经网络更小,同时也能够在保证准确率的前提下大大提高计算效率。 可以适应不同的输入尺寸。ECA-Net可以适应不同的输入尺寸,因此在处理不同大小的图像时具有很好的适应性。.总的来说,ECA-Net是一种非常有前途的卷积神经网络结构,它具有良好的性能和高效的计算能力,可以在计算机视觉等领域得到广泛的应用。 比较了不同的注意力方法在ImageNet数据集上的网络参数(param),浮点运算每秒(FLOPs),训练或推理速度(帧每秒,FPS), Top-1/Top-5的准确性(%)。 2.ECA加入YOLOv82.1加入ultralytics/nn/attention/attention.py import torch
import torch.nn as nn
from torch.nn import functional as F
###################### ECAAttention #### start ###############################
class ECAAttention(nn.Module):
"""Constructs a ECA module.
Args:
channel: Number of channels of the input feature map
k_size: Adaptive selection of kernel size
"""
def __init__(self, c1, k_size=3):
super(ECAAttention, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
# feature descriptor on the global spatial information
y = self.avg_pool(x)
y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)
# Multi-scale information fusion
y = self.sigmoid(y)
return x * y.expand_as(x)
###################### ECAAttention #### end ############################### 2.2 修改tasks.py首先ECAAttention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,ECAAttention):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_ECAAttention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, ECAAttention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_ECAAttention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, ECAAttention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, ECAAttention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, ECAAttention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_ECAAttention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, ECAAttention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, ECAAttention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, ECAAttention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, ECAAttention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(五):Gold-YOLO,信息聚集-分发(Gather-
本文改进: 新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互;如何在YOLOv8下使用:1)作为注意力机制放在各个网络位置;2)与C2f结合替代原始的C2fMSCA多尺度特性在交通摄像头下车辆检测项目中, mAP50从原始的0.745提升至0.756学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。系。 2.Gold-YOLO链接:https://arxiv.org/pdf/2309.11331.pdf 代码:https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO单位:华为诺亚方舟实验室 理论部分可参考:超越YOLO系列!华为提出Gold-YOLO:高效实时目标检测器 - 知乎 传统YOLO的问题在检测模型中,通常先经过backbone提取得到一系列不同层级的特征,FPN利用了backbone的这一特点,构建了相应的融合结构:不层级的特征包含着不同大小物体的位置信息,虽然这些特征包含的信息不同,但这些特征在相互融合后能够互相弥补彼此缺失的信息,增强每一层级信息的丰富程度,提升网络性能。原始的FPN结构由于其层层递进的信息融合模式,使得相邻层的信息能够充分融合,但也导致了跨层信息融合存在问题:当跨层的信息进行交互融合时,由于没有直连的交互通路,只能依靠中间层充当“中介”进行融合,导致了一定的信息损失。之前的许多工作中都关注到了这一问题,而解决方案通常是通过添加shortcut增加更多的路径,以增强信息流动。摘要:当前YOLO系列模型通常采用类FPN方法进行信息融合,而这一结构在融合跨层信息时存在信息损失的问题。针对这一问题,我们提出了全新的信息聚集-分发(Gather-and-Distribute Mechanism)GD机制,通过在全局视野上对不同层级的特征进行统一的聚集融合并分发注入到不同层级中,构建更加充分高效的信息交互融合机制,并基于GD机制构建了Gold-YOLO。在COCO数据集中,我们的Gold-YOLO超越了现有的YOLO系列,实现了精度-速度曲线上的SOTA提出了一种全新的信息交互融合机制:信息聚集-分发机制(Gather-and-Distribute Mechanism)。该机制通过在全局上融合不同层次的特征得到全局信息,并将全局信息注入到不同层级的特征中,实现了高效的信息交互和融合。在不显著增加延迟的情况下GD机制显著增强了Neck部分的信息融合能力,提高了模型对不同大小物体的检测能力。 在Gold-YOLO中,针对模型需要检测不同大小的物体的需要,并权衡精度和速度,我们构建了两个GD分支对信息进行融合:低层级信息聚集-分发分支(Low-GD)和高层级信息聚集-分发分支(High-GD),分别基于卷积和transformer提取和融合特征信息。源码详见:YOLOv8改进:Neck改进系列 | Gold-YOLO,信息聚集-分发(Gather-and-Distribute Mechanism)机制 | 华为诺亚NeurIPS23-CSDN博客3.训练可视化分析 mAP50从原始的0.745提升至0.748YOLOv8-goldYOLO summary: 359 layers, 6015123 parameters, 0 gradients, 11.9 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 37/37 [00:18<00:00, 2.04it/s]
all 582 6970 0.821 0.699 0.763 0.4训练结果如下:PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。
神机妙算
基于YOLOv8的人脸检测小目标识别算法:可变形大核注意力(D-LKA Attention),实现涨
🚀🚀🚀本文改进:可变形大核注意力(D-LKA Attention),大卷积核增强注意力机制,引入到YOLOv8,与C2f结合实现二次创新🚀🚀🚀D-LKA Attention在人脸检测小目标识别算法中, mAP@0.5从原始的0.929提升至0.933🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.人脸识别小目标数据集介绍数据集来源:GitHub - HCIILAB/SCUT-HEAD-Dataset-Release: SCUT HEAD is a large-scale head detection dataset, including 4405 images labeld with 111251 heads.本文章主要通过小目标来进行优化,因此数据集只选择partA部分,总共 2000张,按照7:2:1随机进行分配;下图可以看出都是小目标人脸识别 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。2.YOLOv8介绍改进点:1 .Backbone:使用的依旧是CSP的思想,不过YOLOv5中的C3模块被替换成了C2f模块,实现了进一步的轻量化,同时YOLOv8依旧使用了YOLOv5等架构中使用的SPPF模块;2 .PAN-FPN:毫无疑问YOLOv8依旧使用了PAN的思想,不过通过对比YOLOv5与YOLOv8的结构图可以看到,YOLOv8将YOLOv5中PAN-FPN上采样阶段中的卷积结构删除了,同时 也将C3模块替换为了C2f模块; 3.Decoupled-Head:是不是嗅到了不一样的味道?是的YOLOv8走向了Decoupled-Head; 4.YOLOv8抛弃了以往的Anchor-Base,使用了Anchor-Free的思想;5.损失函数:YOLOv8使用VFL Loss作为分类损失,使用DFL Loss+CIOU Loss作为分类损失;6.样本匹配:YOLOv8抛弃了以往的IOU匹配或者单边比例的分配方式,而是使用了Task-Aligned Assigner匹配方式。2.1 C2f模块介绍C2f模块就是参考了C3模块以及ELAN的思想进行的设计,让YOLOv8可以在保证轻量化的同时获得更加丰富的梯度流信息。 代码:class C2f(nn.Module):
# CSP Bottleneck with 2 convolutions
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
self.c = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).split((self.c, self.c), 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1))
3.D-LKA Net介绍 摘要:医学图像分割通过 Transformer 模型得到了显着改进,该模型在掌握深远的上下文和全局上下文信息方面表现出色。 然而,这些模型不断增长的计算需求(与平方令牌数量成正比)限制了它们的深度和分辨率能力。 目前的大多数方法都是逐片处理 D 体图像数据(称为伪 3D),缺少关键的片间信息,从而降低了模型的整体性能。 为了应对这些挑战,我们引入了可变形大核注意力(D-LKA Attention)的概念,这是一种采用大卷积核来充分理解体积上下文的简化注意力机制。 这种机制在类似于自注意力的感受野中运行,同时避免了计算开销。 此外,我们提出的注意力机制受益于可变形卷积来灵活地扭曲采样网格,使模型能够适当地适应不同的数据模式。我们设计了 D-LKA 注意力的 2D 和 3D 适应,后者在跨深度方面表现出色 数据理解。 这些组件共同塑造了我们新颖的分层 Vision Transformer 架构,即 D-LKA Net。根据流行的医学分割数据集(Synapse、NIH 胰腺和皮肤病变)上的领先方法对我们的模型进行的评估证明了其卓越的性能。为了解决这些挑战,我们引入了Deformable Large Kernel Attention (D-LKA Attention)}的概念,这是一种采用大卷积核来充分理解体积上下文的简化注意力机制。这种机制在类似于自注意力的感受野中运行,同时避免了计算开销。 此外,我们提出的注意力机制受益于可变形卷积来灵活地扭曲采样网格,使模型能够适当地适应不同的数据模式。 我们设计了 D-LKA Attention 的 2D 和 3D 适应,后者在跨深度数据理解方面表现出色。4.实验结果分析 mAP@0.5从原始的0.929提升至0.933YOLOv8_C2f_deformable_LKA summary (fused): 189 layers, 4336387 parameters, 0 gradients, 12.8 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 17/17 [01:24<00:00, 4.98s/it]
all 540 18086 0.917 0.889 0.933 0.43
神机妙算
halcon学习和实践(第一个范例threshold.hdev)
对于halcon学习,一个比较好的学习方法就是学习它的范例,效果虽然慢,但是作用是实实在在的。范例中不仅包含了很多的应用case,而且可以通过这些范例,可以学习问题解决的思路是什么样子的。只要有了这些思路,遇到问题的时候才不会那么慌张。 打开halcon之后,只要输入ctrl+E,或者是依次输入文件-》浏览HDevelop示例程序,就可以看到对应的窗口,比如像这样, 左边是各种各样分类的方法,右边是具体的案例。不失一般性,我们可以找一个blob分析,然后选择一个threashold.hdev的案例来进行分析, 打开后似乎什么也没有,没关系,这个时候只需要单击上面的执行按钮就可以看到效果了, 不出意外的话,你就会看到这样的执行结果, 上面整个截图有四个部分,左上是一副图片,上面有几个彩色的部分,看上去所有的操作都是为了为了找到这几个彩色的连通区域;左下有很多小图片,看上去应该是执行过程中的中间结果;右上是查找执行函数使用的;右下是执行的脚本。我们可以进一步分析这个脚本是做什么的,read_image (Audi2, 'audi2')
fill_interlace (Audi2, ImageFilled, 'odd')
threshold (ImageFilled, Region, 0, 90)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'width', 'and', 30, 70)
select_shape (SelectedRegions, Letters, 'height', 'and', 60, 110)
dev_clear_window ()
dev_set_colored (12)
dev_display (ImageFilled)
dev_display (Letters) 脚本内容看上去有点像python脚本,当然这不重要。第一行read_image,顾名思义,应该是读取图片;第二行fill_interlace,不太懂,暂且认为是图像增强的功能吧;第三行threshold,这个好理解,就是二值化;第四行connection,听名字好像是区域连接,姑且认为是分割吧;第五行和第六行是select_shape,两个函数一样,但是参数不一样,一个是width,一个是height,从字面上看,应该是从之前的分割区域中筛选出合适的区域。第七行dev_clear_window,从名字上看是清除窗口。第八行dev_set_colored,字面上看是设置颜色;第九行和第十行都是dev_display,很明显这是一个显示函数,只不过一个显示的是原图像,一个显示的是分割后的图像,两者叠加在一起。 有了上面的分析,我们可以清楚的知道,这就是一个车牌识别的程序。 也许 有的同学会说,能不能单步调试呢,其实这是完全可以的,也是比较推荐的调试方法,选择F2重新执行, 接着就是单步执行,可以输入F6,或者是单击这个按钮, 上面这些步骤,大家都可以在安装halcon之后,在自己的电脑上完成。学习图像固然需要花费一些时间,但是只要一步一步去做,总能学会的。
神机妙算
halcon学习和实践(从halcon转化为opencv)
halcon本身还是商业软件,从学习的角度来使用无可厚非,但是如果用在商业上面,那么就必须要获得halcon的授权,这是底线。那么既然学了halcon,又不想支付高额的授权费用,那么只有两条路了。第一个就是自己写一个image的库,另外一个就是寻找开源库,比如opencv就是其中的一种开源库。 从最早的opencv2开始,目前最新的opencv已经进化到了opencv4。opencv目前支持的语言主要是c++和python两种。c++基础比较好的同学,完全可以用c++来进行开发,这主要体现在最终部署上面。而在平时学习的时候,最好使用python来学习,这样比较方便,也比较快捷。因为在图像处理的过程中,一个很重要的部分,就是参数的标定工作。如果每次都是用c++来测试的话,那么标定一次,就要重新编译一次。这就显得很麻烦。当然也有比较讨巧的办法,就是把标定的数据变成字符串,这样不重新编译c++,直接修改exe文件也可以达成调参不重编的目的。 还是以之前audi2的例子为证,我们看一下如果需要变成opencv应该怎么做。 首先,还是看一下halcon的代码,read_image (Audi2, 'audi2')
fill_interlace (Audi2, ImageFilled, 'odd')
threshold (ImageFilled, Region, 0, 90)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'width', 'and', 30, 70)
select_shape (SelectedRegions, Letters, 'height', 'and', 60, 110)
dev_clear_window ()
dev_set_colored (12)
dev_display (ImageFilled)
dev_display (Letters) 这段代码相信大家看了很多遍,早已经熟记在心。那么,下面需要做的就是一个一个找到对应的opencv函数即可, read_image ===>cv2.imread
threshold===>cv2.threshold
connection===>cv2.findContours
select_shape===>cv2.boundingRect
dev_display===>cv2.drawContours & cv2.imshow 对于算法中的参数,基本上也可以作为参考。当然,这里因为暂时没有找到原来的图片,所以在参数上面稍做了修改。经过这些处理之后,最终获得的opencv代码如下所示,import numpy as np
import cv2
img = cv2.imread('./audi2.png')
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret1, img_thresh = cv2.threshold(imgGray, 90, 255, cv2.THRESH_BINARY)
_, contours, hierarchy = cv2.findContours(img_thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for i,c in enumerate(contours):
x,y,w,h = cv2.boundingRect(c)
if w < 10 or w > 60:
continue
if h < 40 or h > 150:
continue
cv2.drawContours(img, contours, i, (0, 0, 255), 3)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows() 利用python命令,直接运行代码,python demo.py 不出意外,我们就可以获得这样的运行效果,基本可以满足我们的要求,
神机妙算
YOLOv8改进:注意力系列篇 | SRM特征重新校准方法,效果优于SE、GE,且参数的数量较少
🚀🚀🚀本文改进: SRM特征重新校准方法,引入到YOLOv8,多种实现方式🚀🚀🚀SRM在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.SRM介绍 SRM的总体结构如 Figure 1 所示。它由两个主要组件组成:Style Pooling 和 Style Integration。Style Pooling 运算符通过汇总跨空间维度的特征响应来从每个通道提取风格特征。紧随其后的是 Style Integration 运算符,该运算符通过基于通道的操作利用风格特征来生成特定于示例的风格权重。 SRM首先通过“style pooling”从特征图的每个通道中提取风格信息,然后通过与通道无关的风格集成来估计每个通道的重新校准权重。通过将单个风格的相对重要性纳入特征图,SRM有效地增强了CNN的表示能力。 Figure 3 展示了带有 SRM 和其他特征重新校准方法的 ResNet-50 的训练和验证曲线。在整个训练过程中,无论是在训练还是在验证曲线上,SRM的准确性都比SE和GE高得多。这意味着,在SRM中使用风格,比在SE中建模通道相关性或在GE中收集全局上下文更有效,这两方面都有助于训练和提高泛化能力。值得注意的是,SRM的性能优于SE和GE,其附加参数的数量较少。 2.SRM加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### SRM attention #### START ##############################
"""
PyTorch implementation of Srm : A style-based recalibration module for
convolutional neural networks
As described in https://arxiv.org/pdf/1903.10829
SRM first extracts the style information from each channel of the feature maps by style pooling,
then estimates per-channel recalibration weight via channel-independent style integration.
By incorporating the relative importance of individual styles into feature maps,
SRM effectively enhances the representational ability of a CNN.
"""
import torch
from torch import nn
class SRM(nn.Module):
def __init__(self, feature, channel):
super().__init__()
self.cfc = nn.Conv1d(channel, channel, kernel_size=2, groups=channel,
bias=False)
self.bn = nn.BatchNorm1d(channel)
def forward(self, x):
b, c, h, w = x.shape
# style pooling
mean = x.reshape(b, c, -1).mean(-1).unsqueeze(-1)
std = x.reshape(b, c, -1).std(-1).unsqueeze(-1)
u = torch.cat([mean, std], dim=-1)
# style integration
z = self.cfc(u)
z = self.bn(z)
g = torch.sigmoid(z)
g = g.reshape(b, c, 1, 1)
return x * g.expand_as(x)
###################### SRM attention #### END ############################### 2.2 修改tasks.py首先SRM进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3
,SRM):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_SRM.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, SRM, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_SRM2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, SRM, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, SRM, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, SRM, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_SRM3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, SRM, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, SRM, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, SRM, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, SRM, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(七):HIC-YOLOv8复现HIC-YOLOv5,助力
本文改进: 新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互;如何在YOLOv8下使用:1)作为注意力机制放在各个网络位置;2)与C2f结合替代原始的C2fMSCA多尺度特性在交通摄像头下车辆检测项目中, mAP50从原始的0.745提升至0.756学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。系。 2.HIC-YOLOv5介绍摘要:小目标检测一直是目标检测领域的一个具有挑战性的问题。 已经有一些工作提出了对该任务的改进,例如添加几个注意力块或改变特征融合网络的整体结构。 然而,这些模型的计算成本很大,这使得部署实时目标检测系统不可行,同时还有改进的空间。 为此,提出了一种改进的YOLOv5模型:HICYOLOv5来解决上述问题。 首先,添加一个针对小物体的额外预测头,以提供更高分辨率的特征图,以实现更好的预测。 其次,在backbone和neck之间采用involution block来增加特征图的通道信息。 此外,在主干网末端应用了一种名为 CBAM 的注意力机制,与之前的工作相比,不仅降低了计算成本,而且还强调了通道和空间域中的重要信息。 我们的结果表明,HIC-YOLOv5 在 VisDrone-2019-DET 数据集上将 mAP@[.5:.95] 提高了 6.42%,将 mAP@0.5 提高了 9.38%。 2.1 Convolutional Block Attention Module(CBAM)介绍 论文地址:https://arxiv.org/pdf/1807.06521.pdf 摘要:我们提出了卷积块注意力模块(CBAM),这是一种用于前馈卷积神经网络的简单而有效的注意力模块。 给定中间特征图,我们的模块沿着两个独立的维度(通道和空间)顺序推断注意力图,然后将注意力图乘以输入特征图以进行自适应特征细化。 由于 CBAM 是一个轻量级通用模块,因此它可以无缝集成到任何 CNN 架构中,且开销可以忽略不计,并且可以与基础 CNN 一起进行端到端训练。 我们通过在 ImageNet-1K、MS COCO 检测和 VOC 2007 检测数据集上进行大量实验来验证我们的 CBAM。我们的实验显示各种模型在分类和检测性能方面的持续改进,证明了 CBAM 的广泛适用性。 代码和模型将公开。 上图可以看到,CBAM包含CAM(Channel Attention Module)和SAM(Spartial Attention Module)两个子模块,分别进行通道和空间上的Attention。这样不只能够节约参数和计算力,并且保证了其能够做为即插即用的模块集成到现有的网络架构中去。2.2 Involution原理介绍论文链接:https://arxiv.org/abs/2103.06255作者认为卷积操作的两个特征虽然也有一定的优势,但同样也有缺点。所以提出了Involution,Involution所拥有的特征正好和卷积相对称,即 spatial-specific and channel-agnostic那就是通道无关和特定于空间。和卷积一样,内卷也有内卷核(involution kernels)。内卷核在空间范围上是不同的,但在通道之间共享。看到这里就有一定的画面感了。内卷的优点:1.可以在更大的空间范围中总结上下文信息,从而克服long-range interaction(本来的卷积操作只能在特定的小空间如3x3中集合空间信息)2.内卷可以将权重自适应地分配到不同的位置,从而对空间域中信息量最大的视觉元素进行优先级排序。(本来的卷积在空间的每一个地方都是用到同一个卷积核,用的同一套权重)重新考虑了视觉任务标准卷积的固有原理,特别是与空间无关和特定于通道的方法。取而代之的是,我们通过反转前述的卷积设计原理(称为卷积)提出了一种用于深度神经网络的新颖atomic操作。2.3 多头检测器在进行目标检测时,小目标会出现漏检或检测效果不佳等问题。YOLOv8有3个检测头,能够多尺度对目标进行检测,但对微小目标检测可能存在检测能力不佳的现象,因此添加一个微小物体的检测头,能够大量涨点,map提升明显;源码:YOLOv8改进:复现HIC-YOLOv5,助力小目标检测-CSDN博客3.训练可视化分析 mAP50从原始的0.745提升至0.802YOLOv8_HIC-YOLOv8 summary (fused): 221 layers, 3004550 parameters, 0 gradients, 12.2 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 19/19 [00:12<00:00, 1.49it/s]
all 582 6970 0.816 0.711 0.775 0.407训练结果如下:PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。
神机妙算
YOLOv8优化:注意力系列篇 | CoordAttention,捕捉空间上的局部关系和全局关系,效
🚀🚀🚀本文改进:CoordAttention注意力,引入到YOLOv8,多种实现方式🚀🚀🚀CoordAttention在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.CoordAttention CoordAttention是一种注意力机制,在计算机视觉中被广泛应用。它可以捕捉特定位置的空间关系,并在注意力计算中加以利用。与常规的注意力机制不同,CoordAttention在计算注意力时,不仅会考虑输入的特征信息,还会考虑每个像素点的位置信息,从而更好地捕捉空间上的局部关系和全局关系。这种注意力机制可以应用于许多计算机视觉任务,如图像分类、目标检测和语义分割等。 新加坡国立大学的Qibin Hou等人提出了一种为轻量级网络设计的新的注意力机制,该机制将位置信息嵌入到了通道注意力中,称为coordinate attention(简称CoordAttention,下文也称CA),该论文已被CVPR2021收录。 CoordAttention简单灵活且高效,可以插入经典的轻量级网络(如MobileNetV2)在几乎不带来额外计算开销的前提下,提升网络的精度。实验表明,CoordAttention不仅仅对于分类任务有不错的提高,对目标检测、实例分割这类密集预测的任务,效果提升更加明显。 SE、CBAM和CA模块注意力结果可视化,CA更能精确关注感兴趣目标。 效果秒杀CBAM、SE2.CoordAttention加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### CoordAtt #### start ###############################
import torch
import torch.nn as nn
import torch.nn.functional as F
class h_sigmoid(nn.Module):
def __init__(self, inplace=True):
super(h_sigmoid, self).__init__()
self.relu = nn.ReLU6(inplace=inplace)
def forward(self, x):
return self.relu(x + 3) / 6
class h_swish(nn.Module):
def __init__(self, inplace=True):
super(h_swish, self).__init__()
self.sigmoid = h_sigmoid(inplace=inplace)
def forward(self, x):
return x * self.sigmoid(x)
class CoordAtt(nn.Module):
def __init__(self, inp, reduction=32):
super(CoordAtt, self).__init__()
self.pool_h = nn.AdaptiveAvgPool2d((None, 1))
self.pool_w = nn.AdaptiveAvgPool2d((1, None))
mip = max(8, inp // reduction)
self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0)
self.bn1 = nn.BatchNorm2d(mip)
self.act = h_swish()
self.conv_h = nn.Conv2d(mip, inp, kernel_size=1, stride=1, padding=0)
self.conv_w = nn.Conv2d(mip, inp, kernel_size=1, stride=1, padding=0)
def forward(self, x):
identity = x
n, c, h, w = x.size()
x_h = self.pool_h(x)
x_w = self.pool_w(x).permute(0, 1, 3, 2)
y = torch.cat([x_h, x_w], dim=2)
y = self.conv1(y)
y = self.bn1(y)
y = self.act(y)
x_h, x_w = torch.split(y, [h, w], dim=2)
x_w = x_w.permute(0, 1, 3, 2)
a_h = self.conv_h(x_h).sigmoid()
a_w = self.conv_w(x_w).sigmoid()
out = identity * a_w * a_h
return out
###################### CoordAtt #### end ############################### 2.2 修改tasks.py首先CoordAtt进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,
CoordAtt):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_CoordAtt.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, CoordAtt, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_CoordAtt2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, CoordAtt, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, CoordAtt, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, CoordAtt, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_CoordAtt3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, CoordAtt, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, CoordAtt, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, CoordAtt, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, CoordAtt, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
YOLOv8优化:注意力系列篇 | 高斯上下文变换器GCT,性能优于ECA、SE等注意力
🚀🚀🚀本文改进:高斯上下文变换器GCT,引入到YOLOv8,多种实现方式🚀🚀🚀GCT在不同检测领域中应用广泛🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.GCT介绍浙江大学等机构发布的一篇收录于CVPR2021的文章,提出了一种新的通道注意力结构,在几乎不引入参数的前提下优于大多SOTA通道注意力模型,如SE、ECA等。这篇文章虽然叫Gaussian Context Transformer,但是和Transformer并无太多联系,这里可以理解为高斯上下文变换器。 LCT(linear context transform)观察所得,如下图所示,SE倾向于学习一种负相关,即全局上下文偏离均值越多,得到的注意力激活值就越小。为了更加精准地学习这种相关性,LCT使用一个逐通道地变换来替代SE中的两个全连接层。然而,实验表明,LCT学得的这种负相关质量并不是很高,下图中右侧可以看出,LCT的注意力激活值波动是很大的。 在本文中,我们假设这种关系是预先确定的。基于这个假设,我们提出了一个简单但极其有效的通道注意力块,称为高斯上下文Transformer (GCT),它使用满足预设关系的高斯函数实现上下文特征激励。实验结果在ImageNet 和 MS COCO 基准测试的大量实验表明,我们的 GCT 导致各种深度 CNN 和检测器的持续改进。与一系列最先进的通道注意力块(例如 SE 和 ECA)相比,我们的 GCT 在有效性和效率方面更为出色。2.GCT加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### GCT #### start ###############################
"""
PyTorch implementation of Gaussian Context Transformer
As described in http://openaccess.thecvf.com//content/CVPR2021/papers/Ruan_Gaussian_Context_Transformer_CVPR_2021_paper.pdf
Gaussian Context Transformer (GCT), which achieves contextual feature excitation using
a Gaussian function that satisfies the presupposed relationship.
"""
import torch
from torch import nn
class GCTattention(nn.Module):
def __init__(self, channels, c=2, eps=1e-5):
super().__init__()
self.avgpool = nn.AdaptiveAvgPool2d(1)
self.eps = eps
self.c = c
def forward(self, x):
y = self.avgpool(x)
mean = y.mean(dim=1, keepdim=True)
mean_x2 = (y ** 2).mean(dim=1, keepdim=True)
var = mean_x2 - mean ** 2
y_norm = (y - mean) / torch.sqrt(var + self.eps)
y_transform = torch.exp(-(y_norm ** 2 / 2 * self.c))
return x * y_transform.expand_as(x)
###################### Gaussian Context Transformer attention #### END ############################### 2.2 修改tasks.py首先GCTattention进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,GCTattention):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_GCTattention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, GCTattention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_GCTattention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, GCTattention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, GCTattention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, GCTattention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_GCTattention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, GCTattention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, GCTattention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, GCTattention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, GCTattention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(三):Wasserstein Distance Loss
🚀🚀🚀本文改进: 新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互;如何在YOLOv8下使用:1)作为注意力机制放在各个网络位置;2)与C2f结合替代原始的C2f🚀🚀🚀MSCA多尺度特性在交通摄像头下车辆检测项目中, mAP50从原始的0.745提升至0.756🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研;1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。2.Wasserstein Distance Loss介绍 论文名称:《A Normalized Gaussian Wasserstein Distance for Tiny Object Detection》作者:Jinwang Wang、Chang Xu、Chang Xu、Lei Yu论文地址:https://arxiv.org/abs/2110.13389小目标检测是一个非常具有挑战性的问题,因为小目标只包含几个像素大小。作者证明,由于缺乏外观信息,最先进的检测器也不能在小目标上得到令人满意的结果。作者的主要观察结果是,基于IoU (Intersection over Union, IoU)的指标,如IoU本身及其扩展,对小目标的位置偏差非常敏感,在基于Anchor的检测器中使用时,严重降低了检测性能。为了解决这一问题,本文提出了一种新的基于Wasserstein距离的小目标检测评估方法。具体来说,首先将BBox建模为二维高斯分布,然后提出一种新的度量标准,称为Normalized Wasserstein Distance(NWD),通过它们对应的高斯分布计算它们之间的相似性。提出的NWD度量可以很容易地嵌入到任何基于Anchor的检测器的Assignment、非最大抑制和损失函数中,以取代常用的IoU度量。1)分析了 IoU 对微小物体位置偏差的敏感性,并提出 NWD 作为衡量两个边界框之间相似性的更好指标;2)通过将NWD 应用于基于锚的检测器中的标签分配、NMS 和损失函数来设计强大的微小物体检测器;3)提出的 NWD 可以显着提高流行的基于锚的检测器的 TOD 性能,它在 AI-TOD 数据集上的 Faster R-CNN 上实现了从 11.1% 到 17.6% 的性能提升; 具体来说,对于6×6像素的小目标,轻微的位置偏差会导致明显的IoU下降(从0.53下降到0.06),导致标签分配不准确。然而,对于36×36像素的正常目标,IoU略有变化(从0.90到0.65),位置偏差相同。此外,图2给出了4条不同目标尺度的IoU-Deviation曲线,随着目标尺度的减小,曲线下降速度更快。值得注意的是,IoU的敏感性来自于BBox位置只能离散变化的特殊性。 Wasserstein distance的主要优点是:无论小目标之间有没有重叠都可以度量分布相似性;NWD对不同尺度的目标不敏感,更适合测量小目标之间的相似性。NWD可应用于One-Stage和Multi-Stage Anchor-Based检测器。此外,NWD不仅可以替代标签分配中的IoU,还可以替代非最大抑制中的IoU(NMS)和回归损失函数。在一个新的TOD数据集AI-TOD上的大量实验表明,本文提出的NWD可以持续地提高所有检测器的检测性能。3.训练可视化分析 mAP50从原始的0.745提升至0.759YOLOv8n_nwdloss summary (fused): 168 layers, 3005843 parameters, 0 gradients, 8.1 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 19/19 [00:15<00:00, 1.25it/s]
all 582 6970 0.814 0.686 0.759 0.392训练结果如下:PR_curve.png PR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关
神机妙算
halcon学习和实践(hdev脚本学习技巧)
上一节我们提到了第一个halcon的脚本,也就是threshold.hdev。有过编码经验的同学看到这段代码,可能不会感到学习上有什么难度。但是对于一些plc开发的同学来说,特别是熟悉梯形图开发的朋友来说,学习上或许还是有一定的困难的。所以,这里提供一个hdev脚本的技巧。 首先,还是重新看一下这个脚本,read_image (Audi2, 'audi2')
fill_interlace (Audi2, ImageFilled, 'odd')
threshold (ImageFilled, Region, 0, 90)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'width', 'and', 30, 70)
select_shape (SelectedRegions, Letters, 'height', 'and', 60, 110)
dev_clear_window ()
dev_set_colored (12)
dev_display (ImageFilled)
dev_display (Letters) 我们知道每一个算子都有它的输入和输出,所以,这里可以先确定一个模型, 从上面的算子来说,每一个算子都有一个或者若干个输入,但是输出一般只有一个。对于function1来说,它的输入就是input1,它的输出是output1。对于function2呢,function1的output1就是它的input1,它自己的输出就是output2,这里output1只是input2的一部分,可能function2还有其他输入。function3也是这样,依次类推。 回到上面的脚本代码,第一行代码read_image (Audi2, 'audi2') 很明显,输入是图片名称'audi2',输出是图片数据Audi2。 紧接着分析第二行代码,fill_interlace (Audi2, ImageFilled, 'odd') 这里我们看到第一行的输出Audi2,当然也多了一个输入'odd',输出为ImageFilled。 继续分析第三行代码,threshold (ImageFilled, Region, 0, 90) 经过观察发现,第二行的输出ImageFilled变成了这里的输入,除此之外,多了两个输入,一个是0,一个是90,输出是Region。 第四行到第六行代码,大家可以自己去分析。 接着分析第七行代码,dev_clear_window () 这里既没有看到输入,也没有看到输出,因此可以看成是全局设定。 分析第八行代码,dev_set_colored (12) 这里只有一个12输入,同样没有输出,所以可以看成是全局设定。 继续分析第九行、第十行代码,dev_display (ImageFilled)
dev_display (Letters) 上面两行代码只有输入,没有输出。进一步查找发现,ImageFilled是第二行的输出结果,Letters是第六行输出结果。所以,这里也可以近似看成是全局设定,主要是为了显示处理后的图像结果。因为不涉及到图像的继续处理,所以也就没有输出。当然如果说有输出的话,那么输出的对象就是窗口屏幕,这也就是讲得通的。 所以,不管hdev脚本多么复杂,基本都是参考上面的逻辑来执行的。只要掌握了上面给出的模型,掌握hdev脚本不会很复杂的。
神机妙算
YOLOv8优化:注意力系列篇 | 卷积块注意力模块(CBAM)
🚀🚀🚀本文改进:CBAM注意力,引入到YOLOv8,多种实现方式🚀🚀🚀CBAM在不同检测领域中应用广泛 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.CBAM注意力介绍 论文地址:https://arxiv.org/pdf/1807.06521.pdf 摘要:我们提出了卷积块注意力模块(CBAM),这是一种用于前馈卷积神经网络的简单而有效的注意力模块。 给定中间特征图,我们的模块沿着两个独立的维度(通道和空间)顺序推断注意力图,然后将注意力图乘以输入特征图以进行自适应特征细化。 由于 CBAM 是一个轻量级通用模块,因此它可以无缝集成到任何 CNN 架构中,且开销可以忽略不计,并且可以与基础 CNN 一起进行端到端训练。 我们通过在 ImageNet-1K、MS COCO 检测和 VOC 2007 检测数据集上进行大量实验来验证我们的 CBAM。我们的实验显示各种模型在分类和检测性能方面的持续改进,证明了 CBAM 的广泛适用性。 代码和模型将公开。 上图可以看到,CBAM包含CAM(Channel Attention Module)和SAM(Spartial Attention Module)两个子模块,分别进行通道和空间上的Attention。这样不只能够节约参数和计算力,并且保证了其能够做为即插即用的模块集成到现有的网络架构中去。2.CBAM加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### CBAM #### start ###############################
import torch
import torch.nn as nn
from torch.nn import functional as F
class ChannelAttention(nn.Module):
# Channel-attention module https://github.com/open-mmlab/mmdetection/tree/v3.0.0rc1/configs/rtmdet
def __init__(self, channels: int) -> None:
super().__init__()
self.pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Conv2d(channels, channels, 1, 1, 0, bias=True)
self.act = nn.Sigmoid()
def forward(self, x: torch.Tensor) -> torch.Tensor:
return x * self.act(self.fc(self.pool(x)))
class SpatialAttention(nn.Module):
# Spatial-attention module
def __init__(self, kernel_size=7):
super().__init__()
assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
padding = 3 if kernel_size == 7 else 1
self.cv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
self.act = nn.Sigmoid()
def forward(self, x):
return x * self.act(self.cv1(torch.cat([torch.mean(x, 1, keepdim=True), torch.max(x, 1, keepdim=True)[0]], 1)))
class CBAM(nn.Module):
# Convolutional Block Attention Module
def __init__(self, c1, kernel_size=7): # ch_in, kernels
super().__init__()
self.channel_attention = ChannelAttention(c1)
self.spatial_attention = SpatialAttention(kernel_size)
def forward(self, x):
return self.spatial_attention(self.channel_attention(x))
###################### CBAM #### end ############################### 2.2 修改tasks.py首先CBAM进行注册from ultralytics.nn.attention.attention import *函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改 #####attention ####
elif m in (CBAM,SimAM,MHSA,ECAAttention,TripletAttention,BAM,CoTAttention,PolarizedSelfAttention):
c1, c2 = ch[f], args[0]
if c2 != nc:
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, *args[1:]]
#####attention #### 2.3 yaml实现2.3.1 yolov8_CBAM.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, CBAM, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_CBAM2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, CBAM, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, CBAM, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, CBAM, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_CBAM3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, CBAM, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, CBAM, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, CBAM, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, CBAM, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
halcon学习和实践(导出cpp文件)
halcon除了编写脚本文件之外,还可以导出cpp文件。因为,最终的功能总是要给客户使用的,相关的软件也要部署到客户的机器上的,总不能把hdevelop软件安装在客户的电脑上吧。这也不是很合适。 还是以上次的脚本为例,看一下如何导出cpp代码。导出cpp的方法也很简单,选择文件-》导出即可, 格式选择cpp,然后单击导出就可以了, 目前来说,总共支持4种格式的导出方式,分别是c文件、cpp文件、vb文件、c#文件。因为c#编写上位机比较方便,所以需要的同学可以导出为c#文件。当然对c和cpp比较熟悉的朋友,可以导出为对应的文件,界面部分用mfc或者qt编写效果也是一样的。 我们可以阅读一下这个生成的cpp文件,源代码如下所示,///
// File generated by HDevelop for HALCON/C++ Version 13.0.2
///
#ifndef __APPLE__
# include "HalconCpp.h"
# include "HDevThread.h"
# if defined(__linux__) && !defined(__arm__) && !defined(NO_EXPORT_APP_MAIN)
# include <X11/Xlib.h>
# endif
#else
# ifndef HC_LARGE_IMAGES
# include <HALCONCpp/HalconCpp.h>
# include <HALCONCpp/HDevThread.h>
# else
# include <HALCONCppxl/HalconCpp.h>
# include <HALCONCppxl/HDevThread.h>
# endif
# include <stdio.h>
# include <HALCON/HpThread.h>
# include <CoreFoundation/CFRunLoop.h>
#endif
using namespace HalconCpp;
#ifndef NO_EXPORT_MAIN
// Main procedure
void action()
{
// Local iconic variables
HObject ho_Audi2, ho_ImageFilled, ho_Region;
HObject ho_ConnectedRegions, ho_SelectedRegions, ho_Letters;
ReadImage(&ho_Audi2, "audi2");
FillInterlace(ho_Audi2, &ho_ImageFilled, "odd");
Threshold(ho_ImageFilled, &ho_Region, 0, 90);
Connection(ho_Region, &ho_ConnectedRegions);
SelectShape(ho_ConnectedRegions, &ho_SelectedRegions, "width", "and", 30, 70);
SelectShape(ho_SelectedRegions, &ho_Letters, "height", "and", 60, 110);
if (HDevWindowStack::IsOpen())
ClearWindow(HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
SetColored(HDevWindowStack::GetActive(),12);
if (HDevWindowStack::IsOpen())
DispObj(ho_ImageFilled, HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
DispObj(ho_Letters, HDevWindowStack::GetActive());
}
#ifndef NO_EXPORT_APP_MAIN
#ifdef __APPLE__
// On OS X systems, we must have a CFRunLoop running on the main thread in
// order for the HALCON graphics operators to work correctly, and run the
// action function in a separate thread. A CFRunLoopTimer is used to make sure
// the action function is not called before the CFRunLoop is running.
// Note that starting with macOS 10.12, the run loop may be stopped when a
// window is closed, so we need to put the call to CFRunLoopRun() into a loop
// of its own.
HTuple gStartMutex;
H_pthread_t gActionThread;
HBOOL gTerminate = FALSE;
static void timer_callback(CFRunLoopTimerRef timer, void *info)
{
UnlockMutex(gStartMutex);
}
static Herror apple_action(void **parameters)
{
// Wait until the timer has fired to start processing.
LockMutex(gStartMutex);
UnlockMutex(gStartMutex);
try
{
action();
}
catch (HException &exception)
{
fprintf(stderr," Error #%u in %s: %s\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());
}
// Tell the main thread to terminate itself.
LockMutex(gStartMutex);
gTerminate = TRUE;
UnlockMutex(gStartMutex);
CFRunLoopStop(CFRunLoopGetMain());
return H_MSG_OK;
}
static int apple_main(int argc, char *argv[])
{
Herror error;
CFRunLoopTimerRef Timer;
CFRunLoopTimerContext TimerContext = { 0, 0, 0, 0, 0 };
CreateMutex("type","sleep",&gStartMutex);
LockMutex(gStartMutex);
error = HpThreadHandleAlloc(&gActionThread);
if (H_MSG_OK != error)
{
fprintf(stderr,"HpThreadHandleAlloc failed: %d\n", error);
exit(1);
}
error = HpThreadCreate(gActionThread,0,apple_action);
if (H_MSG_OK != error)
{
fprintf(stderr,"HpThreadCreate failed: %d\n", error);
exit(1);
}
Timer = CFRunLoopTimerCreate(kCFAllocatorDefault,
CFAbsoluteTimeGetCurrent(),0,0,0,
timer_callback,&TimerContext);
if (!Timer)
{
fprintf(stderr,"CFRunLoopTimerCreate failed\n");
exit(1);
}
CFRunLoopAddTimer(CFRunLoopGetCurrent(),Timer,kCFRunLoopCommonModes);
for (;;)
{
HBOOL terminate;
CFRunLoopRun();
LockMutex(gStartMutex);
terminate = gTerminate;
UnlockMutex(gStartMutex);
if (terminate)
break;
}
CFRunLoopRemoveTimer(CFRunLoopGetCurrent(),Timer,kCFRunLoopCommonModes);
CFRelease(Timer);
error = HpThreadHandleFree(gActionThread);
if (H_MSG_OK != error)
{
fprintf(stderr,"HpThreadHandleFree failed: %d\n", error);
exit(1);
}
ClearMutex(gStartMutex);
return 0;
}
#endif
int main(int argc, char *argv[])
{
int ret = 0;
try
{
#if defined(_WIN32)
SetSystem("use_window_thread", "true");
#elif defined(__linux__) && !defined(__arm__)
XInitThreads();
#endif
// Default settings used in HDevelop (can be omitted)
SetSystem("width", 512);
SetSystem("height", 512);
#ifndef __APPLE__
action();
#else
ret = apple_main(argc,argv);
#endif
}
catch (HException &exception)
{
fprintf(stderr," Error #%u in %s: %s\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());
ret = 1;
}
return ret;
}
#endif
#endif
整个代码的长度大约200行,不算很长,在可以接受的范围内。通过观察发现,主要的图像操作代码都被翻译到了action这个函数里面。 代码从main函数开始。分成两种情况,一种是没有定义__APPLE__宏,也就是mac电脑的宏;一种是定义了__APPLE__宏。如果没有定义这个宏,那么使用就比较简单,main函数直接调用action函数即可。 如果定义了__APPLE__宏,那么流程稍微复杂一点,首先它会调用apple_main函数,在apple_main函数里面会创建一个入口是apple_action函数的线程。这个线程没有立即开始执行,直到apple_main创建一个Timer的定时器,并且timer_callback回调函数中释放gStartMutex之后,apple_action才开始执行。在apple_action中会继续调用action函数,调用结束后,会设置g_Terminate为true,这样app_main函数就可以跳出循环等待,整个操作也就这样完成了。 一般编译c、cpp代码都需要include目录、lib目录和dll目录,这部分和平台有关,相差不大,剩下来的工作就是把这段代码集成到自己的上位机软件中即可。1)include目录位置C:\Program Files\MVTec\HALCON-13.0\include2)lib目录位置C:\Program Files\MVTec\HALCON-13.0\lib\x64-win643)dll位置C:\Program Files\MVTec\HALCON-13.0\bin\x64-win64
神机妙算
基于YOLOv8的交通摄像头下车辆检测算法(四):高效的通道先验卷积注意力(CPCA) | 中科院
本文改进: 新的注意力机制——多尺度空洞注意力(MSDA)。MSDA 能够模拟小范围内的局部和稀疏的图像块交互;如何在YOLOv8下使用:1)作为注意力机制放在各个网络位置;2)与C2f结合替代原始的C2fMSCA多尺度特性在交通摄像头下车辆检测项目中, mAP50从原始的0.745提升至0.756YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.交通摄像头车辆检测数据集介绍数据集来源:极市开发者平台-计算机视觉算法开发落地平台-极市科技数据集类别“car",训练集验证集测试集分别5248,582,291张下图可以看出都是车辆数据集具有不同尺寸的目标物体,既有大目标又有小目标 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。系。 2.CPCA介绍 论文:[2306.05196] Channel prior convolutional attention for medical image segmentation (arxiv.org)摘要:本文提出了一种高效的通道先验卷积注意力(CPCA)方法,支持注意力权重在通道和空间维度上的动态分布。 通过采用多尺度深度卷积模块,可以有效地提取空间关系,同时保留通道先验。 CPCA具备聚焦信息渠道和重要区域的能力。 基于 CPCA 提出了一种用于医学图像分割的分割网络 CPCANet。 CPCANet 在两个公开可用的数据集上进行了验证。 通过与最先进的算法进行比较,CPCANet 提高了分割性能,同时需要更少的计算资源。 现有研究问题点:虽然 CBAM 整合了通道注意和空间注意,但它在其输出特征的所有通道上强制执行一致的空间注意分布。相反,SE(图 1(a))只整合了通道注意,这限制了它选择重要区域的能力。本文创新:如图 1(c) 所示,作者提出了一种新的通道优先卷积注意力(Channel Prior Convolutional Attention,CPCA)方法,采用多尺度的深度可分离卷积模块构成空间注意力,可以在通道和空间维度上动态分配注意权重。 图3:通道先验卷积注意力(CPCA)的整体结构包括通道注意力和空间注意力的顺序放置。特征图的空间信息是由通道注意力通过平均池化和最大池化等操作来聚合的。 随后,空间信息通过共享 MLP(多层感知器)进行处理并添加以生成通道注意力图。 通道先验是通过输入特征和通道注意力图的元素相乘获得的。 随后,通道先验被输入到深度卷积模块中以生成空间注意力图。 卷积模块接收空间注意力图以进行通道混合。 最终,通过通道混合结果与通道先验的逐元素相乘,获得细化的特征作为输出。 通道混合过程有助于增强特征的表示详见:YOLOv8改进:注意力系列篇 |高效的通道先验卷积注意力(CPCA) | 中科院 2023.6-CSDN博客3.训练可视化分析 mAP50从原始的0.745提升至0.748YOLOv8_CPCA summary (fused): 181 layers, 3100564 parameters, 0 gradients, 8.3 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 19/19 [00:17<00:00, 1.09it/s]
all 582 6970 0.81 0.689 0.748 0.396训练结果如下:PR_curve.pngPR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系。文章知识点与官方知识档案匹配,可进一步学习相关知识
神机妙算
Gold-YOLO,信息聚集-分发(Gather-and-Distribute Mechanism)
🚀🚀🚀本文改进:全新的信息聚集-分发(Gather-and-Distribute Mechanism)GD机制,替代YOLOv8 Neck,实现创新🚀🚀🚀Gold-YOLO在人脸检测小目标识别算法中, mAP@0.5从原始的0.929提升至0.935,mAP50-95从原始的0.43提升至0.435🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK1.人脸识别小目标数据集介绍数据集来源:GitHub - HCIILAB/SCUT-HEAD-Dataset-Release: SCUT HEAD is a large-scale head detection dataset, including 4405 images labeld with 111251 heads.本文章主要通过小目标来进行优化,因此数据集只选择partA部分,总共 2000张,按照7:2:1随机进行分配;下图可以看出都是小目标人脸识别 1.1 小目标检测难点 本文所指的小目标是指COCO中定义的像素面积小于32*32 pixels的物体。小目标检测的核心难点有三个:由本身定义导致的rgb信息过少,因而包含的判别性特征特征过少。数据集方面的不平衡。这主要针对COCO而言,COCO中只有51.82%的图片包含小物体,存在严重的图像级不平衡。具体的统计结果见下图。2.YOLOv8介绍改进点:1.Backbone:使用的依旧是CSP的思想,不过YOLOv5中的C3模块被替换成了C2f模块,实现了进一步的轻量化,同时YOLOv8依旧使用了YOLOv5等架构中使用的SPPF模块;2.PAN-FPN:毫无疑问YOLOv8依旧使用了PAN的思想,不过通过对比YOLOv5与YOLOv8的结构图可以看到,YOLOv8将YOLOv5中PAN-FPN上采样阶段中的卷积结构删除了,同时也将C3模块替换为了C2f模块;3.Decoupled-Head:是不是嗅到了不一样的味道?是的YOLOv8走向了Decoupled-Head;4.YOLOv8抛弃了以往的Anchor-Base,使用了Anchor-Free的思想;5.损失函数:YOLOv8使用VFL Loss作为分类损失,使用DFL Loss+CIOU Loss作为分类损失;6.样本匹配:YOLOv8抛弃了以往的IOU匹配或者单边比例的分配方式,而是使用了Task-Aligned Assigner匹配方式。2.1 C2f模块介绍C2f模块就是参考了C3模块以及ELAN的思想进行的设计,让YOLOv8可以在保证轻量化的同时获得更加丰富的梯度流信息。 代码:class C2f(nn.Module):
# CSP Bottleneck with 2 convolutions
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__()
self.c = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).split((self.c, self.c), 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1)) 3.Gold-YOLO链接:https://arxiv.org/pdf/2309.11331.pdf 代码:https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO单位:华为诺亚方舟实验室 理论部分可参考:超越YOLO系列!华为提出Gold-YOLO:高效实时目标检测器 - 知乎 传统YOLO的问题在检测模型中,通常先经过backbone提取得到一系列不同层级的特征,FPN利用了backbone的这一特点,构建了相应的融合结构:不层级的特征包含着不同大小物体的位置信息,虽然这些特征包含的信息不同,但这些特征在相互融合后能够互相弥补彼此缺失的信息,增强每一层级信息的丰富程度,提升网络性能。原始的FPN结构由于其层层递进的信息融合模式,使得相邻层的信息能够充分融合,但也导致了跨层信息融合存在问题:当跨层的信息进行交互融合时,由于没有直连的交互通路,只能依靠中间层充当“中介”进行融合,导致了一定的信息损失。之前的许多工作中都关注到了这一问题,而解决方案通常是通过添加shortcut增加更多的路径,以增强信息流动。摘要:当前YOLO系列模型通常采用类FPN方法进行信息融合,而这一结构在融合跨层信息时存在信息损失的问题。针对这一问题,我们提出了全新的信息聚集-分发(Gather-and-Distribute Mechanism)GD机制,通过在全局视野上对不同层级的特征进行统一的聚集融合并分发注入到不同层级中,构建更加充分高效的信息交互融合机制,并基于GD机制构建了Gold-YOLO。在COCO数据集中,我们的Gold-YOLO超越了现有的YOLO系列,实现了精度-速度曲线上的SOTA。 提出了一种全新的信息交互融合机制:信息聚集-分发机制(Gather-and-Distribute Mechanism)。该机制通过在全局上融合不同层次的特征得到全局信息,并将全局信息注入到不同层级的特征中,实现了高效的信息交互和融合。在不显著增加延迟的情况下GD机制显著增强了Neck部分的信息融合能力,提高了模型对不同大小物体的检测能力。 在Gold-YOLO中,针对模型需要检测不同大小的物体的需要,并权衡精度和速度,我们构建了两个GD分支对信息进行融合:低层级信息聚集-分发分支(Low-GD)和高层级信息聚集-分发分支(High-GD),分别基于卷积和transformer提取和融合特征信息。4.实验结果分析 mAP@0.5从原始的0.929提升至0.935,mAP50-95从原始的0.43提升至0.435YOLOv8-goldYOLO summary: 359 layers, 6015123 parameters, 0 gradients, 11.9 GFLOPs
Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 17/17 [00:28<00:00, 1.68s/it]
all 540 18086 0.916 0.892 0.935 0.435
神机妙算
halcon学习和实践(工业视觉套路)
和学术领域为了追求正确率尝试各种算法不同,工业视觉领域更多的是一种算法的套路。这些套路有它自己的道理,也有它内在的逻辑,整个过程也比较好解释,所以在工业上面其实用的很广。大家可以来看一看, 在工作当中,会有一个有趣的现象。那就是,早期的很多工业视觉工程师,虽然没有系统学过相关图形图像的原理,但是这并不妨碍他们在实际生产和工作中大量使用工业视觉的相关算法。究其原因,主要是他们了解算法使用的套路,知道怎么把需求和算法匹配起来,所以熟悉了算法理论的同学只要掌握了这个套路,也是可以很快搭建出自己需要的视觉工业开发软件的。1、图像获取 工业图像获取目前主要是usb3和ethernet。ethernet因为可以分布式部署,处理图像的设备可以和摄像头离的很远,camera部署也比较方便,因此在生产中得到了广泛引用。此外,图像获取的这部分工作主要都是由设备厂商来完成的,开发算法的同学只需要复用厂家给出的demo代码即可。2、彩色转黑白 如果选用的是黑白相机,那么获取的图像直接就是黑白图片。反之,如果本身是彩色相机,算法分割对色彩没有特殊要求的话,那么大概率需要自己转换成黑白图像。黑白图像处理数据少一些,但是细节部分还是保留下来了,计算量也小很多,后续的主要算法也是基于黑白图像来完成的。3、降噪 自然界的图片总是会存在噪声的,用合理的算法剔除这些噪声是不错的一个方法。当然,降噪还可以通过控制曝光时间、添加滤光片等方法来解决,不仅仅是降噪算法这一个选项。4、边缘检测 边缘检测是图像处理的一个重要环节。通过边缘检测的解算,大部分边缘细节都被完整保留下来了,那些边缘不是特别明显的部分往往就被忽略了。5、二值化 二值化的意思,后面的黑白图片中,像素值不是0,就是255,没有了中间地带。所以,二值化后的图像,信息进一步聚集,相应的计算量也开始进一步减小了。6、腐蚀 腐蚀运算是非常有用的一个操作。如果本来两个区域,因为一些噪声莫名其妙粘连在一起了,那么用腐蚀运算就可以重新把两个区域分开。7、膨胀 和腐蚀操作对应的就是膨胀了。举个例子,假设本来是一个区域,同样因为噪声分成了两个区域,那么就可以用膨胀操作来解决这个问题。实际操作中,一般用开运算和闭运算来代替。开运算是先腐蚀、再膨胀;闭运算是先膨胀、再腐蚀,具体用哪个看实际情况。8、分割 经过上面的操作之后,图像一般会被分割成若干个小区域。halcon里面用的是connection函数完成,opencv里面用的是findContours函数完成。9、过滤筛选 分割后的区域,并不是每一部分都是符合我们要求的。所以这个时候,只能根据一些特定的属性去筛选和过滤了,比如说长度、宽度、面积、圆度、半径、长宽比等等。halcon用的是select_shape函数,opencv就只能自己写了。10、测量 经过上面的操作之后,这个时候剩下来的区域往往就是自己需要的连通域了。从图像中可以获取很多的信息,比如长度、宽度、位置、大小、面积等等,这些都是可以通过转换测算出来的。11、ocr、分类、预测 随着深度学习的发展,传统的测量和定位已经越来越不能满足客户的需求了。所以,在分割好图像好之后,可以利用模版做进一步的匹配识别操作。此外,对于不规则的图像,可以通过训练模型的方法,进一步从图像中获取故障信息、ocr信息和异常信息等等,这些都是从前的传统图像算法做不了的。即使做,也是基于图像+传统的机器学习算法来做的,比如hog+svm等等,但是它在准确率和效率上面,和深度学习还是比不了的。12、给机器人发送命令 图像识别的目的,主要还是为了获取信息,根据信息生成命令通知给控制机构,或者直接一点就是机械手,进一步完成后面的动作,这样一个工业视觉软件算法才算是真正做完了
神机妙算
halcon学习和实践(设备要求)
和学校里面的只注重图像算法本身不同,真正的机器视觉是以应用为前提的。就算它使用的工业摄像头,也和我们平常pc笔记本上使用的摄像头不一样的。不失一般性,我们可以看下一般机器视觉需要哪些设备,可以用画一个简单的流程图来表示,这样更方便理解, 蓝色的部分,就是机器视觉所需要的设备,分别是光源控制器、光源、镜头、图像传感器、PC工控机或者嵌入式开发板。这里面,光源控制器、图像传感器、PC都是可以执行算法控制的。等所有流程都执行完毕之后,一般会输出对应的控制命令,传递给机器人或者其他机械装置,也就是图中黄色的部分。1、光源控制器 光源控制器一般是控制光的强度,作为补光使用,自然光很多时候并不能满足实际的拍摄需求。此外光源控制器会有通道选择、粗调、细调这些功能,对外提供的控制接口有rs232、rs485。当然这取决于工厂用什么开发板。2、光源 光源是一门大学问。按照形状分,可以有平面光源、环形光源;按照颜色分,可以有白光、蓝光、红光等各色光源;按照照射方法,可以有正面照射和背面照射;此外如果希望夜里也能看见物体,这个时候就需要发射红外光等等。很多同学都把精力花在算法上面,但是对光源了解很少,其实这大可不必。设计好的光源,可以让物体特征和属性更明显地暴露出来,反而有利于简化算法的设计,甚至有时候都不需要复杂的算子,就可以出来很好的处理效果。3、镜头 镜头这个大家都很熟悉,玩摄影的同学更是对徕卡、蔡司这些名字如数家珍。工业上的镜头也很讲究,比如是否需要加偏振片,选择什么样尺寸的镜头,是否需要广角镜头,视场角多少,焦距选择多少的镜头合适,这都需要自己好好测算下的。工业视觉里面,传感器和镜头是分开来的,毕竟不同的场景下的需求是不一样的。这里面两者的接口也有很多种,主要分为卡口和螺口,常用的螺口又分c口、cs口等等,买的时候一定要注意清楚。4、传感器 传感器这部分,大家比较了解的可能就是分辨率。一般认为,分辨率越高越好。当然除了分辨率之外,曝光时间、帧率、对外接口形式、isp设置这些也是需要考虑清楚的。特别是测量和定位,对于不同精度的要求,直接决定了我们需要选择什么样的镜头和传感器。另外,在windows平台上面有一个很好用的软件AMCAP,上面可以很清晰地告诉我们,当前图像传感器支持哪些属性配置, 5、PC工控机或者嵌入式开发板 摄像头连接到算法处理设备上,一般是ethernet或者usb居多。如果分辨率很高,那么ethernet用的多一些,价格也高一些,反之则usb多一点。PC的好处就是资源多,如果资源不够,还可以添加gpu显卡。而嵌入式的好处是性价比比较高,但是开发难度也稍微高一点,如果对性能和成本有一定的要求,那么用嵌入式设备开发也是不错的一个选择。 在一开始学习的时候,可以只用pc的摄像头进行测试和分析。等到有了一定开发经验之后,一定要购买一些设备,上实际环境测试,这才是比较好的做法。
神机妙算
YOLOv8优化:注意力系列篇 |基于标准化的注意力模块NAM,效果秒杀CBAM、SE
🚀🚀🚀本文改进:NAM注意力,引入到YOLOv8,多种实现方式🚀🚀🚀NAM在不同检测领域中应用广泛 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 1.NAM注意力介绍论文: https://arxiv.org/pdf/2111.12419.pdf摘要: 本文提出一种基于归一化的注意力模块(NAM),可以降低不太显著的特征的权重,这种方式在注意力模块上应用了稀疏的权重惩罚,这使得这些权重在计算上更加高效,同时能够保持同样的性能。文章在ResNet和MobileNet上和其他的注意力方式进行了对比,提出的NAM的方法可以达到更高的准确率。 NAM作为一种高效且轻量级的注意力机制。采用了CBAM的模块集成并重新设计了通道和空间注意子模块。 然后,在每个网络块的末尾嵌入一个 NAM 模块。 对于残差网络,它嵌入在残差结构的末尾。 对于通道注意力子模块,我们使用批量归一化(BN)中的缩放因子2.NAM加入YOLOv82.1加入ultralytics/nn/attention/attention.py###################### PolarizedSelfAttention #### start ###############################
import torch
import torch.nn as nn
from torch.nn import functional as F
class Channel_Att(nn.Module):
def __init__(self, channels, t=16):
super(Channel_Att, self).__init__()
self.channels = channels
self.bn2 = nn.BatchNorm2d(self.channels, affine=True)
def forward(self, x):
residual = x
x = self.bn2(x)
weight_bn = self.bn2.weight.data.abs() / torch.sum(self.bn2.weight.data.abs())
x = x.permute(0, 2, 3, 1).contiguous()
x = torch.mul(weight_bn, x)
x = x.permute(0, 3, 1, 2).contiguous()
x = torch.sigmoid(x) * residual #
return x
class NAMAttention(nn.Module):
def __init__(self, channels, shape, out_channels=None, no_spatial=True):
super(NAMAttention, self).__init__()
self.Channel_Att = Channel_Att(channels)
def forward(self, x):
x_out1 = self.Channel_Att(x)
return x_out1
###################### PolarizedSelfAttention #### end ############################### 2.2 修改tasks.py首先NAMAttention进行注册from ultralytics.nn.attention.attention import *
函数def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)进行修改
if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,
NAMAttention):
c1, c2 = ch[f], args[0] 2.3 yaml实现2.3.1 yolov8_NAMAttention.yaml加入backbone SPPF后# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
- [-1, 1, NAMAttention, [1024]] # 10
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 10], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 22 (P5/32-large)
- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)2.3.2 yolov8_NAMAttention2.yamlneck里的连接Detect的3个C2f结合# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)
- [-1, 1, NAMAttention, [256]] # 16
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 19 (P4/16-medium)
- [-1, 1, NAMAttention, [512]] # 20
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 23 (P5/32-large)
- [-1, 1, NAMAttention, [1024]] # 24
- [[16, 20, 24], 1, Detect, [nc]] # Detect(P3, P4, P5) 2.3.3 yolov8_NAMAttention3.yaml放入neck的C2f后面# Ultralytics YOLO 🚀, GPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 1 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12
- [-1, 1, NAMAttention, [512]] # 13
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 16 (P3/8-small)
- [-1, 1, NAMAttention, [256]] # 17 (P5/32-large)
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 20 (P4/16-medium)
- [-1, 1, NAMAttention, [512]] # 21 (P5/32-large)
- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 24 (P5/32-large)
- [-1, 1, NAMAttention, [1024]] # 25 (P5/32-large)
- [[17, 21, 25], 1, Detect, [nc]] # Detect(P3, P4, P5)
神机妙算
halcon学习和实践(开篇)
大学里面开设数字图像处理课程的学校很多,选用的书籍一般就是冈萨雷斯那本《数字图像处理》。编程实践的话,一般是三种方法,一种是老师自己写一个dll库,里面包含了基本的read image、write image方法,学生专注于算法的编写就好了;一种是用python + opencv库编写算法;还有一种是matlab编写,大体就是这三种。 我们不能说这种教学是错误的,但是有点脱离生产实际,这是肯定的。有几个方面,这个与实际应用场景是严重脱离的, 1、教学使用的图片一般都是来自于公开图片库,这给人一个错觉,那就是好的图像似乎是天然获得的。但是实际上,在工业生产上为了获得一张符合要求的图片需要付出很多的努力,比如说选择好的光源,选择合适的镜头,选择匹配的传感器等等。此外,对相机的安装位置也有一定的要求。有了高质量的图片,对算法要求自然也就低很多。很多时候,大家会发现,工业生产上面花费在算法的时间上不一定很多,但是花在获取高质量图片的功夫上面需要花费很多的时间,而且很多时候这个时间都是少不了的。 2、工业生产的算力并不是无限供给的,而且对时间有一定的要求。一般教学中,都是拿PC或者笔记本直接对图像处理,用的都是最新的cpu、最新的显卡、最新的硬件。但是工业或者消费品中,用的可能是嵌入式板子,而且嵌入式板子的算力都是一定的。不管如此,就是这算力不高的开发板,对于其结果的输出还是有性能要求的。比如汽车、机器人系统,如果图像输出结果不能在一定时间内完成,那么即使后面给出了结果,也基本上没有了意义。为了加速图像处理,你可能还需要掌握dsp、fpga、gpu的处理方法,这都是cpu开发之外的必须的工作量。不光如此,你可能还需要掌握硬件知识,比如网络、dma、v4l2、neon汇编等等,这一切的一切都是为了加速算法的执行。 3、学术中,为了提高对图像的处理能力,可能会设计出各种各样的算法。而在生产中,很多时候一个系统,是需要多种传感器配合才能获得最终结果的。比如图像可能和激光雷达、3d结构光camera、毫米波雷达、超声波雷达来进行配合。只要对最终的系统有利,我们有必要选用各种传感器组合在一起,而不拘泥于摄像头本身。图像本身没有深度信息,此时除了深度学习之外,另外一个稳妥的办法,就是匹配一个深度检测传感器,距离短可以用3d结构光,距离长可以用lidar,现在这方面都已经越来越成熟了。 上面说的三点只是生产中常见的几个误区。此外,在工业当中,实际使用的软件,也不是opencv,而是halcon和vision pro。拿halcon举例,用户自己本身不需要掌握复杂的算法,通过脚本就可以实现功能的开发。在脚本完成后,可以导出为c#或者c++代码,结合dll文件,可以最终部署到自己的项目中。本身halcon也有windows版本和linux版本。只是halcon本身是商业软件,作为学习使用一般问题不大,如果是大范围的做商业部署,最好还是用opencv+定制算法+硬件优化来解决大多数问题,这样比较稳妥。
神机妙算
YOLOv8实战改进教程
1)YOLOv8在自己的数据集下验证创新点可行性;2)分享前沿开源相关技术; 3) 手把手教程,带你入门;
神机妙算
halcon学习和实践
以应用为前提深入了解halcon的原理,搭配对应的python和cpp代码,最终达到灵活运用的目的。
神机妙算
第二章:掌握机器学习中的“瑞士军刀”XGBoost,从入门到实战
作为机器学习领域中的“瑞士军刀”,XGBoost在各大数据科学竞赛中屡获佳绩。本篇博客将为大家介绍如何使用Python中的XGBoost库,从入门到实战掌握XGBoost的使用。 1 XGBoost简介 XGBoost(eXtreme Gradient Boosting)是一种集成学习算法,它可以在分类和回归问题上实现高准确度的预测。XGBoost在各大数据科学竞赛中屡获佳绩,如Kaggle等。XGBoost是一种基于决策树的算法,它使用梯度提升(Gradient Boosting)方法来训练模型。XGBoost的主要优势在于它的速度和准确度,尤其是在大规模数据集上的处理能力。 XGBoost的核心思想是将多个弱分类器组合成一个强分类器。在每次迭代中,XGBoost通过加权最小化损失函数的方法来拟合模型。与传统的梯度提升算法不同的是,XGBoost在每次迭代中加入了正则化项,以避免过拟合。同时,它还使用了分裂点查找算法和近似算法来提高模型的训练效率。 在构建树模型时,XGBoost采用了一种基于排序的策略来选择最优的分裂点。具体来说,它将数据按特征值排序,并计算每个特征值作为分裂点时的增益值。然后,它选择增益值最大的特征值作为最优的分裂点。这种方法可以大大减少搜索空间,提高训练效率。 另外,XGBoost还使用了近似算法来加速训练过程。在构建树模型时,XGBoost将数据集划分为多个块,并使用直方图算法来近似每个块的分布。这样,它就可以在每个块上快速计算增益值,从而加速模型训练。 一句话总结:XGBoost通过梯度提升算法和正则化项来构建一个性能更好的预测模型。同时,它采用了排序和近似算法来提高训练效率。这些优化措施使得XGBoost在许多实际应用中都表现出了非常优秀的性能。 2 XGBoost的算法优势 首先,XGBoost能够处理大规模的数据集。在传统的机器学习算法中,当数据集变得非常大时,模型的性能往往会急剧下降。而XGBoost通过并行处理和压缩技术,能够处理大量数据,并在处理过程中减少内存占用和计算时间。 其次,XGBoost在处理非线性数据时表现优异。在实际问题中,许多数据都是非线性的,即使传统的线性模型也需要使用复杂的函数来捕捉数据的非线性关系。XGBoost可以自适应地学习非线性关系,并在不增加过拟合的风险的情况下提高模型的准确性。 此外,XGBoost具有很好的鲁棒性。在传统的机器学习算法中,异常值和噪声会对模型的性能造成很大影响,导致模型出现过拟合或欠拟合等问题。而XGBoost使用了基于树的算法,在构建树时将异常值视为叶子节点,从而使模型对异常值更具有鲁棒性。 最后,XGBoost在训练速度和准确性之间取得了很好的平衡。在大规模数据集上训练传统机器学习算法时,往往需要花费很长时间来训练模型,并且模型的准确性也不能保证。而XGBoost可以在短时间内完成模型训练,并且通常能够获得更高的准确性。 3 安装XGBoost库 XGBOOST不包含在sklearn中,因此,在使用XGBoost库之前,需要先安装它。我们可以通过以下命令在Python环境中安装XGBoost: pip install xgboost 从其官方文档中,可以看到XGBoost算法支持各类主流语言,我们只需查看Python相关的文档即可。 这一算法支持GPU运算,Conda 应该能够检测到计算机上是否存在 GPU,如果安装遇到问题,则可以指定安装CPU或GPU版本。 # CPU only
conda install -c conda-forge py-xgboost-cpu
# Use NVIDIA GPU
conda install -c conda-forge py-xgboost-gpu 4 回归模型 接下来,我们将演示如何使用XGBoost库来构建回归模型。我们将使用波士顿房价数据集来演示XGBoost在回归问题上的表现: from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
import xgboost as xgb
# 加载波士顿房价数据集
boston = load_boston()
X_train, X_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2, random_state=42)
# 构建XGBoost回归模型
xgb_reg = xgb.XGBRegressor()
xgb_reg.fit(X_train, y_train)
# 预测测试集的结果
y_pred = xgb_reg.predict(X_test) 在上面的代码中,我们首先加载了波士顿房价数据集,并将数据集划分为训练集和测试集。然后,我们使用XGBoost库来构建回归模型,并在测试集上进行预测。 接下来,我们可以通过评估回归模型的性能来评估XGBoost的表现。我们使用R平方和均方误差(MSE)两个指标来评估模型的性能: from sklearn.metrics import r2_score, mean_squared_error
# 计算R平方和MSE
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
print('R^2: {:.2f}'.format(r2))
print('MSE: {:.2f}'.format(mse)) 我们得到的R平方值为0.92,MSE为2.43。这表明XGBoost在波士顿房价数据集上表现出色,具有高预测准确度。 5 分类模型 除了回归问题,XGBoost还可以用于解决分类问题。我们将使用著名的鸢尾花数据集来演示XGBoost在分类问题上的表现: from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import xgboost as xgb
# 加载鸢尾花数据集
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)
# 构建XGBoost分类模型
xgb_cls = xgb.XGBClassifier()
xgb_cls.fit(X_train, y_train)
# 预测测试集的结果
y_pred = xgb_cls.predict(X_test) 在上面的代码中,我们首先加载了鸢尾花数据集,并将数据集划分为训练集和测试集。然后,我们使用XGBoost库来构建分类模型,并在测试集上进行预测。 接下来,我们可以通过评估分类模型的性能来评估XGBoost的表现。我们使用精度和混淆矩阵两个指标来评估模型的性能: from sklearn.metrics import accuracy_score, confusion_matrix
# 计算精度和混淆矩阵
accuracy = accuracy_score(y_test, y_pred)
confusion_mat = confusion_matrix(y_test, y_pred)
print('Accuracy: {:.2f}'.format(accuracy))
print('Confusion matrix:\n', confusion_mat)
我们得到的精度值为0.97,混淆矩阵表明XGBoost在鸢尾花数据集上表现出色,具有高预测准确度。 6 XGBoost调参 在使用XGBoost库构建模型时,调参是非常重要的。XGBoost有许多参数可以调整,包括树的深度、学习率、正则化参数等等。我们可以使用交叉验证和网格搜索来调整参数,以获得更好的性能。 以下是一个使用网格搜索调整XGBoost参数的示例: from sklearn.model_selection import GridSearchCV
# 定义XGBoost分类器
xgb_cls = xgb.XGBClassifier()
# 定义参数范围
param_grid = {
'max_depth': [3, 4, 5],
'learning_rate': [0.1, 0.01, 0.001],
'n_estimators': [50, 100, 200],
'reg_alpha': [0, 0.1, 0.5, 1],
'reg_lambda': [0, 0.1, 0.5, 1]
}
# 执行网格搜索
grid_search = GridSearchCV(xgb_cls, param_grid=param_grid, cv=3)
grid_search.fit(X_train, y_train)
# 输出最佳参数和对应的最佳值:
print('Best parameters:', grid_search.best_params_)
print('Best score:', grid_search.best_score_)
执行上述代码后,我们可以得到最佳参数和对应的最佳得分。这里我们使用了3折交叉验证来评估模型的性能。 XGBoost是一种非常流行的机器学习算法,它在大规模数据集和各种类型的问题上都表现出色。在本文中,我们介绍了XGBoost的基本原理和常用的Python代码示例。我们还演示了如何使用XGBoost库解决回归和分类问题,并展示了如何使用交叉验证和网格搜索来调整XGBoost的参数。如果你正在寻找一种快速而强大的机器学习算法来解决自己的问题,那么XGBoost可能是一个很好的选择。
神机妙算
第五章:线性回归 梯度下降算法大全与基于Python的底层代码实现
梯度下降是一种常用的优化算法,它通过不断迭代来最小化一个损失函数。根据不同的损失函数和迭代方式,梯度下降可以被分为批量梯度下降(Batch Gradient Descent,BGD)、随机梯度下降(Stochastic Gradient Descent,SGD)、小批量梯度下降(Mini-batch Gradient Descent)、共轭梯度法(Conjugate Gradient,CG)等。1 批量梯度下降(Batch Gradient Descent,BGD)批量梯度下降(Batch Gradient Descent,BGD)是一种非常常见的梯度下降算法,它通过在每一次迭代中计算所有训练样本的梯度来更新模型参数。其具体算法参见上一篇博文:线性回归 梯度下降原理与基于Python的底层代码实现GD 的优点包括:可以保证收敛到全局最优解,特别是在凸优化问题中。可以利用矩阵运算,加速计算过程。对于比较稠密的数据集,BGD 的计算速度较快。BGD 的缺点包括:需要处理所有训练样本,计算量较大,因此不适合处理大规模数据集。可能会陷入局部最优解,特别是在非凸优化问题中。对于比较稀疏的数据集,BGD 的计算效率较低,因为大部分数据都是无关的。由于每次迭代都需要处理整个数据集,因此在处理在线学习或实时学习等实时数据流问题时,BGD 的计算效率也较低。2 随机梯度下降(Stochastic Gradient Descent,SGD)随机梯度下降(Stochastic Gradient Descent,SGD)是一种常用的梯度下降算法,它通过在每一次迭代中计算一个训练样本的梯度来更新模型参数。SGD 的优点包括:可以处理大规模、稀疏或实时数据流问题,因为每次只处理一个样本,计算效率较高。可以跳出局部最优解,因为每次更新参数的方向不一定是相同的。对于非凸优化问题,SGD 的表现可能会更好,因为它能够跳出局部最优解。SGD 的缺点包括:可能无法保证收敛到全局最优解,因为更新方向是随机的。在处理比较稠密的数据集时,SGD 的计算速度可能较慢,因为需要频繁读取数据。可能会出现震荡或抖动的情况,导致收敛速度较慢。随机梯度下降算法适合处理大规模、稀疏或实时数据流问题,并且能够跳出局部最优解。但是,对于小规模、稠密或需要保证全局最优解的问题,SGD 的表现可能会不如批量梯度下降算法。同时,SGD 的收敛速度可能会受到震荡或抖动的影响,需要进行一些额外的优化或调整。3 小批量梯度下降(Mini-batch Gradient Descent, MGD)小批量梯度下降(Mini-batch Gradient Descent,MBGD)是一种介于批量梯度下降(Batch Gradient Descent,BGD)和随机梯度下降(Stochastic Gradient Descent,SGD)之间的梯度下降算法,它通过在每一次迭代中计算一小部分训练样本的梯度来更新模型参数。MBGD 的优点包括:可以利用矩阵运算,加速计算过程。对于比较稠密的数据集,MBGD 的计算速度较快。对于比较稀疏的数据集,MBGD 的计算效率也比较高。可以保证收敛到全局最优解,特别是在凸优化问题中。可以跳出局部最优解,因为每次更新参数的方向不一定是相同的。MBGD 的缺点包括:需要手动设置小批量大小,如果选择不当,可能会影响收敛速度和精度。对于大规模、稀疏或实时数据流问题,MBGD 的计算效率可能不如 SGD,但比 BGD 要好。小批量梯度下降算法是一种折中的梯度下降算法,可以在一定程度上平衡计算效率和收敛速度,适用于大部分深度学习模型的训练。但是,需要根据具体情况来选择小批量大小,以获得最好的效果。4 共轭梯度法(Conjugate Gradient,CG)共轭梯度法(Conjugate Gradient,CG)是一种针对特殊的矩阵结构进行求解的迭代方法,它可以快速收敛到全局最优解。CG 方法是一种迭代算法,每次更新的方向不同于梯度方向,但会沿着前一次更新方向和当前梯度方向的线性组合方向进行更新。CG 算法的迭代过程可以描述为以下步骤:随机初始化模型参数。计算梯度,并将其作为初始搜索方向。沿着搜索方向更新模型参数。计算新的梯度,并计算一个新的搜索方向,使得该方向与前一次搜索方向共轭。重复步骤 3-4,直到达到预定的迭代次数或误差阈值。CG 算法的优点包括:可以快速收敛到全局最优解,特别是对于对称、正定的矩阵结构而言。不需要存储所有历史梯度,可以节省内存空间。在更新模型参数的方向上,CG 方法不需要进行线搜索,因此不需要设置学习率等参数。CG 算法的缺点包括:只适用于特定类型的矩阵结构,特别是对称、正定的矩阵结构而言。对于非凸优化问题,CG 的表现可能会不如其他梯度下降算法。由于需要额外的内存来存储一些临时变量,因此在处理大规模问题时可能会受到限制。共轭梯度法适用于对称、正定的矩阵结构,可以快速收敛到全局最优解,并且不需要进行线搜索。但是,对于非凸优化问题和大规模问题,CG 的表现可能会受到一些限制。5 不同梯度方法的底层代码实例5.1 构造数据集此处我们假定数据集仅x一个变量,x与y的关系为y = 8 x y=8xy=8x。下面将构造100个数据,x的取值范围为range(0, 10, 0.1)。EXAMPLE_NUM = 100
BATCH_SIZE = 10
TRAIN_STEP = 150
LEARNING_RATE = 0.0001
X_INPUT = np.arange(EXAMPLE_NUM) * 0.1
Y_OUTPUT_CORRECT = 8 * X_INPUT + np.random.uniform(low=-10, high=10)
def train_func(X, K):
result = K * X
return result此处EXAMPLE_NUM为数据个数;BATCH_SIZE为小批量梯度下降每次使用的数据个数;TRAIN_STEP为迭代次数;X_INPUT为构造的x取值范围;Y_OUTPUT_CORRECT为对应的y真实值,这里根据xy的映射关系,在数据集上加入了(-10,10)的噪音。同时构造了train_func,用于后面梯度下降寻找最佳k值的使用。5.2 BGD回归k_BGD = 0.0
k_BGD_RECORD = [0]
for step in range(TRAIN_STEP):
SUM_BGD = 0
for index in range(len(X_INPUT)):
SUM_BGD += (train_func(X_INPUT[index], k_BGD) - Y_OUTPUT_CORRECT[index]) * X_INPUT[index]
k_BGD -= LEARNING_RATE * SUM_BGD
k_BGD_RECORD.append(k_BGD) k_BGD为给定的初始k值,k_BGD_RECORD用于记录梯度下降过程中K值的变化。第一个循环为在150次训练中的循环,第二个循环为依次计算每一个数据的梯度,并将所有计算结果求和。这里SUM_BGD为损失函数的导数。损失函数为:对损失函数求导后得:在代码中没有写出 ,是因为其本身也是一个常数,可以整合到学习速率之中。(因此相比于随机梯度下降,批量梯度下降的学习速率可以小一些,否则会学习过快)5.3 SGD回归k_SGD = 0.0
k_SGD_ECORD = [0]
for step in range(TRAIN_STEP*10):
index = np.random.randint(len(X_INPUT))
SUM_SGD = (train_func(X_INPUT[index], k_SGD) - Y_OUTPUT_CORRECT[index]) * X_INPUT[index]
k_SGD -= LEARNING_RATE * SUM_SGD
if step%10==0:
k_SGD_RECORD.append(k_SGD)SGD就只有一个循环了,因为SGD每次只使用一个数据,同时考虑到训练速度,对其训练周期进行了10倍扩增。每计算一个数据的梯度之后,都会对k进行更新。由于k的更新较慢,因此我们采取每隔10次才记录一次k的变化值。5.4 MGD回归k_MBGD = 0.0
k_MBGD_RECORD = [0]
for step in range(TRAIN_STEP):
SUM_MBGD = 0
index_start = np.random.randint(len(X_INPUT) - BATCH_SIZE)
for index in np.arange(index_start, index_start+BATCH_SIZE):
SUM_MBGD += (train_func(X_INPUT[index], k_MBGD) - Y_OUTPUT_CORRECT[index]) * X_INPUT[index]
k_MBGD -= LEARNING_RATE * SUM_MBGD
k_MBGD_RECORD.append(k_MBGD)MGD与BGD的代码很类似,只是每个step的数据只有BATCH_SIZE个。需要注意在随机选择数据起点时,其范围是0至len(X_INPUT) - BATCH_SIZE,以免数据的选择范围超出数据量。5.4 不同方法的对比绘图plt.plot(np.arange(TRAIN_STEP+1), np.array(k_BGD_RECORD), label='BGD')
plt.plot(np.arange(TRAIN_STEP+1), k_SGD_RECORD, label='SGD')
plt.plot(np.arange(TRAIN_STEP+1), k_MBGD_RECORD, label='MBGD')
plt.legend()
plt.ylabel('K')
plt.xlabel('step')
plt.show()可以看到BGD的训练效果最快,这是因为BGD的数据量比另外两种多了10倍。通常情况下,BGD的曲线会更加平滑,另外两种方法会有偶尔的偏离正确值的情况。但BGD无法避开局部最优,由于本函数不存在局部最优,因此三种效果的拟合方法都还不错。
神机妙算
第四章:逻辑回归 算法推导与基于Python的实现详解
1 逻辑回归概述逻辑回归(Logistic Regression)是一种用于分类问题的统计学习方法。它基于线性回归的原理,通过将线性函数的输出值映射到[0,1]区间上的概率值,从而进行分类。逻辑回归的输入是一组特征变量,它通过计算每个特征与对应系数的乘积,加上截距项得到线性函数,然后将该函数的输出值经过sigmoid函数的映射,得到概率值。逻辑回归常用于二分类问题,即将样本分为两类,如判断一封邮件是否为垃圾邮件。逻辑回归还可以扩展到多分类问题,如将样本分为三类或更多类别。逻辑回归具有简单、高效、易于理解等优点,在实际应用中被广泛使用,如金融风控、医学诊断、推荐系统等领域。2 逻辑回归公式推导与求解2.1 公式推导逻辑回归的公式大家可能很熟悉,但并不知道推导过程,事实上这一推导过程也十分简单。给定输入特征 x \mathbf{x}x,逻辑回归模型的输出 y yy 可以表示为:其中,σ ( z ) 表示 sigmoid 函数,定义为:。这一函数在之后的深度学习中也会经常用到。至于什么使用sigmoid函数,原因也很简单,很多教材都把这个重要的思考环节忽略了,博主在此进行补充。我们希望找到一个函数的值域在[0,1]的函数,但是这种函数并不容易找到,线性回归使用的公式 的值域是(-∞,+∞)。因此,我们引入了odds(几率)的概念。odds的取值为(0,+∞),而对于log函数,其定义域刚好为(0,+∞),值域为(-∞,+∞)。因此,我们便可以构造一个函数对P进行求解,即得到了逻辑回归的基本形式也就是我们所常说的sigmoid函数。2.2公式求解为了方便推导,我们假设训练数据集包含 m mm 个样本,每个样本有 n nn 个特征,即 ,标签为 。为了构建模型,我们需要使用训练数据集求解模型参数 w 。我们使用最大似然估计来求解模型参数。最大似然估计的目标是找到一组模型参数 w,使得训练数据集出现的概率最大。设训练数据集中的第 i 个样本的输入特征为,输出为 ,其概率表示为:训练数据集的概率可以表示为:对数似然函数为:我们的目标是最大化对数似然函数 L ( w )。使用梯度上升算法来求解最优参数 w 。对 L ( w ) 求导,得到:使用梯度上升算法,每次更新 w 的值为:其中,α 是学习率。3 基于Python的实现3.1可接收参数在Python中,使用Scikit-learn库中的LogisticRegression类可以创建逻辑回归模型。下面是LogisticRegression类的主要参数和方法:参数:penalty: 惩罚项,可以是‘l1’、‘l2’、‘elasticnet’、‘none’中的一种,默认为‘l2’。C: 正则化系数,用于控制模型的复杂度,C值越小,模型越简单,默认为1.0。solver: 用于优化问题的算法,可以是‘newton-cg’、‘lbfgs’、‘liblinear’、‘sag’、‘saga’中的一种,默认为‘lbfgs’。max_iter: 最大迭代次数,用于控制优化算法的迭代次数,默认为1003.2 完整代码示例我们使用sklearn自带的威斯康辛州乳腺癌数据集,进行模型的训练和预测。首先导入sklearn等必要的包与数据:import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import matplotlib as mpl
## 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False
# 加载数据集
data = load_breast_cancer()
# 转换为DataFrame
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = pd.Series(data.target)此处skearn自带的数据已经是清洗后的版本,如果使用的是原始威斯康辛州乳腺癌数据集或者其他个人数据集,需要对数据进行查看、清洗与特征初筛。比如特征集可能包含患者的身份ID等无用信息,将此类信息直接删除即可。同时可以使用常用的函数查看数据集状态,比如# 检测非数据类型与缺失值
print(df.info())
# 检查异常值
print(df.describe())这里官方的数据运行结果如下,可以看到已经不需要做什么修改了。其输出如下:如果Type中出现object,通常意味着这一类的某一行存在非数值类型,此时可以使用df['A'] = pd.to_numeric(df['A'], errors='coerce').astype(float)这段函数可以将df的A列转为float类型,并将不能转换的数值变为空值。之后与其他缺失值共同使用dropna删除即可。2. 模型建立与拟合# 分割数据集
X = df.drop('target', axis=1)
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)
# 创建逻辑回归模型
clf = LogisticRegression(max_iter=100)
# 拟合模型
clf.fit(X_train, y_train)建立模型时,通常不用修改超参数,也可根据数据集的实际特点或拟合后的一些警告(比如函数最终没有收敛)进行超参数的调整。3. 模型预测与绘图# 预测
y_pred = clf.predict(X_test)
# 评估
accuracy = clf.score(X_test, y_test)
print("预测结果:", y_pred)
print("准确率:", accuracy)
plt.plot(range(len(X_test)), y_test, 'ro', markersize=4, zorder=3, label=u'真实值')
plt.plot(range(len(X_test)), y_pred, 'go', markersize=10, zorder=2, label=u'预测值')
plt.legend()
plt.show()从图片上可以看出,红色圈与绿色圈同时出现的点为预测正确的数据,二者单独出现的点位为预测错误的数据。此处对预测结果的判断,是基于概率大于0.5和小于0.5来分割的。如果我们想达到当大于0.8的概率为0才视为0时(降低漏诊概率),可以使用下面的方法。4. 自定义阈值print(clf.predict_proba(X_test)[:,0]>0.8)clf.predict_proba(X_test)用于输出不同类别的概率,其输出型输入下:如果想要获取分类为0的可能性大于0.8的数据,提取粗该列的数值加以判断即可。
神机妙算
12356445
神机妙算
第一章:Stacking:解决机器学习进行多模型组合的实用工具
在机器学习领域,算法的选择和参数的调整一直是让人头痛的难题。虽然有很多算法可以使用,但没有一种算法是万能的。随着技术的不断发展,出现了一些新的技术可以在算法选择和调整参数方面提供一些帮助。其中最流行的技术之一是Stacking。Stacking是一种用于增强机器学习模型性能的技术。该技术通过结合不同算法的预测结果来生成最终的预测结果。这种方法能够帮助解决许多机器学习问题,特别是当单一算法不足以解决问题时。1 Stacking 原理在介绍如何使用代码实现 Stacking 之前,我们需要先了解一下 Stacking 的原理。Stacking 通常由两个步骤组成:第一步是使用多个基础模型来生成预测结果,第二步是使用另一个模型来整合这些预测结果,并生成最终的预测结果。第一步:生成预测结果在第一步中,我们使用多个基础模型来生成预测结果。对于每个基础模型,我们将训练数据拆分成两部分:一部分用于训练模型,另一部分用于生成预测结果。我们可以使用不同的模型,如线性回归、决策树、随机森林、支持向量机、神经网络等。每个模型生成一个预测结果。第二步:整合预测结果在第二步中,我们使用另一个模型来整合这些预测结果,并生成最终的预测结果。我们可以使用线性回归、逻辑回归、决策树、随机森林、支持向量机、神经网络等算法来完成这一步。需要注意的是,第二步中的模型必须使用第一步中的预测结果作为输入。这样可以保证整个 Stacking 过程的连贯性。2 使用 Python 实现 Stacking现在我们已经了解了 Stacking 的原理,接下来我们将介绍如何使用 Python 实现 Stacking。我们将使用一个简单的例子来说明如何使用 Python 实现 Stacking。假设我们有一个数据集,其中包含 5 个特征和 1 个目标变量。我们将使用随机森林、支持向量机和神经网络作为基础模型,并使用线性回归作为元模型来整合预测结果第一步:生成预测结果我们首先需要将数据集拆分成训练集和测试集。训练集用于训练基础模型,测试集用于生成预测结果。from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
data = load_boston()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)接下来,我们定义 3 个基础模型:随机森林、支持向量机和神经网络,并训练它们。from sklearn.ensemble import RandomForestRegressor
from sklearn.svm import SVR
from sklearn.neural_network import MLPRegressor
rf = RandomForestRegressor(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
svm = SVR()
svm.fit(X_train, y_train)
nn = MLPRegressor(hidden_layer_sizes=(100, 50), activation='relu', solver='adam', random_state=42)
nn.fit(X_train, y_train)对于每个基础模型,我们使用测试集生成预测结果。rf_pred = rf.predict(X_test)
svm_pred = svm.predict(X_test)
nn_pred = nn.predict(X_test)第二步:整合预测结果在第二步中,我们使用线性回归作为元模型来整合预测结果。需要注意的是,元模型必须使用第一步中的预测结果作为输入。from sklearn.linear_model import LinearRegression
X_pred = np.column_stack((rf_pred, svm_pred, nn_pred))
meta_model = LinearRegression()
meta_model.fit(X_pred, y_test)现在我们已经训练好了 Stacking 模型。我们可以使用训练好的模型来生成预测结果。rf_pred_train = rf.predict(X_train)
svm_pred_train = svm.predict(X_train)
nn_pred_train = nn.predict(X_train)
X_pred_train = np.column_stack((rf_pred_train, svm_pred_train, nn_pred_train))
y_pred_train = meta_model.predict(X_pred_train)
X_pred_test = np.column_stack((rf_pred, svm_pred, nn_pred))
y_pred_test = meta_model.predict(X_pred_test)现在我们已经生成了训练集和测试集的预测结果。我们可以使用这些预测结果来评估 Stacking 模型的性能。from sklearn.metrics import mean_squared_error
print('Training MSE:', mean_squared_error(y_train, y_pred_train))
print('Test MSE:', mean_squared_error(y_test, y_pred_test))借助 sklearn 实现 stacking目前新版的 sklearn 中已经内置了 StackingClassifier 方法,大家可以直接调包使用。from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import StackingClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# 生成一个分类数据集
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0, random_state=42)
# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义基本估计器
estimators = [('dt', DecisionTreeClassifier()), ('knn', KNeighborsClassifier()), ('svc', SVC())]
# 定义元估计器
clf = RandomForestClassifier(n_estimators=10, random_state=42)
# 定义Stacking分类器
stacking_clf = StackingClassifier(estimators=estimators, final_estimator=clf)
# 训练Stacking分类器
stacking_clf.fit(X_train, y_train)
# 评估Stacking分类器性能
score = stacking_clf.score(X_test, y_test)
print("Stacking分类器准确率:", score)3 各领域内的一些实际应用Stacking 已经被广泛应用于各种领域,如金融、医疗、推荐系统等。在这些领域,Stacking 已经成为了一个强有力的工具,能够提高预测准确性和稳定性。例如,在金融领域中,Stacking 已经被广泛应用于股票价格预测。股票价格预测是一个非常复杂的问题,需要考虑很多因素,如经济指标、政策变化、公司业绩等。利用 Stacking,我们可以将多个基学习器的预测结果组合起来,以提高预测准确性和泛化能力。在医疗领域中,Stacking 已经被用于疾病预测和诊断。例如,使用 Stacking 算法可以将多个医学测试的结果组合起来,以提高疾病预测的准确性。此外,Stacking 还可以帮助医生诊断疾病,比如通过将多个医学图像的结果组合起来,以帮助医生做出更准确的诊断。在推荐系统中,Stacking 已经被用于预测用户的兴趣和行为。推荐系统的主要目标是将用户与他们可能感兴趣的物品联系起来。利用 Stacking,我们可以将多个基学习器的预测结果组合起来,以提高推荐的准确性和个性化。
神机妙算
第三章:Scikit-learn中的Pipeline:让机器学习流程更加简单、高效、可靠
Scikit-learn是一个非常流行的机器学习库,提供了各种各样的算法、工具和API,让用户可以轻松地构建和调整机器学习模型。其中一个非常有用的工具是Pipeline,它可以将多个数据预处理步骤和机器学习模型组合在一起,构建起整个机器学习流程。在这篇博客中,我们将介绍Scikit-learn中的Pipeline,包括Pipeline的基本概念、使用方法和实际案例。这篇博客将将解如何使用Pipeline来构建高效且可靠的机器学习流程,使你的机器学习任务更加简单、高效和可靠。1 什么是PipelinePipeline是Scikit-learn中的一个类,它允许用户将多个数据预处理步骤和机器学习模型组合成一个整体。具体而言,Pipeline将多个估算器对象串联在一起,其中估算器可以是数据预处理步骤(如缺失值填充、特征缩放、特征选择等)或机器学习模型(如线性回归、决策树、支持向量机等)。Pipeline对象可以像普通的估算器一样进行训练、预测和评估,并且可以与GridSearchCV等工具一起使用,对估算器参数进行调优。使用Pipeline的好处是显而易见的:它使机器学习流程更加简单、高效和可靠。通过将多个步骤串联在一起,Pipeline可以避免许多常见的错误,例如将测试集数据泄露到训练集中,或者忘记对所有特征进行相同的预处理。Pipeline还可以减少代码量,并使代码更易于维护和修改。此外,使用Pipeline可以使参数搜索空间更小,从而加快模型调整的速度。2 Pipeline的基本用法2.1 数据准备工作在使用Pipeline之前,你需要准备好数据集。将数据集分成训练集和测试集,并将它们分别用于训练和评估Pipeline对象。例如,假设你正在处理一个二元分类问题,数据集包含100个样本,每个样本有10个特征和一个二元标签。可以使用Scikit-learn的train_test_split函数将数据集分成训练集和测试集:from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
X, y = make_classification(n_samples=100, n_features=10, n_classes=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)2.2 定义Pipeline对象接下来,需要定义Pipeline对象。定义Pipeline对象的方法是创建一个元组列表,其中每个元组表示一个步骤,格式为(步骤名称, 估算器对象)。可以使用make_pipeline函数来创建一个Pipeline对象,它会自动为每个步骤分配一个唯一的名称。例如,假设想要将数据进行特征缩放,并使用支持向量机模型进行分类。可以定义一个Pipeline对象,其中包含两个步骤:from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
pipe = make_pipeline(
StandardScaler(),
SVC()
)在上面的代码中,第一个步骤是使用StandardScaler进行特征缩放,第二个步骤是使用SVC进行分类。2.3 训练Pipeline对象一旦定义了Pipeline对象,就可以将其视为一个普通的估算器对象,对其进行训练和调整。训练Pipeline对象非常简单,只需要调用它的fit方法并将训练数据集作为参数传入即可。pipe.fit(X_train, y_train)在训练过程中,Pipeline对象将按照定义的顺序依次执行每个步骤。例如,在上面的示例中,Pipeline对象将首先使用StandardScaler对特征进行缩放,然后使用SVC进行分类。2.4 使用Pipeline对象进行预测和评估训练完成后,可以使用Pipeline对象进行预测和评估。预测过程非常简单,只需要调用Pipeline对象的predict方法并将测试数据集作为参数传入即可。y_pred = pipe.predict(X_test)评估过程也非常简单,只需要调用Pipeline对象的score方法并将测试数据集和相应的标签作为参数传入即可。score = pipe.score(X_test, y_test)3 Pipeline的高级用法除了上面介绍的基本用法之外,Pipeline还具有许多高级用法,可以帮助我们更好地控制机器学习流水线的行为。3.1 GridSearchCV与PipelineGridSearchCV是一个可以自动搜索最佳参数组合的工具,可以与Pipeline结合使用。GridSearchCV会尝试所有可能的参数组合,并返回最佳参数组合及其对应的评分。例如,假设我们正在处理一个分类问题,数据集包含100个样本,每个样本有10个特征和一个二元标签。可以使用Pipeline对象将数据进行特征缩放,并使用支持向量机模型进行分类,然后使用GridSearchCV搜索最佳参数组合。from sklearn.model_selection import GridSearchCV
pipe = make_pipeline(
StandardScaler(),
SVC()
)
param_grid = {
'svc__C': [0.1, 1, 10],
'svc__gamma': [0.1, 1, 10],
}
grid = GridSearchCV(pipe, param_grid=param_grid, cv=5)
grid.fit(X_train, y_train)
print("Best parameters: ", grid.best_params_)
print("Best cross-validation score: {:.2f}".format(grid.best_score_))
print("Test set score: {:.2f}".format(grid.score(X_test, y_test)))在上面的代码中,可以看到param_grid字典指定了要搜索的参数,其中’svc__C’和’svc__gamma’指定了SVC的两个超参数。在GridSearchCV中,这些参数名称必须以步骤名称和双下划线分隔符的形式指定,例如’svc__C’指定了SVC的C超参数。3.2 make_union与Pipeline有时候,我们可能希望将多个预处理步骤应用于同一数据集,然后将它们组合在一起,再将组合的结果送到估算器中进行训练。在这种情况下,可以使用make_union函数将多个预处理步骤组合在一起。例如,假设正在处理一个分类问题,数据集包含100个样本,每个样本有10个特征和一个二元标签。我们想要将数据集分成两个子集,对每个子集进行不同的预处理,然后将预处理的结果合并在一起,并使用支持向量机模型进行分类。则可以使用make_union函数来实现这一目标。from sklearn.pipeline import make_union
from sklearn.decomposition import PCA
union = make_union(
StandardScaler(),
PCA(n_components=3)
)
pipe = make_pipeline(
union,
SVC()
)
pipe.fit(X_train, y_train)
score = pipe.score(X_test, y_test)在上面的代码中,可以看到make_union函数将两个预处理步骤组合在一起,其中一个步骤是使用StandardScaler进行特征缩放,另一个步骤是使用PCA进行降维。然后,Pipeline对象将使用这个组合预处理步骤的结果,并将其作为输入传递给支持向量机模型进行分类。3.3 FeatureUnion与Pipeline除了make_union函数之外,scikit-learn还提供了FeatureUnion类,用于将多个预处理步骤组合在一起。与make_union不同的是,FeatureUnion可以处理非数字特征(例如文本或图像)。FeatureUnion的工作原理类似于Pipeline,它按顺序应用每个预处理步骤,然后将结果合并在一起。可以将FeatureUnion与其他转换器和估计器结合使用,例如CountVectorizer或TfidfVectorizer。例如,假设我们正在处理一个分类问题,数据集包含100个样本,其中有一些文本特征和一些数字特征,我们想要将它们组合起来进行分类。可以使用FeatureUnion将两个预处理步骤组合在一起。
from sklearn.pipeline import FeatureUnion
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import StandardScaler
text_union = make_pipeline(
CountVectorizer(),
TfidfTransformer()
)
numeric_union = make_pipeline(
StandardScaler(),
PCA(n_components=3)
)
combined_features = FeatureUnion([
('text_features', text_union),
('numeric_features', numeric_union)
])
pipe = make_pipeline(
combined_features,
SVC()
)
pipe.fit(X_train, y_train)
score = pipe.score(X_test, y_test)在上面的代码中,可以看到将两个预处理步骤组合在一起,其中一个步骤是处理文本特征,另一个步骤是处理数字特征。FeatureUnion按照指定的顺序依次处理每个预处理步骤,并将它们的结果组合在一起。最后,Pipeline对象将使用这些组合的特征并将其作为输入传递给支持向量机模型进行分类。在这篇文章中,我们介绍了scikit-learn中的Pipeline类,并讨论了它如何帮助您在机器学习流程中自动化预处理步骤。Pipeline类能够将多个预处理步骤组合在一起,并按照指定的顺序应用它们。此外,我们还介绍了Pipeline的高级用法,包括结合GridSearch进行网格搜索,以及使用make_union进行预处理的组合等。希望大家能够使用Pipeline和其他scikit-learn中提供的工具更加轻松地构建机器学习模型。
神机妙算
机器学习进阶大师班
学习实用工具 Stacking、深入 XGBoost 实战、Scikit-learn 中 Pipeline 流程优化、透彻掌握逻辑回归、线性回归梯度下降与正则项原理,精通最小二乘法与特征扩展的实现。全面提升机器学习技能,成为领域专家