YOLOv5的Tricks | 【Trick2】目标检测中进行多模型推理预测(Model Ensemble)

简介: 在学习yolov5代码的时候,发现experimental.py文件中有一个很亮眼的模块:Ensemble。接触过机器学习的可能了解到,机器学习的代表性算法是随机森林这种,使用多个模型来并行推理,然后归纳他们的中值或者是平均值来最为整个模型的最后预测结构,没想到的是目标检测中也可以使用,叹为观止。下面就对其进行详细介绍:

1. Ensemble的概念


集成建模是通过使用许多不同的建模算法或使用不同的训练数据集创建多个不同模型来预测结果的过程。使用集成模型的动机是减少预测的泛化误差。只要基础模型是多样且独立的,使用集成方法时模型的预测误差就会减小。该方法在做出预测时寻求群体的智慧。即使集成模型在模型中具有多个基础模型(求多个模型的平均值或最大值),它仍作为单个模型运行和执行(最终还是以一个综合模型的取整进行预测)。


详细介绍见:https://www.sciencedirect.com/topics/computer-science/ensemble-modeling


2. Ensemble的实现


yolov5实现代码如下:


# 集成算法
class Ensemble(nn.ModuleList):
    # Ensemble of models
    def __init__(self):
        super().__init__()
    def forward(self, x, augment=False, profile=False, visualize=False):
        y = []
        # 集成模型为多个模型时, 在每一层forward运算时, 都要运行多个模型在该层的结果append进y中
        for module in self:
            y.append(module(x, augment, profile, visualize)[0])
        # y = torch.stack(y).max(0)[0]  # 求多个模型结果的最大值 max ensemble
        # y = torch.stack(y).mean(0)    # 求多个模型结果的均值   mean ensemble
        y = torch.cat(y, 1)             # 将多个模型结果concat在一起, 后面做做nms等于翻了一倍的pred nms ensemble
        return y, None  # inference, train output


在yolov5中使用attempt_load模块来实现多模型的调用,代码如下:


def attempt_load(weights, map_location=None, inplace=True, fuse=True):
    from models.yolo import Detect, Model
    # Loads an ensemble of models weights=[a,b,c] or a single model weights=[a] or weights=a
    model = Ensemble()
    # weights如果是单路径, 则使用单个模型; 如果是list多路径, 则使用集成模型(多模型)
    for w in weights if isinstance(weights, list) else [weights]:
        # 这里map_location参数可以指定加载设备, 或者实现设备间的转化,eg:cuda1->cuda0 / cuda->cpu
        ckpt = torch.load(attempt_download(w), map_location=map_location)  # load
        if fuse:
            # 参数重结构化
            model.append(ckpt['ema' if ckpt.get('ema') else 'model'].float().fuse().eval())  # FP32 model
        else:
            model.append(ckpt['ema' if ckpt.get('ema') else 'model'].float().eval())  # without layer fuse
    # Compatibility updates(关于版本兼容的设置)
    for m in model.modules():
        if type(m) in [nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, Detect, Model]:
            m.inplace = inplace  # pytorch 1.7.0 compatibility
            if type(m) is Detect:
                if not isinstance(m.anchor_grid, list):  # new Detect Layer compatibility
                    delattr(m, 'anchor_grid')       # delattr(x, 'y') is equivalent to `del x.y'
                    setattr(m, 'anchor_grid', [torch.zeros(1)] * m.nl)  # setattr(x, 'y', v) is equivalent to `x.y = v'
        elif type(m) is Conv:
            m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatibility
    # 单模型设置
    if len(model) == 1:
        return model[-1]  # return model
    # 集成模型设置
    else:
        print(f'Ensemble created with {weights}\n')
        # 给每个模型一个name属性
        for k in ['names']:
            setattr(model, k, getattr(model[-1], k))    # getattr(x, 'y') is equivalent to x.y
        # 给每个模型分配stride属性
        model.stride = model[torch.argmax(torch.tensor([m.stride.max() for m in model])).int()].stride  # max stride
        return model  # return ensemble


3. Ensemble的使用


Ensemble使用方法,具体见yolov5的Tutorial:https://github.com/ultralytics/yolov5/issues/318


  • Ensemble Test
# python val.py --weights yolov5x.pt --data coco.yaml --img 640 --half    # use single 
python val.py --weights yolov5x.pt yolov5l6.pt --data coco.yaml --img 640 --half


  • Ensemble Inference
python detect.py --weights yolov5x.pt yolov5l6.pt --img 640 --source data/images


Output:


detect: weights=['yolov5x.pt', 'yolov5l6.pt'], source=data/images, imgsz=640, conf_thres=0.25, iou_thres=0.45, max_det=1000, device=, view_img=False, save_txt=False, save_conf=False, save_crop=False, nosave=False, classes=None, agnostic_nms=False, augment=False, update=False, project=runs/detect, name=exp, exist_ok=False, line_thickness=3, hide_labels=False, hide_conf=False, half=False
YOLOv5 🚀 v5.0-267-g6a3ee7c torch 1.9.0+cu102 CUDA:0 (Tesla P100-PCIE-16GB, 16280.875MB)
Fusing layers... 
Model Summary: 476 layers, 87730285 parameters, 0 gradients
Fusing layers... 
Model Summary: 501 layers, 77218620 parameters, 0 gradients
Ensemble created with ['yolov5x.pt', 'yolov5l6.pt']
image 1/2 /content/yolov5/data/images/bus.jpg: 640x512 4 persons, 1 bus, 1 tie, Done. (0.063s)
image 2/2 /content/yolov5/data/images/zidane.jpg: 384x640 3 persons, 2 ties, Done. (0.056s)
Results saved to runs/detect/exp2
Done. (0.223s)


可以看见输出的时候出打印使用了多少个模型,每个模型的层数,参数量


测试代码:


if __name__ == '__main__':
    x = torch.rand([8, 3, 640, 640])
    weights = ['../weights/yolov5s.pt', '../weights/yolov5m.pt', '../weights/yolov5l.pt']
    device = torch.device('cpu')
    # 集成模型测试
    model = attempt_load(weights, map_location=device)
    print("len(model(x)):", len(model(x)))
    print(model(x)[0].shape)
    # 单模型测试
    model = attempt_load(weights[0], map_location=device)
    print("len(model(x)):", len(model(x)))
    print(model(x)[0].shape)


输出:


Ensemble created with ['../weights/yolov5s.pt', '../weights/yolov5m.pt', '../weights/yolov5l.pt']
len(model(x)): 2
torch.Size([8, 75600, 85])
len(model(x)): 2
torch.Size([8, 25200, 85])


需要注意:


集成模块只能在推理的阶段使用(也就是测试或者验证阶段),因为这时候是调用多个已经训练好的模型权重来分别独立的对输入进行预测,然后每个训练好的模型所得到的结果取平均或者堆叠再做后续的后处理操作。


可以注意到,由于在上诉的Ensemble模块中,源码中选择了将结果拼接了在一起。所以可以看见,在对通一批图像做处理的时候,会得到多个模型预测的结果,预测框成倍的增加,使用多少个模型就会增加多少倍,后处理过程会变慢,但是精度会提高,其实也可以换成mean或者是max的方法。


目录
相关文章
|
6月前
|
并行计算 数据可视化 PyTorch
单目3D目标检测——MonoCon 模型训练 | 模型推理
本文分享 MonoCon 的模型训练、模型推理、可视化3D检测结果、以及可视化BEV效果。
166 0
|
6月前
|
数据可视化 PyTorch 算法框架/工具
单目3D目标检测——MonoDLE 模型训练 | 模型推理
本文分享 MonoDLE 的模型训练、模型推理、可视化3D检测结果。
72 0
|
6月前
|
数据可视化 计算机视觉
单目3D目标检测——SMOKE 模型推理 | 可视化结果
本文分享SMOKE的模型推理,和可视化结果。以kitti数据集为例子,对训练完的模型进行推理,并可视化3D框的结果,画到图像中。
59 0
|
2天前
|
机器学习/深度学习 存储 人工智能
【人工智能】机器学习算法综述及常见算法详解
【人工智能】机器学习算法综述及常见算法详解
|
4天前
|
机器学习/深度学习 人工智能 算法
探索机器学习中的支持向量机(SVM)算法
【5月更文挑战第6天】在数据科学和人工智能的广阔天地中,支持向量机(SVM)以其强大的分类能力与理论深度成为机器学习领域中的一个闪亮的星。本文将深入探讨SVM的核心原理、关键特性以及实际应用案例,为读者提供一个清晰的视角来理解这一高级算法,并展示如何利用SVM解决实际问题。
28 7
|
4天前
|
机器学习/深度学习 人工智能 算法
探索机器学习中的支持向量机算法
【5月更文挑战第6天】 在数据科学和人工智能领域,支持向量机(SVM)是一种强大的监督学习模型,它凭借其出色的分类能力在众多机器学习任务中占据重要地位。本文旨在深入剖析支持向量机的工作原理,探讨其在高维数据处理中的优势以及面对大规模数据集时的应对策略。通过对核技巧、软间隔以及优化问题的讨论,我们将揭示SVM如何优雅地处理线性不可分问题,并保持模型的泛化性能。
|
8天前
|
机器学习/深度学习 自然语言处理 算法
机器学习算法原理与应用:深入探索与实战
【5月更文挑战第2天】本文深入探讨机器学习算法原理,包括监督学习(如线性回归、SVM、神经网络)、非监督学习(聚类、PCA)和强化学习。通过案例展示了机器学习在图像识别(CNN)、自然语言处理(RNN/LSTM)和推荐系统(协同过滤)的应用。随着技术发展,机器学习正广泛影响各领域,但也带来隐私和算法偏见问题,需关注解决。
|
10天前
|
机器学习/深度学习 运维 算法
【Python机器学习专栏】异常检测算法在Python中的实践
【4月更文挑战第30天】本文介绍了异常检测的重要性和在不同领域的应用,如欺诈检测和网络安全。文章概述了四种常见异常检测算法:基于统计、距离、密度和模型的方法。在Python实践中,使用scikit-learn库展示了如何实现这些算法,包括正态分布拟合、K-means聚类、局部异常因子(LOF)和孤立森林(Isolation Forest)。通过计算概率密度、距离、LOF值和数据点的平均路径长度来识别异常值。
|
10天前
|
机器学习/深度学习 数据可视化 算法
【Python机器学习专栏】t-SNE算法在数据可视化中的应用
【4月更文挑战第30天】t-SNE算法是用于高维数据可视化的非线性降维技术,通过最小化Kullback-Leibler散度在低维空间保持数据点间关系。其特点包括:高维到二维/三维映射、保留局部结构、无需预定义簇数量,但计算成本高。Python中可使用`scikit-learn`的`TSNE`类实现,结合`matplotlib`进行可视化。尽管计算昂贵,t-SNE在揭示复杂数据集结构上极具价值。
|
10天前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】关联规则学习:Apriori算法详解
【4月更文挑战第30天】Apriori算法是一种用于关联规则学习的经典算法,尤其适用于购物篮分析,以发现商品间的购买关联。该算法基于支持度和置信度指标,通过迭代生成频繁项集并提取满足阈值的规则。Python中可借助mlxtend库实现Apriori,例如处理购物篮数据,设置支持度和置信度阈值,找出相关规则。

热门文章

最新文章