yolov5的持续发力|分类任务

人工智能与算法智能应用数据库管理服务

picture.image

点击下方 公众号 关注,一起进步,持续传达瓜货

picture.image

yolov5一直作为目标检测的扛把子,训练快、效果好、易部署等优点让从入门小白到行业大佬都对其膜拜不已,而yolov5不仅限于目标检测,现在已经在分类、分割等其他任务上开始发力,这篇文章介绍下yolov5框架在分类任务上的应用以及相关代码的变动。

前言

大家好,我是张大刀。

之前听说yolov5在6版本以上会添加其他的图像任务,今天打开官方github时,发现分类和分割任务已经更新到7.0版本了。今天对分类任务大概梳理一遍。

1

Yolov5-cls的变动

仔细对比yolov5的目标检测与分类的代码框架,主要的改动点在以下几个方面:

  1. 训练、测试、验证等的代码入口;

  2. 数据加载和预处理;

  3. 网络变动;

  4. loss的变动;

  5. 评价指标。

01 训练、测试、验证等的代码入口

yolov5分类任务的训练、测试以及预测的代码入口是在新建的文件夹下:

| --classify

| --train.py

| --val.py

| --pred.py

三个入口的架构整理上与目标检测保持一致,主要变动在数据集、网络部分、loss和评价指标上。

02 数据加载和预处理

数据预加载上,首先需要将数据集按照imageNet的格式保存,文件夹下面有train/test/val文件夹,同时在每个文件夹下,以标签作为文件夹存储属于该标签的图片:


              
 
 
              
 
 `|--dataset  
   |--train  
     |--dog  
       |--1.jpg  
       |--2.jpg  
       |--3.jpg  
       ....  
     |--cat  
       |--1.jpg  
       |--2.jpg  
       |--3.jpg  
       ....  
     ....  
   |--test  
     ....` 
 
 
            

通过

create_classification_dataloader 处理数据集,如果选择数据缓存在disk,会将数据先缓存成npy文件。同时在数据增强方面,除了常规的

torchvision. transforms外,也有 albumentations提供的增强。不过先较于检测中的mixup类的增强,分类的数据增强稍显单薄:


              
   

 
 
              
 
  `class ClassificationDataset(torchvision.datasets.ImageFolder):`
  `"""    YOLOv5 Classification Dataset.    Arguments        root:  Dataset path        transform:  torchvision transforms, used by default        album_transform: Albumentations transforms, used if installed    """    def __init__(self, root, augment, imgsz, cache=False):        super().__init__(root=root)        self.torch_transforms = classify_transforms(imgsz)        self.album_transforms = classify_albumentations(augment, imgsz) if augment else None        self.cache_ram = cache is True or cache == 'ram'        self.cache_disk = cache == 'disk'        self.samples = [list(x) + [Path(x[0]).with_suffix('.npy'), None] for x in self.samples]  # file, index, npy, im    def __getitem__(self, i):        f, j, fn, im = self.samples[i]  # filename, index, filename.with_suffix('.npy'), image        if self.cache_ram and im is None:            im = self.samples[i][3] = cv2.imread(f)        elif self.cache_disk:             if not fn.exists():  # load npy                np.save(fn.as_posix(), cv2.imread(f))            im = np.load(fn)        else:  # read image            im = cv2.imread(f)  # BGR        if self.album_transforms:            sample = self.album_transforms(image=cv2.cvtColor(im, cv2.COLOR_BGR2RGB))["image"]        else:            sample = self.torch_transforms(im)        return sample, j`
 
 
            

03 网络变动

网络模型上,加载同目标检测网络加载,同时如果加载了yolo的检测模型,会通过 ClassificationModel 去除后面的detect head, 换成对应类别的分类器:


              
 
   

 
 
              
 
  `class ClassificationModel(BaseModel):`
  `# YOLOv5 classification model    def __init__(self, cfg=None, model=None, nc=1000, cutoff=10):  # yaml, model, number of classes, cutoff index        super().__init__()        self._from_detection_model(model, nc, cutoff) if model is not None else self._from_yaml(cfg)    def _from_detection_model(self, model, nc=1000, cutoff=10):        # Create a YOLOv5 classification model from a YOLOv5 detection model        if isinstance(model, DetectMultiBackend):            model = model.model  # unwrap DetectMultiBackend        model.model = model.model[:cutoff]  # 获取backbone模型其中cutoff值与对应网络的yaml文件中backbone中最后一层值对应。        m = model.model[-1]  # backbone的最后一层        ch = m.conv.in_channels if hasattr(m, 'conv') else m.cv1.conv.in_channels  # ch into module        c = Classify(ch, nc)  # 在backbone后面接分类器,Classify(),分类器        c.i, c.f, c.type = m.i, m.f, 'models.common.Classify'  # index, from, type        model.model[-1] = c  # 将最后一层换成分类器        self.model = model.model        self.stride = model.stride        self.save = []        self.nc = nc    def _from_yaml(self, cfg):        # Create a YOLOv5 classification model from a *.yaml file        self.model = None`
 
 
            

04 loss

loss上采用了label_smoothing,当label_smothing=0时,为一般的CELoss,而分类任务中的focalLoss以及二分类的BCEloss 等还未加进去。


              
   

 
              
 
 `def smartCrossEntropyLoss(label\_smoothing=0.0):  
    # Returns nn.CrossEntropyLoss with label smoothing enabled for torch>=1.10.0  
    if check\_version(torch.\_\_version\_\_, '1.10.0'):  
        return nn.CrossEntropyLoss(label\_smoothing=label\_smoothing) # torch1.10后,nn.CrossEntropyLoss自支持label\_smoothing  
    if label\_smoothing > 0:  
        LOGGER.warning(f'WARNING ⚠️ label smoothing {label\_smoothing} requires torch>=1.10.0')  
    return nn.CrossEntropyLoss()` 
 
 
            

05 评价指标

分类的评价指标,使用的是acc_top1和acc_top5,而实际上针对分类的模型性能指标有AUC,MAP, F1等,期待后期能将这些补全。


              
 
  `pred, targets = torch.cat(pred), torch.cat(targets)  
    correct = (targets[:, None] == pred).float()  
    acc = torch.stack((correct[:, 0], correct.max(1).values), dim=1)  # (top1, top5) accuracy  
    top1, top5 = acc.mean(0).tolist()`
 
 
            

2

Yolov5-cls训练及建议

yolov5的分类训练按照readme上的基本上已经能满足需求。

训练:

Single-GPU

python classify/train.py --model yolov5s-cls.pt --data cifar100 --epochs 5 --img 224 --batch 128

Multi-GPU DDP

python -m torch.distributed.run --nproc_per_node 4 --master_port 1 classify/train.py --model yolov5s-cls.pt --data imagenet --epochs 5 --img 224 --device 0,1,2,3

训练后的数据会保存在runs/train-cls文件夹下面:

picture.image

验证:


              
 
  `python classify/val.py --weights yolov5m-cls.pt --data ../datasets/imagenet --img 224 # validate`
 
 
            

推理:


              
 
  `python classify/predict.py --weights yolov5s-cls.pt --data data/images/bus.jpg`
 
 
            

导出onnx 和 TensorRT:


              
 
  `python export.py --weights yolov5s-cls.pt resnet50.pt efficientnet\_b0.pt --include onnx engine --img 224`
 
 
            

建议

其在imageNet上与其他分类网络的效果如下:

picture.image

图源:https://github.com/ultralytics/yolov5/pull/8956

Yolov5x的分类模型相比较resnet101和efficientNet_b3模型虽然其acc_top1的效果高1-2个点,但EfficientNet_b3的参数量是Yolov5x的1/4倍,其在cpu上的运行速度也差不多是其1/4,这样看如果最后模型部署在GPU上,可以考虑上Yolov5,其训练速度快,便于实际项目中的快速迭代;如果部署在cpu上,则建议使用EfficientNet系列。

结语

以上为yolov5在分类任务中的应用,期待yolov5后续trick的添加,希望对大家有帮助。

参考:

[1] https://github.com/ultralytics/yolov5

           ![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/5c23f945820d4a70a9dbabdf28c3749e~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1746249221&x-signature=ReBFWmgAm6Ecgw%2FeSnmGiE%2BUD4k%3D)

最后,为了便于大家学习交流,创建了深度学习的 算法交流群 ,包括但不限于CV,nlp, 算法,开发,IT技术等。欢迎大家入群一起学习交流~(因群人数满200人,只能邀请进群,请公众号后台加我微信,拉你进群~

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
火山引擎大规模机器学习平台架构设计与应用实践
围绕数据加速、模型分布式训练框架建设、大规模异构集群调度、模型开发过程标准化等AI工程化实践,全面分享如何以开发者的极致体验为核心,进行机器学习平台的设计与实现。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论