【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统

1.研究背景与意义

项目参考AAAI Association for the Advancement of Artificial Intelligence

研究背景与意义

近年来,随着计算机视觉和深度学习的快速发展,物体检测和图像分类技术在各个领域都得到了广泛应用。其中,YOLO(You Only Look Once)是一种快速且准确的物体检测算法,而FasterNet则是一种高效的图像分类网络。然而,在实际应用中,单独使用YOLO或FasterNet往往无法满足复杂场景下的准确性和效率要求。

苹果品质分级是农业生产中的重要环节,对于果农和消费者来说都具有重要意义。传统的苹果品质分级通常依赖于人工进行,这不仅费时费力,而且容易受主观因素的影响,导致结果的不一致性。因此,开发一种自动化的苹果品质分级系统具有重要的实际意义。

本研究旨在融合FasterNet的YOLO算法,开发一种高效准确的苹果品质分级系统。通过将YOLO算法与FasterNet相结合,可以充分利用两者的优势,提高苹果品质分级的准确性和效率。具体而言,YOLO算法可以实现对苹果的快速检测和定位,而FasterNet则可以对检测到的苹果进行准确的品质分类。

本研究的意义主要体现在以下几个方面:

  1. 提高苹果品质分级的准确性:传统的人工分级容易受主观因素的影响,导致结果的不一致性。而本研究所提出的基于YOLO和FasterNet的苹果品质分级系统可以实现自动化的苹果品质分级,减少人为因素的干扰,提高分级结果的准确性。

  2. 提高苹果品质分级的效率:传统的人工分级需要大量的人力和时间,效率较低。而本研究所提出的系统可以实现对苹果的快速检测和品质分类,大大提高了分级的效率,减少了人力和时间成本。

  3. 推动农业智能化发展:随着人工智能技术的不断发展,农业智能化已经成为农业发展的重要方向。本研究所提出的苹果品质分级系统可以为果农提供一种智能化的品质分级解决方案,推动农业智能化的发展。

  4. 推动计算机视觉和深度学习的应用:本研究所提出的苹果品质分级系统是计算机视觉和深度学习在农业领域的典型应用。通过将YOLO和FasterNet相结合,可以为其他物体检测和分类问题提供借鉴和参考,推动计算机视觉和深度学习在更多领域的应用。

综上所述,本研究旨在融合FasterNet的YOLO算法,开发一种高效准确的苹果品质分级系统。该系统具有重要的实际意义,可以提高苹果品质分级的准确性和效率,推动农业智能化发展,同时也为计算机视觉和深度学习的应用提供了借鉴和参考。

2.图片演示



3.视频演示

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_哔哩哔哩_bilibili

4.数据集的采集&标注和整理

图片的收集

首先,我们需要收集所需的图片。这可以通过不同的方式来实现,例如使用现有的公开数据集APDatasets。

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第1张图片

labelImg是一个图形化的图像注释工具,支持VOC和YOLO格式。以下是使用labelImg将图片标注为VOC格式的步骤:

(1)下载并安装labelImg。
(2)打开labelImg并选择“Open Dir”来选择你的图片目录。
(3)为你的目标对象设置标签名称。
(4)在图片上绘制矩形框,选择对应的标签。
(5)保存标注信息,这将在图片目录下生成一个与图片同名的XML文件。
(6)重复此过程,直到所有的图片都标注完毕。

由于YOLO使用的是txt格式的标注,我们需要将VOC格式转换为YOLO格式。可以使用各种转换工具或脚本来实现。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第2张图片

下面是一个简单的方法是使用Python脚本,该脚本读取XML文件,然后将其转换为YOLO所需的txt格式。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import xml.etree.ElementTree as ET
import os

classes = []  # 初始化为空列表

CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))

def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)

def convert_annotation(image_id):
    in_file = open('./label_xml\%s.xml' % (image_id), encoding='UTF-8')
    out_file = open('./label_txt\%s.txt' % (image_id), 'w')  # 生成txt格式文件
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        cls = obj.find('name').text
        if cls not in classes:
            classes.append(cls)  # 如果类别不存在,添加到classes列表中
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
             float(xmlbox.find('ymax').text))
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')

xml_path = os.path.join(CURRENT_DIR, './label_xml/')

# xml list
img_xmls = os.listdir(xml_path)
for img_xml in img_xmls:
    label_name = img_xml.split('.')[0]
    print(label_name)
    convert_annotation(label_name)

print("Classes:")  # 打印最终的classes列表
print(classes)  # 打印最终的classes列表

整理数据文件夹结构

我们需要将数据集整理为以下结构:

-----data
   |-----train
   |   |-----images
   |   |-----labels
   |
   |-----valid
   |   |-----images
   |   |-----labels
   |
   |-----test
       |-----images
       |-----labels

确保以下几点:

所有的训练图片都位于data/train/images目录下,相应的标注文件位于data/train/labels目录下。
所有的验证图片都位于data/valid/images目录下,相应的标注文件位于data/valid/labels目录下。
所有的测试图片都位于data/test/images目录下,相应的标注文件位于data/test/labels目录下。
这样的结构使得数据的管理和模型的训练、验证和测试变得非常方便。

模型训练
 Epoch   gpu_mem       box       obj       cls    labels  img_size
 1/200     20.8G   0.01576   0.01955  0.007536        22      1280: 100%|██████████| 849/849 [14:42<00:00,  1.04s/it]
           Class     Images     Labels          P          R     [email protected] [email protected]:.95: 100%|██████████| 213/213 [01:14<00:00,  2.87it/s]
             all       3395      17314      0.994      0.957      0.0957      0.0843

 Epoch   gpu_mem       box       obj       cls    labels  img_size
 2/200     20.8G   0.01578   0.01923  0.007006        22      1280: 100%|██████████| 849/849 [14:44<00:00,  1.04s/it]
           Class     Images     Labels          P          R     [email protected] [email protected]:.95: 100%|██████████| 213/213 [01:12<00:00,  2.95it/s]
             all       3395      17314      0.996      0.956      0.0957      0.0845

 Epoch   gpu_mem       box       obj       cls    labels  img_size
 3/200     20.8G   0.01561    0.0191  0.006895        27      1280: 100%|██████████| 849/849 [10:56<00:00,  1.29it/s]
           Class     Images     Labels          P          R     [email protected] [email protected]:.95: 100%|███████   | 187/213 [00:52<00:00,  4.04it/s]
             all       3395      17314      0.996      0.957      0.0957      0.0845

5.核心代码讲解

5.1 DropPath.py

封装为类后的代码如下:


class DropPath(nn.Module):
    def __init__(self, drop_prob=None):
        super(DropPath, self).__init__()
        self.drop_prob = drop_prob

    def forward(self, x):
        if self.drop_prob == 0.0 or not self.training:
            return x
        keep_prob = 1 - self.drop_prob
        shape = (x.shape[0],) + (1,) * (x.ndim - 1)
        random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)
        random_tensor = torch.floor(random_tensor)  # binarize
        output = x.div(keep_prob) * random_tensor
        return output

这个类将原来的drop_path函数封装为了一个DropPath类,并将其继承自nn.Moduleforward方法实现了原来drop_path函数的功能,其中使用了PyTorch的相关函数来替代PaddlePaddle的函数。

该程序文件名为DropPath.py,主要包含了两个函数:drop_path和DropPath。

drop_path函数用于在主路径的残差块中对每个样本进行路径丢弃(随机深度)。如果drop_prob为0或者不处于训练状态,则直接返回输入x。否则,根据drop_prob生成一个保留概率keep_prob,并根据输入x的形状生成一个与x相同形状的随机张量random_tensor。然后将random_tensor进行二值化处理,并将其与x相乘后除以keep_prob得到输出output。

DropPath类继承自nn.Layer,用于封装drop_path函数。在初始化时可以指定drop_prob参数。在前向传播过程中,调用drop_path函数对输入x进行路径丢弃操作,并返回结果。

5.2 FasterNet.py


class PConv(nn.Layer):
    def __init__(self, dim, kernel_size=3, n_div=4):
        super().__init__()

        self.dim_conv = dim // n_div
        self.dim_untouched = dim - self.dim_conv

        self.conv = nn.Conv2D(self.dim_conv, self.dim_conv, kernel_size, padding=(kernel_size - 1) // 2,
                              bias_attr=False)

    def forward(self, x):
        x1, x2 = paddle.split(x, [self.dim_conv, self.dim_untouched], axis=1)
        x1 = self.conv(x1)
        x = paddle.concat([x1, x2], axis=1)

        return x

class FasterNetBlock(nn.Layer):
    def __init__(self, dim, expand_ratio=2, act_layer=nn.ReLU, drop_path_rate=0.0):
        super().__init__()

        self.pconv = PConv(dim)

        self.conv1 = nn.Conv2D(dim, dim * expand_ratio, 1, bias_attr=False)

        self.bn = nn.BatchNorm2D(dim * expand_ratio)
        self.act_layer = act_layer()

        self.conv2 = nn.Conv2D(dim * expand_ratio, dim, 1, bias_attr=False)

        self.drop_path = DropPath(drop_path_rate) if drop_path_rate > 0.0 else nn.Identity()

    def forward(self, x):
        residual = x

        x = self.pconv(x)
        x = self.conv1(x)
        x = self.bn(x)
        x = self.act_layer(x)
        x = self.conv2(x)

        x = residual + self.drop_path(x)
        return x


class FasterNet(nn.Layer):
    def __init__(self, in_channel=3, embed_dim=40, act_layer=nn.ReLU, num_classes=1000, depths=[1, 2, 8, 2],
                 drop_path=0.0):
        super().__init__()

        self.stem = nn.Sequential(
            nn.Conv2D(in_channel, embed_dim, 4, stride=4, bias_attr=False),
            nn.BatchNorm2D(embed_dim),
            act_layer()
        )

        drop_path_list = [x.item() for x in paddle.linspace(0, drop_path, sum(depths))]

        self.feature = []
        embed_dim = embed_dim
        for idx, depth in enumerate(depths):

            self.feature.append(nn.Sequential(
                *[FasterNetBlock(embed_dim, act_layer=act_layer, drop_path_rate=drop_path_list[sum(depths[:idx]) + i])
                  for i in range(depth)]
            ))

            if idx < len(depths) - 1:
                self.feature.append(nn.Sequential(
                    nn.Conv2D(embed_dim, embed_dim * 2, 2, stride=2, bias_attr=False),
                    nn.BatchNorm2D(embed_dim * 2),
                    act_layer()
                ))

                embed_dim = embed_dim * 2

        self.feature = nn.Sequential(*self.feature)

        self.avg_pool = nn.AdaptiveAvgPool2D(1)

        self.conv1 = nn.Conv2D(embed_dim, 1280, 1, bias_attr=False)
        self.act_layer = act_layer()
        self.fc = nn.Linear(1280, num_classes)

    def forward(self, x):
        x = self.stem(x)
        x = self.feature(x)

        x = self.avg_pool(x)
        x = self.conv1(x)
        x = self.act_layer(x)
        x = self.fc(x.flatten(1))

        return x

该程序文件是一个用于构建FasterNet模型的Python代码。它包含了以下几个类和函数:

  1. PConv类:一个用于局部卷积的类,将输入的特征图分为两部分,其中一部分经过卷积操作后再与另一部分拼接在一起。

  2. FasterNetBlock类:FasterNet的基本模块,包含了PConv、卷积、批归一化、激活函数等操作。

  3. FasterNet类:FasterNet的主体结构,包含了多个FasterNetBlock模块,以及卷积、池化、全连接等操作。

  4. fasternet_t0、fasternet_t1、fasternet_t2、fasternet_s、fasternet_m、fasternet_l函数:分别返回不同配置的FasterNet模型。

该程序文件可以用于构建不同配置的FasterNet模型,并用于图像分类任务。

5.3 train.py
class YOLOv5Trainer:
    def __init__(self, hyp, opt, device, callbacks):
        self.hyp = hyp
        self.opt = opt
        self.device = device
        self.callbacks = callbacks

    def train(self):
        # code for training
        pass

    def load_model(self):
        # code for loading the model
        pass

    def save_model(self):
        # code for saving the model
        pass

    def create_optimizer(self):
        # code for creating the optimizer
        pass

    def create_scheduler(self):
        # code for creating the scheduler
        pass

    def create_dataloader(self):
        # code for creating the dataloader
        pass

    def compute_loss(self):
        # code for computing the loss
        pass

    def evaluate(self):
        # code for evaluating the model
        pass

该程序文件是用于训练一个YOLOv5模型的。程序中包含了训练模型所需的各种功能和工具函数。具体的使用方法和参数可以通过命令行进行设置。程序会自动下载模型和数据集,并根据设置进行训练。训练过程中会保存模型权重和日志信息。程序还支持多GPU训练和断点续训功能。

5.4 ui.py


def load_model(
        weights='./best.pt',  # model.pt path(s)
        data=ROOT / 'data/coco128.yaml',  # dataset.yaml path
        device='',  # cuda device, i.e. 0 or 0,1,2,3 or cpu
        half=False,  # use FP16 half-precision inference
        dnn=False,  # use OpenCV DNN for ONNX inference

):
    # Load model
    device = select_device(device)
    model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data)
    stride, names, pt, jit, onnx, engine = model.stride, model.names, model.pt, model.jit, model.onnx, model.engine

    # Half
    half &= (pt or jit or onnx or engine) and device.type != 'cpu'  # FP16 supported on limited backends with CUDA
    if pt or jit:
        model.model.half() if half else model.model.float()
    return model, stride, names, pt, jit, onnx, engine


def run(model, img, stride, pt,
        imgsz=(640, 640),  # inference size (height, width)
        conf_thres=0.15,  # confidence threshold
        iou_thres=0.15,  # NMS IOU threshold
        max_det=1000,  # maximum detections per image
        device='',  # cuda device, i.e. 0 or 0,1,2,3 or cpu
        classes=None,  # filter by class: --class 0, or --class 0 2 3
        agnostic_nms=False,  # class-agnostic NMS
        augment=False,  # augmented inference
        half=False,  # use FP16 half-precision inference
        ):

    cal_detect = []

    device = select_device(device)
    names = model.module.names if hasattr(model, 'module') else model.names  # get class names

    # Set Dataloader
    im = letterbox(img, imgsz, stride, pt)[0]

    # Convert
    im = im.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB
    im = np.ascontiguousarray(im)

    im = torch.from_numpy(im).to(device)
    im = im.half() if half else im.float()  # uint8 to fp16/32
    im /= 255  # 0 - 255 to 0.0 - 1.0
    if len(im.shape) == 3:
        im = im[None]  # expand for batch dim

    pred = model(im, augment=augment)

    pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
    # Process detections
    for i, det in enumerate(pred):  # detections per image
        if len(det):
            # Rescale boxes from img_size to im0 size
            det[:, :4] = scale_coords(im.shape[2:], det[:, :4], img.shape).round()

            # Write results

            for *xyxy, conf, cls in reversed(det):
                c = int(cls)  # integer class
                label = f'{names[c]}'
                lbl = names[int(cls)]
                #print(lbl)
                #if lbl not in [' Chef clothes',' clothes']:
                    #continue
                cal_detect.append([label, xyxy,str(float(conf))[:5]])
    return cal_detect

......

这个程序文件是一个基于YOLOv5的苹果品质分级系统的用户界面程序。程序中使用了PyQt5库来创建一个图形用户界面。主要功能包括选择文件、预处理和开始检测。

程序中还导入了其他一些库,包括argparse、platform、shutil、time、numpy、os、sys、pathlib、cv2、torch等。

程序中定义了一些函数,包括load_model函数用于加载模型,run函数用于运行模型进行检测,det_yolov5v6函数用于对图像进行检测并显示结果。

程序中还定义了一个Thread_1类,继承自QThread类,用于创建一个线程来运行检测函数。

程序中还定义了一个Ui_MainWindow类,用于创建主窗口界面,并设置了一些控件,包括标签、按钮和文本浏览器。

主窗口界面中的按钮分别对应选择文件、预处理和开始检测功能。

整个程序的主要功能是加载模型并使用模型对选择的图像进行苹果品质分级检测,并将检测结果显示在界面上。

5.5 yolov5-FasterBlock.py


class Partial_conv3(nn.Module):
    def __init__(self, dim, n_div, forward):
        super().__init__()
        self.dim_conv3 = dim // n_div
        self.dim_untouched = dim - self.dim_conv3
        self.partial_conv3 = nn.Conv2d(self.dim_conv3, self.dim_conv3, 3, 1, 1, bias=False)

        if forward == 'slicing':
            self.forward = self.forward_slicing
        elif forward == 'split_cat':
            self.forward = self.forward_split_cat
        else:
            raise NotImplementedError

    def forward_slicing(self, x):
        # only for inference
        x = x.clone()   # !!! Keep the original input intact for the residual connection later
        x[:, :self.dim_conv3, :, :] = self.partial_conv3(x[:, :self.dim_conv3, :, :])
        return x

    def forward_split_cat(self, x):
        # for training/inference
        x1, x2 = torch.split(x, [self.dim_conv3, self.dim_untouched], dim=1)
        x1 = self.partial_conv3(x1)
        x = torch.cat((x1, x2), 1)
        return x

class Faster_Block(nn.Module):
    def __init__(self,
                 inc,
                 dim,
                 n_div=4,
                 mlp_ratio=2,
                 drop_path=0.1,
                 layer_scale_init_value=0.0,
                 pconv_fw_type='split_cat'
                 ):
        super().__init__()
        self.dim = dim
        self.mlp_ratio = mlp_ratio
        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
        self.n_div = n_div

        mlp_hidden_dim = int(dim * mlp_ratio)

        mlp_layer = [
            nn.Conv2d(dim, mlp_hidden_dim, 1),
            nn.Conv2d(mlp_hidden_dim, dim, 1, bias=False)
        ]

        self.mlp = nn.Sequential(*mlp_layer)

        self.spatial_mixing = Partial_conv3(
            dim,
            n_div,
            pconv_fw_type
        )
        
        self.adjust_channel = None
        if inc != dim:
            self.adjust_channel = nn.Conv2d(inc, dim, 1)

        if layer_scale_init_value > 0:
            self.layer_scale = nn.Parameter(layer_scale_init_value * torch.ones((dim)), requires_grad=True)
            self.forward = self.forward_layer_scale
        else:
            self.forward = self.forward

    def forward(self, x):
        if self.adjust_channel is not None:
            x = self.adjust_channel(x)
        shortcut = x
        x = self.spatial_mixing(x)
        x = shortcut + self.drop_path(self.mlp(x))
        return x

    def forward_layer_scale(self, x):
        shortcut = x
        x = self.spatial_mixing(x)
        x = shortcut + self.drop_path(
            self.layer_scale.unsqueeze(-1).unsqueeze(-1) * self.mlp(x))
        return x

class C3_Faster(C3):
    # C3 module with cross-convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)
        self.m = nn.Sequential(*(Faster_Block(c_, c_) for _ in range(n)))

该程序文件名为yolov5-FasterBlock.py,代码实现了一个名为Faster_Block的类,该类继承自nn.Module。Faster_Block类包含了以下几个子模块:

  1. Partial_conv3类:该类继承自nn.Module,用于实现部分卷积操作。根据输入的维度dim和划分比例n_div,将输入划分为两部分,其中一部分经过3x3的卷积操作,另一部分保持不变。根据参数forward的取值,选择不同的前向传播方式。

  2. Faster_Block类:该类继承自nn.Module,用于实现Faster Block模块。该模块包含了多个部分,包括多层感知机(MLP)、部分卷积(Partial_conv3)、通道调整(adjust_channel)和残差连接(shortcut)。根据输入的参数,构建MLP网络,并根据参数inc和dim是否相等,选择是否进行通道调整。根据参数layer_scale_init_value的取值,选择不同的前向传播方式。

  3. C3_Faster类:该类继承自C3类,是一个带有交叉卷积的C3模块。该模块继承了C3模块的属性,并在其中使用了Faster_Block类构建多个Faster Block模块。

整个程序文件实现了一个Faster Block模块和一个带有交叉卷积的C3模块。

5.6 models\common.py
class YOLOv5(nn.Module):
    def __init__(self, cfg='yolov5s.yaml', ch=3, nc=None):
        super().__init__()
        self.model, self.save = parse_model(deepcopy(yaml.load(open(cfg))))  # model, savelist
        self.nc = nc  # number of classes

    def forward(self, x, augment=False, profile=False):
        return self.model.forward(x, augment, profile)

    def fuse(self):
        # Fuse Conv2d + BatchNorm2d layers throughout model
        for m in self.model.modules():
            if type(m) is Conv:
                m.forward = m.forward_fuse  # update forward
            elif type(m) is ConvBnAct:
                m.forward = m.forward_fuse  # update forward
            elif type(m) is BottleneckCSP:
                m.cv3.conv = fuse_conv_and_bn(m.cv3.conv, m.cv3.bn)  # update conv
                m.cv3.bn = None  # remove batchnorm
            elif type(m) is C3:
                m.cv3.conv = fuse_conv_and_bn(m.cv3.conv, m.cv3.bn)  # update conv
                m.cv3.bn = None  # remove batchnorm
            elif type(m) is SPP:
                m.cv2.conv = fuse_conv_and_bn(m.cv2.conv, m.cv2.bn)  # update conv
                m.cv2.bn = None  # remove batchnorm
            elif type(m) is SPPF:
                m.cv2.conv = fuse_conv_and_bn(m.cv2.conv, m.cv2.bn)  # update conv
                m.cv2.bn = None  # remove batchnorm
            elif type(m) is Focus:
                m.conv.conv = fuse_conv_and_bn(m.conv.conv, m.conv.bn)  # update conv
                m.conv.bn = None  # remove batchnorm
            elif type(m) is GhostBottleneck:
                m.conv.conv1 = fuse_conv_and_bn(m.conv.conv1, m.conv.bn1)  # update conv
                m.conv.bn1 = None  # remove batchnorm
                m.conv.conv2 = fuse_conv_and_bn(m.conv.conv2, m.conv.bn2)  # update conv
                m.conv.bn2 = None  # remove batchnorm
            elif type(m) is GhostConv:
                m.cv1.conv = fuse_conv_and_bn(m.cv1.conv, m.cv1.bn)  # update conv
                m.cv1.bn = None  # remove batchnorm
                m.cv2.conv = fuse_conv_and_bn(m.cv2.conv, m.cv2.bn)  # update conv
                m.cv2.bn = None  # remove batchnorm
        return self

    def _initialize_biases(self, cf=None):  # initialize biases into Detect() module
        # cf is class frequency
        m = self.model[-1]  # Detect() module
        for mi, s in zip(m.m, ([self.nc + 5, self.nc + 5, self.nc + 5] if cf is None else cf) + [3]):
            b = mi.bias.view(s, -1)  # split bias into separate shape
            b[:, 4] += math.log(8 / (640 / s) ** 2)  # obj (8 objects per 640 image)
            b[:, 5:] += math.log(0.6 / (self.nc - 0.99)) if cf is None else torch.log(cf / cf.sum())  # cls
            mi.bias = torch.nn.Parameter(b.view(-1), requires_grad=True)

    def _initialize_alphas(self):  # initialize alphas into GhostBottleneck() and GhostConv() modules
        def init_alphas(m):
            if hasattr(m, 'alphas'):
                m.alphas.data.uniform_(-3, -2)  # positive
        self.model.apply(init_alphas)

    def _initialize_weights(self):
        # Initialize model with custom weights
        # Official init from ultralytics/yolov5
        for m in self.modules():
            t = type(m)
            if t is nn.Conv2d:
                pass  # nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif t is nn.BatchNorm2d:
                m.eps = 1e-3
                m.momentum = 0.03
            elif t in [nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU, nn.Sigmoid]:
                m.inplace = True

        # Initialize deepsleep weights
        for m in self.model.modules():
            if type(m) is ConvBnAct:
                nn.init.kaiming_normal_(m.conv.weight, mode='fan_out', nonlinearity='relu')
                if m.conv.bias is not None:
                    nn.init.constant_(m.conv.bias, 0)
                if m.bn is not None:
                    nn.init.constant_(m.bn.weight, 1)
                    nn.init.constant_(m.bn.bias, 0)
            elif type(m) is BottleneckCSP:
                nn.init.kaiming_normal_(m.cv1.conv.weight, mode='fan_out', nonlinearity='relu')
                nn.init.kaiming_normal_(m.cv2.conv.weight, mode='fan_out', nonlinearity='relu')
                if m.cv1.conv.bias is not None:
                    nn.init.constant_(m.cv1.conv.bias, 0)
                if m.cv2.conv.bias is not None:
                    nn.init.constant_(m.cv2.conv.bias, 0)
                if m.bn is not None:
                    nn.init.constant_(m.bn.weight, 1)
                    nn.init.constant_(m.bn.bias, 0)
            elif type(m) is SPP:
                nn.init.kaiming_normal_(m.cv1.conv.weight, mode

这个程序文件是YOLOv5的一部分,主要包含了一些常用的模块和函数。文件中定义了一些卷积层和网络模块,如Conv、DWConv、TransformerLayer、TransformerBlock、Bottleneck、BottleneckCSP等。这些模块和函数用于构建YOLOv5的网络结构。此外,文件中还包含了一些辅助函数和工具函数,用于数据处理、模型训练和推理等操作。

6.系统整体结构

根据以上分析,该程序是一个综合应用了FasterNet和YOLOv5的苹果品质分级系统。主要功能是使用FasterNet模型进行图像分类和品质分级,以及使用YOLOv5模型进行目标检测。程序的整体构架如下:

  1. FasterNet模块:包括FasterNet.py和yolov5-FasterBlock.py文件,用于构建FasterNet模型,其中FasterNet.py定义了FasterNet的基本模块和主体结构,yolov5-FasterBlock.py定义了Faster Block模块和带有交叉卷积的C3模块。

  2. YOLOv5模块:包括models目录下的多个文件,如models\common.py、models\experimental.py、models\tf.py、models\yolo.py等,用于构建YOLOv5的网络结构和相关功能。

  3. 训练和推理模块:train.py文件用于训练模型,ui.py文件是一个用户界面程序,用于选择图像并进行苹果品质分级检测。

  4. 工具模块:tools目录下的多个文件,如tools\activations.py、tools\augmentations.py、tools\autoanchor.py等,包含了一些辅助函数和工具函数,用于数据处理、模型训练和推理等操作。

  5. 实用工具模块:utils目录下的多个文件,如utils\activations.py、utils\augmentations.py、utils\autoanchor.py等,也包含了一些辅助函数和工具函数,用于数据处理、模型训练和推理等操作。

下表整理了每个文件的功能:

文件路径 功能
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\DropPath.py 实现路径丢弃操作的函数和类
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\FasterNet.py 构建FasterNet模型的类和函数
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\train.py 训练YOLOv5模型的主程序
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\ui.py 构建用户界面的程序
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\yolov5-FasterBlock.py 实现Faster Block模块和带有交叉卷积的C3模块的类
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\models\common.py 包含常用的模块和函数,用于构建YOLOv5的网络结构
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\models\experimental.py 包含实验性的模块和函数,用于构建YOLOv5的网络结构
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\models\tf.py 包含与TensorFlow相关的模块和函数,用于构建YOLOv5的网络结构
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\models\yolo.py 包含YOLOv5的主要模块和函数,用于构建YOLOv5的网络结构
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\models_init_.py 模型相关的初始化文件
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\activations.py 包含激活函数的定义和相关操作
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\augmentations.py 包含数据增强的函数和类,用于数据预处理
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\autoanchor.py 包含自动锚框生成的函数和类,用于锚框的设置和调整
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\autobatch.py 包含自动批处理的函数和类,用于批处理大小的自动调整
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\callbacks.py 包含回调函数的定义和相关操作,用于模型训练的回调控制
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\datasets.py 包含数据集的定义和相关操作,用于加载和处理数据集
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\downloads.py 包含下载数据集和模型的函数和类,用于数据集和模型的下载和管理
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\general.py 包含一些通用的函数和工具,用于通用操作和功能实现
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\loss.py 包含损失函数的定义和相关操作,用于模型训练的损失计算
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\metrics.py 包含评估指标的定义和相关操作,用于模型训练的评估计算
E:\视觉项目\shop\【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统\code\tools\plots.py 包含绘图

7.FasterNet简介

神经网络在图像分类、检测和分割等各种计算机视觉任务中经历了快速发展。尽管其令人印象深刻的性能为许多应用程序提供了动力,但一个巨大的趋势是追求具有低延迟和高吞吐量的快速神经网络,以获得良好的用户体验、即时响应和安全原因等。

如何快速?研究人员和从业者不需要更昂贵的计算设备,而是倾向于设计具有成本效益的快速神经网络,降低计算复杂度,主要以浮点运算(FLOPs)的数量来衡量。

MobileNet、ShuffleNet和GhostNet等利用深度卷积(DWConv)和/或组卷积(GConv)来提取空间特征。然而,在减少FLOPs的过程中,算子经常会受到内存访问增加的副作用的影响。MicroNet进一步分解和稀疏网络,将其FLOPs推至极低水平。尽管这种方法在FLOPs方面有所改进,但其碎片计算效率很低。此外,上述网络通常伴随着额外的数据操作,如级联、Shuffle和池化,这些操作的运行时间对于小型模型来说往往很重要。

除了上述纯卷积神经网络(CNNs)之外,人们对使视觉Transformer(ViTs)和多层感知器(MLP)架构更小更快也越来越感兴趣。例如,MobileViT和MobileFormer通过将DWConv与改进的注意力机制相结合,降低了计算复杂性。然而,它们仍然受到DWConv的上述问题的困扰,并且还需要修改的注意力机制的专用硬件支持。使用先进但耗时的标准化和激活层也可能限制其在设备上的速度。

所有这些问题一起导致了以下问题:这些“快速”的神经网络真的很快吗?为了回答这个问题,作者检查了延迟和FLOPs之间的关系,这由
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第3张图片

其中FLOPS是每秒浮点运算的缩写,作为有效计算速度的度量。虽然有许多减少FLOPs的尝试,但都很少考虑同时优化FLOPs以实现真正的低延迟。为了更好地理解这种情况,作者比较了Intel CPU上典型神经网络的FLOPS。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第4张图片

图中的结果表明,许多现有神经网络的FLOPS较低,其FLOPS通常低于流行的ResNet50。由于FLOPS如此之低,这些“快速”的神经网络实际上不够快。它们的FLOPs减少不能转化为延迟的确切减少量。在某些情况下,没有任何改善,甚至会导致更糟的延迟。例如,CycleMLP-B1具有ResNet50的一半FLOPs,但运行速度较慢(即CycleMLPB1与ResNet50:111.9ms与69.4ms)。

请注意,FLOPs与延迟之间的差异在之前的工作中也已被注意到,但由于它们采用了DWConv/GConv和具有低FLOPs的各种数据处理,因此部分问题仍未解决。人们认为没有更好的选择。

该博客提供的方案通过开发一种简单、快速、有效的运算符来消除这种差异,该运算符可以在减少FLOPs的情况下保持高FLOPS。

具体来说,作者重新审视了现有的操作符,特别是DWConv的计算速度——FLOPS。作者发现导致低FLOPS问题的主要原因是频繁的内存访问。然后,作者提出了PConv作为一种竞争性替代方案,它减少了计算冗余以及内存访问的数量。

图1说明了PConv的设计。它利用了特征图中的冗余,并系统地仅在一部分输入通道上应用规则卷积(Conv),而不影响其余通道。本质上,PConv的FLOPs低于常规Conv,而FLOPs高于DWConv/GConv。换句话说,PConv更好地利用了设备上的计算能力。PConv在提取空间特征方面也很有效,这在本文后面的实验中得到了验证。

作者进一步引入PConv设计了FasterNet作为一个在各种设备上运行速度非常快的新网络家族。特别是,FasterNet在分类、检测和分割任务方面实现了最先进的性能,同时具有更低的延迟和更高的吞吐量。例如,在GPU、CPU和ARM处理器上,小模型FasterNet-T0分别比MobileVitXXS快3.1倍、3.1倍和2.5倍,而在ImageNet-1k上的准确率高2.9%。大模型FasterNet-L实现了83.5%的Top-1精度,与Swin-B不相上下,同时在GPU上提供了49%的高吞吐量,在CPU上节省了42%的计算时间。

总之,贡献如下:

指出了实现更高FLOPS的重要性,而不仅仅是为了更快的神经网络而减少FLOPs。

引入了一种简单但快速且有效的卷积PConv,它很有可能取代现有的选择DWConv。

推出FasterNet,它在GPU、CPU和ARM处理器等多种设备上运行良好且普遍快速。

对各种任务进行了广泛的实验,并验证了PConv和FasterNet的高速性和有效性。

8.PConv和FasterNet的设计

原理

DWConv是Conv的一种流行变体,已被广泛用作许多神经网络的关键构建块。对于输入,DWConv应用个滤波器来计算输出。如图(b)所示,每个滤波器在一个输入通道上进行空间滑动,并对一个输出通道做出贡献。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第5张图片
与具有的FLOPs常规Conv相比,这种深度计算使得DWConv仅仅具有的FLOPs。虽然在减少FLOPs方面有效,但DWConv(通常后跟逐点卷积或PWConv)不能简单地用于替换常规Conv,因为它会导致严重的精度下降。因此,在实践中,DWConv的通道数(或网络宽度)增加到>以补偿精度下降,例如,倒置残差块中的DWConv宽度扩展了6倍。然而,这会导致更高的内存访问,这会造成不可忽略的延迟,并降低总体计算速度,尤其是对于I/O绑定设备。特别是,内存访问的数量现在上升到
在这里插入图片描述

它比一个常规的Conv的值要高,即,
在这里插入图片描述

注意,内存访问花费在I/O操作上,这被认为已经是最小的成本,很难进一步优化。

PConv作为一个基本的算子

在下面演示了通过利用特征图的冗余度可以进一步优化成本。如图所示,特征图在不同通道之间具有高度相似性。许多其他著作也涵盖了这种冗余,但很少有人以简单而有效的方式充分利用它。

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第6张图片

具体而言,作者提出了一种简单的PConv,以同时减少计算冗余和内存访问。图4中的左下角说明了PConv的工作原理。它只需在输入通道的一部分上应用常规Conv进行空间特征提取,并保持其余通道不变。对于连续或规则的内存访问,将第一个或最后一个连续的通道视为整个特征图的代表进行计算。在不丧失一般性的情况下认为输入和输出特征图具有相同数量的通道。因此,PConv的FLOPs仅
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第7张图片

对于典型的r=1/4 ,PConv的FLOPs只有常规Conv的1/16。此外,PConv的内存访问量较小,即:
在这里插入图片描述

对于r=1/4,其仅为常规Conv的1/4。

由于只有通道用于空间特征提取,人们可能会问是否可以简单地移除剩余的(c−)通道?如果是这样,PConv将退化为具有较少通道的常规Conv,这偏离了减少冗余的目标。

请注意,保持其余通道不变,而不是从特征图中删除它们。这是因为它们对后续PWConv层有用,PWConv允许特征信息流经所有通道。

PConv之后是PWConv

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第8张图片

为了充分有效地利用来自所有通道的信息,进一步将逐点卷积(PWConv)附加到PConv。它们在输入特征图上的有效感受野看起来像一个T形Conv,与均匀处理补丁的常规Conv相比,它更专注于中心位置,如图5所示。为了证明这个T形感受野的合理性,首先通过计算位置的Frobenius范数来评估每个位置的重要性。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第9张图片

假设,如果一个职位比其他职位具有更大的Frobenius范数,则该职位往往更重要。对于正则Conv滤波器,位置处的Frobenius范数由计算,其中。

一个显著位置是具有最大Frobenius范数的位置。然后,在预训练的ResNet18中集体检查每个过滤器,找出它们的显著位置,并绘制显著位置的直方图。图6中的结果表明,中心位置是过滤器中最常见的突出位置。换句话说,中心位置的权重比周围的更重。这与集中于中心位置的T形计算一致。

虽然T形卷积可以直接用于高效计算,但作者表明,将T形卷积分解为PConv和PWConv更好,因为该分解利用了滤波器间冗余并进一步节省了FLOPs。对于相同的输入和输出,T形Conv的FLOPs可以计算为:
在这里插入图片描述

它高于PConv和PWConv的流量,即:

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第10张图片

其中和(例如,当时)。此外,可以很容易地利用常规Conv进行两步实现。

9.FasterNet作为Backbone

鉴于新型PConv和现成的PWConv作为主要的算子,进一步提出FasterNet,这是一个新的神经网络家族,运行速度非常快,对许多视觉任务非常有效。目标是使体系结构尽可能简单,使其总体上对硬件友好。

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第11张图片

在图中展示了整体架构。它有4个层次级,每个层次级前面都有一个嵌入层(步长为4的常规4×4卷积)或一个合并层(步长为2的常规2×2卷积),用于空间下采样和通道数量扩展。每个阶段都有一堆FasterNet块。作者观察到,最后两个阶段中的块消耗更少的内存访问,并且倾向于具有更高的FLOPS,如表1中的经验验证。因此,放置了更多FasterNet块,并相应地将更多计算分配给最后两个阶段。每个FasterNet块有一个PConv层,后跟2个PWConv(或Conv 1×1)层。它们一起显示为倒置残差块,其中中间层具有扩展的通道数量,并且放置了Shorcut以重用输入特征。

除了上述算子,标准化和激活层对于高性能神经网络也是不可或缺的。然而,许多先前的工作在整个网络中过度使用这些层,这可能会限制特征多样性,从而损害性能。它还可以降低整体计算速度。相比之下,只将它们放在每个中间PWConv之后,以保持特征多样性并实现较低的延迟。

此外,使用批次归一化(BN)代替其他替代方法。BN的优点是,它可以合并到其相邻的Conv层中,以便更快地进行推断,同时与其他层一样有效。对于激活层,根据经验选择了GELU用于较小的FasterNet变体,而ReLU用于较大的FasterNet变体,同时考虑了运行时间和有效性。最后三个层,即全局平均池化、卷积1×1和全连接层,一起用于特征转换和分类。

为了在不同的计算预算下提供广泛的应用,提供FasterNet的Tiny模型、Small模型、Medium模型和Big模型变体,分别称为FasterNetT0/1/2、FasterNet-S、FasterNet-M和FasterNet-L。它们具有相似的结构,但深度和宽度不同。

架构规范如下:
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第12张图片

10.训练结果可视化分析

评价指标

Epoch:训练过程的迭代次数。
训练框损失:训练期间与边界框预测相关的损失。
训练对象损失:训练期间与对象检测相关的损失。
训练类别损失:与训练期间对对象进行分类相关的损失。
指标(Precision、Recall、mAP_0.5、mAP_0.5:0.95):Precision 和 Recall 是物体检测准确度的指标,而 mAP(平均精度)在不同阈值(0.5,范围为 0.5 到 0.95) )衡量整体检测性能。
Val Box/Object/Class Loss:这些分别是边界框预测、对象检测和分类的验证损失。
学习率(x/lr0、x/lr1、x/lr2):神经网络不同层或组件的学习率。

训练结果可视化

这些可视化将有助于了解模型的性能在训练过程中如何演变以及哪里可能有改进的空间。让我们从创建这些可视化开始。

import matplotlib.pyplot as plt
import seaborn as sns

# Setting the style for the plots
sns.set(style="whitegrid")

def plot_metrics(data, metrics, title, xlabel, ylabel):
    plt.figure(figsize=(12, 6))
    for metric in metrics:
        plt.plot(data['epoch'], data[metric], label=metric)
    plt.title(title)
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.legend()
    plt.show()

# Plotting training loss metrics
train_loss_metrics = ['train/box_loss', 'train/obj_loss', 'train/cls_loss']
plot_metrics(data, train_loss_metrics, 'Training Loss Metrics Over Epochs', 'Epoch', 'Loss')

# Plotting validation loss metrics
val_loss_metrics = ['val/box_loss', 'val/obj_loss', 'val/cls_loss']
plot_metrics(data, val_loss_metrics, 'Validation Loss Metrics Over Epochs', 'Epoch', 'Loss')

# Plotting precision, recall, and mAP metrics
performance_metrics = ['metrics/precision', 'metrics/recall', 'metrics/mAP_0.5', 'metrics/mAP_0.5:0.95']
plot_metrics(data, performance_metrics, 'Precision, Recall, and mAP Scores Over Epochs', 'Epoch', 'Score')

# Plotting learning rate changes
lr_metrics = ['x/lr0', 'x/lr1', 'x/lr2']
plot_metrics(data, lr_metrics, 'Learning Rates Over Epochs', 'Epoch', 'Learning Rate')

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第13张图片
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第14张图片
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第15张图片
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第16张图片
这些可视化结果为了解 Apple 质量分级系统在不同时期使用 YOLO 与 FasterNet 集成的性能和行为提供了宝贵的见解。我们从各个方面来分析一下:

训练损失指标

框丢失:此指标表示模型预测苹果周围边界框位置的效果如何。下降趋势表明定位物体的准确性有所提高。
对象丢失:表示模型检测预测框中是否存在对象的能力。这里的下降趋势表明物体检测性能更好。
类别损失:反映模型正确分类苹果的熟练程度。随着这种损失的减少,这表明分类准确性得到提高。

验证损失指标

框、对象和类的验证损失遵循与训练损失类似的趋势,表明学习过程是一致的。然而,密切监视这些是否存在任何过度拟合的迹象至关重要,在这种情况下,训练损失持续减少,而验证损失开始增加。

准确率、召回率和 mAP 分数

Precision:衡量预测的准确性,即真阳性占所有阳性预测的比例。精度的提高表明随着时间的推移,模​​型产生的误报越来越少。
召回率:代表模型找到所有相关案例(真阳性)的能力。召回率的上升趋势表明该模型丢失的实际苹果较少。
mAP(平均平均精度):mAP_0.5 和 mAP_0.5:0.95 提供不同 IoU(交并集)阈值下对象检测性能的总体度量。mAP 值越高表示精度和召回率方面的整体性能越好。

学习率

显示了模型不同层/组件的学习率。这些速率的调整可以显着影响模型的学习效率。选择最佳学习率来平衡收敛速度和超过最小值的风险非常重要。

混淆矩阵 (confusion_matrix.png):

该图像可能呈现一个显示分类模型性能的混淆矩阵。它将预测的分类与真实的分类进行比较,对角线代表正确的预测。非对角元素将表明错误分类。分析混淆矩阵可以深入了解模型所犯错误的类型,例如哪些类相互混淆。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第17张图片

F1 分数曲线 (F1_curve.png):

F1 分数是结合了精度和召回率的度量。该曲线将说明各种阈值设置下精确度和召回率之间的权衡。当类别不平衡时,它特别有用。F1 曲线的峰值代表精度和召回率最佳平衡的阈值,这可能是分类器的操作点。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第18张图片

标签分布 (labels.jpg):

该图像可能显示数据集中不同类的分布。重要的是要确保不存在可能使模型的预测产生偏差的重大类别不平衡。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第19张图片

标签相关图 (labels_correlogram.jpg):

相关图显示本例中变量或标签之间的相关性。对于多标签分类任务,它将显示标签之间是否存在任何依赖关系,这对于理解标签共现或特征工程可能很有用。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第20张图片

精度曲线 (P_curve.png):

该曲线将显示分类器在不同置信阈值水平下的精度。在误报成本较高的情况下,精度非常重要。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第21张图片

精确率-召回率曲线 (PR_curve.png):

该曲线绘制了精确率和召回率的相互关系。它提供了不同阈值的真阳性率和阳性预测值之间的权衡的全面视图。具有完美性能的模型将具有一条紧贴绘图右上角的曲线。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第22张图片

召回曲线 (R_curve.png):

与精度曲线类似,这将显示分类器在不同置信度阈值下的召回率。在错过真正阳性的代价高昂的情况下,召回尤其重要。
【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第23张图片

整体分析

该模型在训练和验证阶段都表现出一致的改进,这是一个积极的迹象。
确保验证损失和指标(尤其是 mAP 分数)与训练性能良好匹配至关重要,因为它们是模型如何在未见过的数据上执行的更好指标。
监控训练和验证指标之间的任何差异对于诊断过度拟合或拟合不足等问题至关重要。
进一步的分析可能包括检查预测误差的分布,识别模型表现不佳的特定类别或场景,以及实施数据增强、超参数调整或架构更改等策略来解决这些弱点。

11.系统整合

下图完整源码&数据集&环境部署视频教程&自定义UI界面

【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统_第24张图片

参考博客《【CVPR2023】融合FasterNet的YOLO的苹果品质分级系统》

12.参考文献


[1]林海波,卢元栋,丁荣诚,等.基于图像处理与改进SVM的苹果多特征融合分级方法[J].山东农业科学.2022,54(6).DOI:10.14083/j.issn.1001-4942.2022.06.020 .

[2]仇晓洁,罗荣芸.MLP模型在房地产批量评估中的应用研究[J].中国资产评估.2022,(1).DOI:10.3969/j.issn.1007-0265.2022.01.005 .

[3]陈庆光,刘强,张竞成,等.多视角三维视觉成像的苹果果形测量与分类[J].杭州电子科技大学学报.2022,42(4).DOI:10.13954/j.cnki.hdu.2022.04.006 .

[4]阳光灿,熊禾根.改进遗传算法求解柔性作业车间调度问题[J].计算机仿真.2022,39(2).DOI:10.3969/j.issn.1006-9348.2022.02.042 .

[5]项辉宇,黄恩浩,冷崇杰,等.基于图像处理与深度学习的苹果检测分级[J].食品安全导刊.2022,(22).

[6]张婧婧,程芸涛,达新民.基于K-means聚类的苹果图像处理与分级设计[J].计算机与数字工程.2021,(8).DOI:10.3969/j.issn.1672-9722.2021.08.030 .

[7]罗炤茜,陈月芬,占煜辉,等.基于Keras和CNN的苹果自动分级[J].系统仿真技术.2021,(1).DOI:10.3969/j.issn.1673-1964.2021.01.011 .

[8]张弛,付相君,周先颖,等.基于MLP的相关路段流量预测模型[J].重庆理工大学学报(自然科学版).2021,(8).DOI:10.3969/j.issn.1674-8425(z).2021.08.017 .

[9]李文其,凌晨昱,余雷.基于卷积神经网络的苹果分级算法研究[J].电工技术.2021,(20).DOI:10.19768/j.cnki.dgjs.2021.20.016 .

[10]张驰,郭媛,黎明.人工神经网络模型发展及应用综述[J].计算机工程与应用.2021,(11).DOI:10.3778/j.issn.1002-8331.2102-0256 .

你可能感兴趣的:(YOLO,人工智能,计算机视觉,深度学习)