Yolov3-spp系列 | yolov3spp的训练验证与测试过程

简介: Yolov3-spp系列 | yolov3spp的训练验证与测试过程

1. 训练过程


1.1 参考代码

代码如下:


def train_one_epoch(model, optimizer, data_loader, device, epoch, epochs,
                    print_freq, accumulate, img_size,
                    grid_min, grid_max, gs,
                    multi_scale=False, warmup=True):
    """
    Args:
        data_loader: len = 1430 1430个batch_size=1个epochs分成一块块的batch_size
        print_freq: 每50个batch在logger中更新
        accumulate: 1、多尺度训练时accumulate个batch改变一次图片的大小
                    2、每训练accumulate*batch_size张图片更新一次权重和学习率
                    第一个epoch  accumulate=1
        img_size: 训练图像的大小
        grid_min, grid_max: 在给定最大最小输入尺寸范围内随机选取一个size(size为32的整数倍)
        gs: grid_size
        warmup: 用在训练第一个epoch时,这个时候的训练学习率要调小点,慢慢训练
    Returns:
        mloss: 每个epch计算的mloss [box_mean_loss, obj_mean_loss, class_mean_loss, total_mean_loss]
        now_lr: 每个epoch之后的学习率
    """
    model.train()
    metric_logger = utils.MetricLogger(delimiter="  ")
    metric_logger.add_meter('lr', utils.SmoothedValue(window_size=1, fmt='{value:.6f}'))
    header = 'Epoch: [{}/{}]'.format(epoch, epochs)
    # 模型训练开始第一轮采用warmup训练 慢慢训练
    lr_scheduler = None
    if epoch == 1 and warmup is True:  # 当训练第一轮(epoch=1)时,启用warmup训练方式,可理解为热身训练
        warmup_factor = 1.0 / 1000
        warmup_iters = min(1000, len(data_loader) - 1)
        lr_scheduler = utils.warmup_lr_scheduler(optimizer, warmup_iters, warmup_factor)
        accumulate = 1  # 慢慢训练,每个batch都改变img大小,每个batch都改变权重
    # amp.GradScaler: 混合精度训练
    # GradScaler: 在反向传播前给 loss 乘一个 scale factor,所以之后反向传播得到的梯度都乘了相同的 scale factor
    # scaler: GradScaler对象用来自动做梯度缩放
    # https://blog.csdn.net/l7H9JA4/article/details/114324414?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161944073216780357273770%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161944073216780357273770&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-1-114324414.pc_search_result_cache&utm_term=amp.GradScaler%28enabled%3Denable_amp%29
    enable_amp = True if "cuda" in device.type else False
    scaler = amp.GradScaler(enabled=enable_amp)
    # mean losses [box_mean_loss, obj_mean_loss, class_mean_loss, total_mean_loss]
    mloss = torch.zeros(4).to(device)
    now_lr = 0.  # 本batch的lr
    nb = len(data_loader)  # number of batches
    # imgs: [batch_size, 3, img_size, img_size]
    # targets: [num_obj, 6] , that number 6 means -> (img_index, obj_index, x, y, w, h)
    # paths: list of img path
    # 这里调用一次datasets.__len__; batch_size次datasets.__getitem__; 再执行1次datasets.collate_fn
    for i, (imgs, targets, paths, _, _) in enumerate(metric_logger.log_every(data_loader, print_freq, header)):
        # ni 统计从epoch0开始的所有batch数
        ni = i + nb * epoch  # number integrated batches (since train start)
        # imgs: [4, 3, 736, 736]一个batch的图片
        # targets(真实框): [22, 6] 22: num_object  6: batch中第几张图(0,1,2,3),类别,x,y,w,h
        imgs = imgs.to(device).float() / 255.0  # 对imgs进行归一化 uint8 to float32, 0 - 255 to 0.0 - 1.0
        targets = targets.to(device)
        # Multi-Scale
        if multi_scale:
            # 每训练accumulate个batch(batch_size*accumulate张图片),就随机修改一次输入图片大小
            # 由于label已转为相对坐标,故缩放图片不影响label的值
            if ni % accumulate == 0:  #  adjust img_size (67% - 150%) every 1 batch
                # 在给定最大最小输入尺寸范围内随机选取一个size(size为32的整数倍)
                img_size = random.randrange(grid_min, grid_max + 1) * gs  # img_size = 320~736
            sf = img_size / max(imgs.shape[2:])  # scale factor
            # 如果图片最大边长不等于img_size, 则缩放一个batch图片,并将长和宽调整到32的整数倍
            if sf != 1:
                # gs: (pixels) grid size
                ns = [math.ceil(x * sf / gs) * gs for x in imgs.shape[2:]]  # new shape (stretched to 32-multiple)
                imgs = F.interpolate(imgs, size=ns, mode='bilinear', align_corners=False)
        # 混合精度训练上下文管理器,如果在CPU环境中不起任何作用
        with amp.autocast(enabled=enable_amp):
            # pred: tensor格式 list列表 存放三个tensor 对应的是三个yolo层的输出
            # 例如[batch_size, 3, 23, 23, 25]  [batch_size, 3, 46, 46, 25]  [batch_size, 3, 96, 96, 25]
            # [batch_size, anchor_num, grid_h, grid_w, xywh + obj + classes]
            # 可以看出来这里的预测值是三个yolo层每个grid_cell(每个grid_cell有三个预测值)的预测值,后面肯定要进行正样本筛选
            pred = model(imgs)
            # dict格式 存放三分tensor 每个tensor对应一个loss的键值对
            # loss的顺序(键)为: 'box_loss', 'obj_loss', 'class_loss'
            # targets(数据增强后的真实框): [21, 6] 21: num_object  6: batch中第几张图(0,1,2,3)+类别+x+y+w+h
            loss_dict = compute_loss(pred, targets, model)
            losses = sum(loss for loss in loss_dict.values())  # 三个相加
            # reduce losses over all GPUs for logging purpose
            loss_dict_reduced = utils.reduce_dict(loss_dict)
            losses_reduced = sum(loss for loss in loss_dict_reduced.values())
            loss_items = torch.cat((loss_dict_reduced["box_loss"],
                                    loss_dict_reduced["obj_loss"],
                                    loss_dict_reduced["class_loss"],
                                    losses_reduced)).detach()
            mloss = (mloss * i + loss_items) / (i + 1)  # update mean losses
            # 如果losses_reduced无效,则输出对应图片信息
            if not torch.isfinite(losses_reduced):
                print('WARNING: non-finite loss, ending training ', loss_dict_reduced)
                print("training image path: {}".format(",".join(paths)))
                sys.exit(1)
            losses *= 1. / accumulate  # scale loss
        # 1、backward 反向传播 scale loss 先将梯度放大 防止梯度消失
        scaler.scale(losses).backward()
        # optimize
        # 每训练accumulate*batch_size张图片更新一次权重
        if ni % accumulate == 0:
            # 2、scaler.step() 首先把梯度的值unscale回来.
            # 如果梯度的值不是 infs 或者 NaNs, 那么调用optimizer.step()来更新权重,
            # 否则,忽略step调用,从而保证权重不更新(不被破坏)
            scaler.step(optimizer)
            # 3、准备着,看是否要增大scaler 不一定更新  看scaler.step(optimizer)的结果,需要更新就更新
            scaler.update()
            # 正常更新权重
            optimizer.zero_grad()
        metric_logger.update(loss=losses_reduced, **loss_dict_reduced)
        now_lr = optimizer.param_groups[0]["lr"]
        metric_logger.update(lr=now_lr)
        # 每训练accumulate*batch_size张图片更新一次学习率(只在第一个epoch) warmup=True 才会执行
        if ni % accumulate == 0 and lr_scheduler is not None:
            lr_scheduler.step()
    return mloss, now_lr


1.2 简要分析

在yolov3spp的训练过程中,其重点只是利用网络的预测的三层特征层,来进行一个正负样本的匹配与损失计算,并结算的损失是根据中心点xy预测的偏移量已经以指数的形式来预测匹配到的anchor与targe的偏移量。


其中所使用到的iou计算不一样,对于边界框偏移量来说,正常使用iou/giou/diou/ciou来进行计算,但是对于正负样本匹配部分来说,选择那一个anchor与对应的target来进行匹配,是根据wh_iou,也就是重叠率来简单的进行计算的。也就是说,只需要根据两个预测框与目标框的宽高,而不需要知道其具体的位置信息来进行一个在大小上的匹配。


所以,整个训练过程是根据匹配好的anchor来进行拟合偏移量,这没有设置到非极大值抑制处理,也没有使用到coco的评价指标,只是计算了平均损失与当前的一个学习率。


2. 验证过程


2.1 参考代码

代码如下:


@torch.no_grad()
def evaluate(model, data_loader, coco=None, device=None):
    """
    Args:
        coco: coco api
    Returns:
    """
    n_threads = torch.get_num_threads()  # 8线程
    # FIXME remove this and make paste_masks_in_image run on the GPU
    torch.set_num_threads(1)
    cpu_device = torch.device("cpu")
    model.eval()
    metric_logger = utils.MetricLogger(delimiter="  ")
    header = "Test: "
    if coco is None:
        coco = get_coco_api_from_dataset(data_loader.dataset)
    iou_types = _get_iou_types(model)  # ['bbox']
    coco_evaluator = CocoEvaluator(coco, iou_types)
    # 这里调用一次datasets.__len__; batch_size次datasets.__getitem__; 再执行1次datasets.collate_fn
    # 调用__len__将dataset分为batch个批次; 再调用__getitem__取出(增强后)当前批次的每一张图片(batch_size张);
    # 最后调用collate_fn函数将当前整个批次的batch_size张图片(增强过的)打包成一个batch, 方便送入网络进行前向传播
    # img_index:对于的是哪一张图像的索引
    # paths:图像的路径
    # imgs:一个batch的图像本身
    # targets:一个列表,存储着每张图像的边界框信息
    for imgs, targets, paths, shapes, img_index in metric_logger.log_every(data_loader, 1, header):
        imgs = imgs.to(device).float() / 255.0  # uint8 to float32, 0 - 255 to 0.0 - 1.0
        # targets = targets.to(device)
        # 当使用CPU时,跳过GPU相关指令
        if device != torch.device("cpu"):
            torch.cuda.synchronize(device)
        model_time = time.time()
        pred = model(imgs)[0]  # only get inference result   [4, 5040, 25]
        # [4, 5040, 25] => len=4  [57,6], [5,6], [14,6], [1,6]  6: batch中第几张图(0,1,2,3),类别,x,y,w,h
        pred = non_max_suppression(pred, conf_thres=0.01, nms_thres=0.6, multi_cls=False)
        outputs = []
        for index, p in enumerate(pred):
            if p is None:
                p = torch.empty((0, 6), device=cpu_device)
                boxes = torch.empty((0, 4), device=cpu_device)
            else:
                # xmin, ymin, xmax, ymax
                boxes = p[:, :4]
                # shapes: (h0, w0), ((h / h0, w / w0), pad)
                # 将boxes信息还原回原图尺度,这样计算的mAP才是准确的
                boxes = scale_coords(imgs[index].shape[1:], boxes, shapes[index][0]).round()
            # 注意这里传入的boxes格式必须是xmin, ymin, xmax, ymax,且为绝对坐标
            info = {"boxes": boxes.to(cpu_device),
                    "labels": p[:, 5].to(device=cpu_device, dtype=torch.int64),
                    "scores": p[:, 4].to(cpu_device)}
            outputs.append(info)
        model_time = time.time() - model_time
        # 对每一张图片的信息进行打包出来,信息包括:边界框坐标、类别。置信度
        res = {img_id: output for img_id, output in zip(img_index, outputs)}
        evaluator_time = time.time()
        coco_evaluator.update(res)
        evaluator_time = time.time() - evaluator_time
        metric_logger.update(model_time=model_time, evaluator_time=evaluator_time)
    # gather the stats from all processes
    metric_logger.synchronize_between_processes()
    print("Averaged stats:", metric_logger)
    coco_evaluator.synchronize_between_processes()
    # accumulate predictions from all images
    coco_evaluator.accumulate()
    coco_evaluator.summarize()
    torch.set_num_threads(n_threads)
    result_info = coco_evaluator.coco_eval[iou_types[0]].stats.tolist()  # numpy to list
    return result_info
def _get_iou_types(model):
    model_without_ddp = model
    if isinstance(model, torch.nn.parallel.DistributedDataParallel):
        model_without_ddp = model.module
    iou_types = ["bbox"]
    return iou_types


2.2 简要分析

在验证过程中,最主要的不同是需要看看训练完后对当前这个验证集的效果,这个是验证过程的核心环节,可以用来检验训练效果以及挑选最后的一个训练权重。


这一部分其实和测试部分有点相像,对于训练好的模型输出的一个预测结果,需要经过非极大值抑制处理,来进行一步步的筛选出比较符合的预测框。其中的重点就是需要非极大值抑制处理,也就是所谓的nms后处理方法。根据预测结果获取后处理后的boxes、labels、scores(置信度),然后对于每一张图像就可以得到他的预测边界框信息,预测类别信息,预测的置信度分数三个类别,够成一个字典,形式为:{img_id: img_info}。


然后使用CocoEvaluator来对刚刚所构建的图像-预测结果字典来作一个评价:coco_evaluator.update(res),随机可以调用coco_evaluator类中的相关函数获取对于验证集的预测结果。


调用coco_evaluator的简要流程为:

coco = get_coco_api_from_dataset(data_loader.dataset)
coco_evaluator = CocoEvaluator(coco, iou_types)
...
res = {img_id: output for img_id, output in zip(img_index, outputs)}   # 构建图像-预测结果字典
coco_evaluator.update(res)
coco_evaluator.synchronize_between_processes()
coco_evaluator.accumulate()
coco_evaluator.summarize()
result_info = coco_evaluator.coco_eval[iou_types[0]].stats.tolist()   # 返回最后的评价结果


对于这一部分,之后会开设一个目标检测的技巧(trick)来详细介绍其使用方法。


3. 测试过程


3.1 参考代码

代码如下:

import os
import json
import time
import torch
import cv2
import argparse
import numpy as np
from matplotlib import pyplot as plt
from build_utils import datasets
from modules.model import DarkNet
from train_val_utils.draw_box_utils import draw_box
from train_val_utils.other_utils import time_synchronized, check_file
from train_val_utils.post_processing_utils import non_max_suppression, scale_coords
def main(opt):
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("Using {} device training.".format(device.type))
    # 1、载入opt参数
    cfg = opt.cfg               # yolo网络配置文件path
    weights = opt.weights       # 训练权重path
    json_path = opt.json_path   # voc classes json path
    img_path = opt.img_path     # 预测图片地址
    img_size = opt.img_size     # 预测图像大小(letterbox后)
    # 2、载入json文件 得到所有class
    json_file = open(json_path, 'r')
    class_dict = json.load(json_file)
    category_index = {v: k for k, v in class_dict.items()}
    # 3、初始化模型 模型载入权重
    model = DarkNet(cfg)
    model.load_state_dict(torch.load(weights, map_location=device)["model"], strict=False)
    model.to(device)
    # eval测试模式
    model.eval()
    with torch.no_grad():
        # 载入原图 img_o (375, 500, 3)  H W C
        img_o = cv2.imread(img_path)  # BGR numpy格式
        assert img_o is not None, "Image Not Found " + img_path
        # letterbox  numpy格式(array)   img:(384, 512, 3) H W C
        # 将原图最长边缩放到指定大小,再将原图较短边按原图比例缩放,最后将较短边两边pad操作缩放到最长边大小(不会失真)
        img = datasets.letterbox(img_o, new_shape=img_size, auto=True, color=(0, 0, 0))[0]
        # Convert (384, 512, 3) => (384, 512, 3) => (3, 384, 512)
        # img[:, :, ::-1]  BGR to RGB => transpose(2, 0, 1) HWC(384, 512, 3)  to  CHW(3, 384, 512)
        img = img[:, :, ::-1].transpose(2, 0, 1)
        img = np.ascontiguousarray(img)  # 使内存是连续的
        # numpy(3, 384, 512) CHW => torch.tensor [3, 384, 512] CHW
        img = torch.from_numpy(img).to(device).float()
        img /= 255.0  # 归一化scale (0, 255) to (0, 1)
        # [3, 384, 512] CHW => [1, 3, 384, 512] BCHW
        img = img.unsqueeze(0)  # add batch dimension
        # start inference
        t1 = time_synchronized()  # 获取当前时间 其实可以用time.time()
        # 推理阶段实际上会有两个返回值 x(相对原图的), p
        # x: predictor数据处理后的输出(数值是相对原图的,这里是img)
        #    [batch_size, anchor_num * grid * grid, xywh + obj + classes]
        #    这里pred[1,12096,25] (实际上是等于x)表示这张图片总共生成了12096个anchor(一个grid中三个anchor)
        # p: predictor原始输出即数据是相对feature map的
        #    [batch_size, anchor_num, grid, grid, xywh + obj + classes]
        pred = model(img)[0]  # only get inference result
        t2 = time_synchronized()
        print("model inference time:", t2 - t1)
        # nms pred=[7,6]=[obj_num, xyxy+score+cls] 这里的xyxy是相对img的
        # pred: 按score从大到小排列; output[0]=第一张图片的预测结果 不一定一次只传入一张图片的
        pred = non_max_suppression(pred)[0]
        t3 = time.time()
        print("nms time:", t3 - t2)
        if pred is None:
            print("No target detected.")
            exit(0)
        # 将nms后的预测结果pred tensor格式(是相对img上的)img.shape=[B,C,H,W]
        # 映射到原图img_o上 img_o.shape=[H, W, C]  pred=(anchor_nums, xyxy+score+class)
        pred[:, :4] = scale_coords(img.shape[2:], pred[:, :4], img_o.shape).round()
        print("pred shape:", pred.shape)
        # tensor.detach()截断tensor变量反向传播的梯度流,因为是预测所以不需要计算梯度信息
        # bboxes、scores、classes: 按score从大到小排列  tensor=>numpy
        bboxes = pred[:, :4].detach().cpu().numpy()  # xyxys
        scores = pred[:, 4].detach().cpu().numpy()   # scores
        classes = pred[:, 5].detach().cpu().numpy().astype(int) + 1  # classes
        # 到这一步,我们就得到了最终的相对原图的所有预测信息bboxes(位置信息)(7,4); scores(7); classes(类别)(7)
        # 画出每个预测结果
        img_o = draw_box(img_o[:, :, ::-1], bboxes, classes, scores, category_index)
        # 显示预测图片
        plt.imshow(img_o)
        plt.show()
        # 保存预测后的图片
        img_o.save("outputs/predict_result.jpg")
if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--cfg', type=str, default='cfg/yolov3-spp.cfg', help="cfg/*.cfg path")
    parser.add_argument('--weights', type=str, default='weights/yolov3spp-voc-512.pt',
                        help='pretrain weights path')
    parser.add_argument('--json-path', type=str, default='data/pascal_voc_classes.json',
                        help="voc_classes_json_path")
    parser.add_argument('--img-path', type=str, default='imgs/2008_000011.jpg',
                        help="predict img path")
    parser.add_argument('--img-size', type=int, default=512,
                        help="predict img path [416, 512, 608] 32的倍数")
    opt = parser.parse_args()
    # 检查文件是否存在
    opt.cfg = check_file(opt.cfg)
    opt.data = check_file(opt.weights)
    opt.hyp = check_file(opt.json_path)
    opt.hyp = check_file(opt.img_path)
    print(opt)
    main(opt)


3.2 简要分析

对于测试来说,最重要的就是根据训练好的权重来对图像进行预测,与验证类似,关键是对预测结果作一个非极大值抑制处理,也就是一个后处理方法,然后甚至不需要对其作一个评价指标,因为没有label。


所以,在测试来说,最后就是根据后处理完的预测结果来直接的进行一个可视化展示,就是对特征层结果来进行一个缩放处理,缩放到原图的原大小,以及对预测的边界框与类别信息在原图上画出来。


总结:


大致看完了整个yolov3spp项目,收获良多,知道了主要的处理细节。对于训练过程,重点就是正负样本的匹配问题了,也就是标签的分配,其是不需要进行一个后处理方法的;而对于验证过程,需要对预测结果进行nms然后使用coco评价指标来进行测试,这是个工具知道如何掉包就好;而对于测试结果,由于测试是没有标签信息的,所以直接将nms后处理后的预测结果直接在原图上进行一个可视化展示即可。


并且,为了加快验证与测试,验证过程与测试过程都会使用Rectangular inference来加快推理。Rectangular inference属于是目标检测中常见的一个数据处理的技巧了,作用就是加快推理速度与验证速度。


除了Rectangular inference之外,yolov3spp中还涉及大量的技巧,这里我并没有对其过多的介绍,只是记录了yolov3spp最本质的算法核心,就是如何进行正负样本匹配以及其损失是如何计算,如何进行训练与验证的。


对于其他设计的训练与测试技巧,之后会放在其他专栏来学习与记录。


参考资料:


https://blog.csdn.net/qq_38253797/article/details/118046587

https://blog.csdn.net/qq_38253797/article/details/117920079


相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
26天前
|
机器学习/深度学习 PyTorch 算法框架/工具
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
这篇文章介绍了如何使用PyTorch框架,结合CIFAR-10数据集,通过定义神经网络、损失函数和优化器,进行模型的训练和测试。
69 2
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
|
25天前
|
机器学习/深度学习 编解码 监控
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章详细介绍了如何使用YOLOv8进行目标检测任务,包括环境搭建、数据准备、模型训练、验证测试以及模型转换等完整流程。
640 1
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
25天前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
215 2
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
26天前
|
PyTorch 算法框架/工具 计算机视觉
目标检测实战(二):YoloV4-Tiny训练、测试、评估完整步骤
本文介绍了使用YOLOv4-Tiny进行目标检测的完整流程,包括模型介绍、代码下载、数据集处理、网络训练、预测和评估。
73 2
目标检测实战(二):YoloV4-Tiny训练、测试、评估完整步骤
|
24天前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
193 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
25天前
|
机器学习/深度学习 并行计算 数据可视化
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用PaddleClas框架完成多标签分类任务,包括数据准备、环境搭建、模型训练、预测、评估等完整流程。
69 0
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
|
25天前
|
机器学习/深度学习 JSON 算法
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
本文介绍了DeepLab V3在语义分割中的应用,包括数据集准备、模型训练、测试和评估,提供了代码和资源链接。
143 0
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
|
25天前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
42 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
25天前
|
机器学习/深度学习 XML 并行计算
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用YOLOX完成图像目标检测任务的完整流程,包括数据准备、模型训练、验证和测试。
126 0
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
25天前
|
机器学习/深度学习 算法 PyTorch
目标检测实战(五): 使用YOLOv5-7.0版本对图像进行目标检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-7.0版本进行目标检测的完整流程,包括算法介绍、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。YOLOv5以其高精度、快速度和模型小尺寸在计算机视觉领域受到广泛应用。
242 0
目标检测实战(五): 使用YOLOv5-7.0版本对图像进行目标检测完整版(从自定义数据集到测试验证的完整流程)