手把手带你微调yolov8+yolov11目标检测-教程

在本教程中,将介绍如何使用Torchvision中的Faster R-CNN模型对自定义数据集进行目标检测微调。我们将使用主流的Penn-Fudan数据集,这个数据集具有170个图像和345个行人实例,用于展示如何在一个具体的场景中进行行人检测。由于Penn-Fudan数据集比较小,所以我们将从COCO数据集中使用预先训练的模型来进行微调。

具体的,这个教程包含以下内容:

  1. 加载数据集
  2. 定义模型
  3. 定义损失函数
  4. 定义优化器
  5. 训练和验证模型

相信通过仔细学习,你会构建自己的深度学习目标检测模型!

如果对你有帮助还请多多关注,时刻分享人工智能相关知识!!

1. 加载数据集

我们将使用Penn-Fudan人工智能数据集,该数据集提供了170张包含行人实例的图像。我们已经将该数据集分成了训练集和验证集,其中训练集包含100张图像,验证集包含70张图像。这是一个二元分类问题:对于每个图像,我们需要预测是否存在行人实例。

Penn-Fudan数据集的文件夹结构如下:

PennFudanPed/
  PedMasks/
    FudanPed00001_mask.png
    FudanPed00002_mask.png
    FudanPed00003_mask.png
    FudanPed00004_mask.png
    ...
  PNGImages/
    FudanPed00001.png
    FudanPed00002.png
    FudanPed00003.png
    FudanPed00004.png
    ...
  Ped_annotations/
    FudanPed00001.txt
    FudanPed00002.txt
    FudanPed00003.txt
    FudanPed00004.txt
    ...

我们将使用torchvision提供的PennFudanDataset类来加载数据集。PennFudanDataset类继承自torch.utils.data.Dataset类,因此我们可以使用torchvision提供的数据加载器来加载数据集。

数据集下载可以联系我---

下面是加载数据集的代码:

相信做过很多项目的你,很熟悉torch加载数据的风格!!

import os
import numpy as np
import torch
from PIL import Image

class PennFudanDataset(torch.utils.data.Dataset):
    def __init__(self, root, transforms=None):
        self.root = root
        self.transforms = transforms
        # load all image files, sorting them to
        # ensure that they are aligned
        self.imgs = list(sorted(os.listdir(os.path.join(root, "PNGImages"))))
        self.masks = list(sorted(os.listdir(os.path.join(root, "PedMasks"))))

    def __getitem__(self, idx):
        # load images and masks
        img_path = os.path.join(self.root, "PNGImages", self.imgs[idx])
        mask_path = os.path.join(self.root, "PedMasks", self.masks[idx])
        img = Image.open(img_path).convert("RGB")
        # note that we haven't converted the mask to RGB,
        # because each color corresponds to a different instance
        # with 0 being background
        mask = Image.open(mask_path)

        # convert the PIL Image into a numpy array
        mask = np.array(mask)
        # instances are encoded as different colors
        obj_ids = np.unique(mask)
        # first id is the background, so remove it
        obj_ids = obj_ids[1:]

        # split the color-encoded mask into a set
        # of binary masks
        masks = mask == obj_ids[:, None, None]

        # get bounding box coordinates for each mask
        num_objs = len(obj_ids)
        boxes = []
        for i in range(num_objs):
            pos = np.where(masks[i])
            xmin = np.min(pos[1])
            xmax = np.max(pos[1])
            ymin = np.min(pos[0])
            ymax = np.max(pos[0])
            boxes.append([xmin, ymin, xmax, ymax])

        # convert everything into a torch.Tensor
        boxes = torch.as_tensor(boxes, dtype=torch.float32)
        # there is only one class
        labels = torch.ones((num_objs,), dtype=torch.int64)
        masks = torch.as_tensor(masks, dtype=torch.uint8)

        image_id = torch.tensor([idx])
        

数据加载完毕,我们开始构建模型。

2. 定义模型

我们将使用Torchvision中提供的高精度目标检测模型Faster R-CNN模型进行微调。Faster R-CNN是一种基于区域提取的目标检测方法,它通过先提取候选区域,再对这些候选区域进行分类和回归,从而检测图像中的目标。 在本教程中,我们将使用预先训练的Faster R-CNN模型进行微调,而不是从头开始训练一个新模型。我们将使用COCO数据集提供的预先训练的Faster R-CNN模型,该模型已经对COCO数据集进行了训练,可以很好地提取图像中的目标区域**。 这也是一个经典的两阶段目标检测器!**

下面是定义模型的代码:

import torchvision
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor

# load a pre-trained model for classification and return
# only the features
backbone = torchvision.models.mobilenet_v2(pretrained=True).features

# FasterRCNN needs to know the number of
# output channels in a backbone. For mobilenet_v2, it's 1280
# so we need to add it here
backbone.out_channels = 1280

# let's make the RPN generate 5 x 3 anchors per spatial
# location, with 5 different sizes and 3 different aspect
# ratios. We have a Tuple[Tuple[int]] because each feature
# map could potentially have different sizes and
# aspect ratios
anchor_generator = torchvision.models.detection.rpn.AnchorGenerator(
    sizes=((32, 64, 128, 256, 512),),
    aspect_ratios=((0.5, 1.0, 2.0),)
)

# let's define what are the feature maps that we will
# use to perform the region of interest cropping, as well as
# the size of the crop after rescaling.
# if your backbone returns a Tensor, featmap_names is expected to
# be [0]. More generally, the backbone should return an
# OrderedDict[Tensor], and in featmap_names you can choose which
# feature maps to use.
roi_pooler = torchvision.ops.MultiScaleRoIAlign(
    featmap_names=['0'],
    output_size=7,
    sampling_ratio=2
)

# put the pieces together inside a FasterRCNN model
model = torchvision.models.detection.FasterRCNN(
    backbone,
    num_classes=2,
    rpn_anchor_generator=anchor_generator,
    box_roi_pool=roi_pooler
)

# replace the classifier with a new one, that has
# num_classes which is user-defined
num_classes = 2
# get number of input features for the classifier
in_features = model.roi_heads.box_predictor.cls_score.in_features
# replace the pre-trained head with a new one
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)

在上面的代码中,我们首先加载了一个预训练的轻量级网络模型MobileNetV2模型,并取出了该模型的特征提取器部分。然后,我们将特征提取器的输出通道数设置为1280,以使其与Faster R-CNN模型兼容。

接下来,我们定义了一个锚点生成器和一个区域兴趣池,它们将在Faster R-CNN模型中用于生成候选区域和对这些候选区域进行分类和回归。最后,我们将Faster R-CNN模型的分类器替换为一个新的分类器,该分类器具有用户定义的类别数。

3. 定义损失函数

我们将使用Faster R-CNN模型默认的损失函数,即Multi-task loss多任务损失。Multi-task loss由两个部分组成:分类损失和回归损失。分类损失用于衡量模型对候选区域进行分类的准确性,回归损失用于衡量模型对候选区域进行回归的准确性。

下面是定义损失函数的代码:

import torch.nn as nn
import torch.optim as optim

# move model to the right device
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)

4. 定义优化器

我们将使用随机梯度下降(SGD)优化器(相信熟悉深度学习的你,一定耳熟能详了这个算法)来训练模型。我们还将使用学习率调度程序来自适应地调整学习率,以提高模型的性能。

下面是定义优化器和学习率调度器的代码:

# construct an optimizer
params = [p for p in model.parameters() if p.requires_grad]
optimizer = torch.optim.SGD(params, lr=0.005,
                            momentum=0.9, weight_decay=0.0005)
# and a learning rate scheduler
lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer,
                                               step_size=3,
                                               gamma=0.1)

在上面的代码中,我们首先获取所有需要进行梯度更新的模型参数,并将它们传递给SGD优化器。我们还指定了学习率、动量和权重衰减等参数。

然后,我们定义了一个学习率调度器,它将在每个epoch结束时自适应地调整学习率。我们将使用StepLR调度程序,每3个epoch将学习率降低10倍。

5. 训练和验证模型

我们将使用PyTorch提供的训练和验证循环来训练和验证我们的模型。

下面是训练和验证模型的代码:

from engine import train_one_epoch, evaluate

# let's train it for 10 epochs
num_epochs = 10

for epoch in range(num_epochs):
    # train for one epoch, printing every 10 iterations
    train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq=10)
    # update the learning rate
    lr_scheduler.step()
    # evaluate on the test dataset
    evaluate(model, data_loader_test, device=device)

在上面的代码中,我们首先指定了要训练的epoch数。然后,我们使用for循环迭代训练和验证模型。

在每个epoch中,我们使用train_one_epoch函数训练模型,该函数将模型、优化器、数据加载器、设备和当前epoch作为输入,并打印每10个batch的训练损失和时间。

在每个epoch结束时,我们使用学习率调度器自适应地调整学习率。然后,我们使用evaluate函数在验证集上评估模型,该函数将模型、数据加载器和设备作为输入,并打印出平均精度和平均损失。

最后,我们完成了目标检测微调的教程。您可以将本教程中的代码与自己的数据集一起使用,以进行目标检测微调。

6. 保存和加载模型

在训练和验证模型之后,我们可能希望保存模型以备将来使用。我们可以使用PyTorch提供的save函数将模型保存到磁盘上。

下面是保存模型的代码:# save the model to disk
torch.save(model.state_dict(), "model.pth")

在上面的代码中,我们使用state_dict函数获取模型的状态字典,并使用torch.save函数将其保存到名为"model.pth"的文件中。

如果我们希望在将来加载模型,我们可以使用load_state_dict函数从磁盘上的文件中加载模型的状态字典。

下面是加载模型的代码:

# create an instance of the model and load the state dict
model = get_instance_segmentation_model(num_classes)
model.load_state_dict(torch.load("model.pth"))

在上面的代码中,我们首先使用get_instance_segmentation_model函数创建一个模型实例。然后,我们使用load_state_dict函数从名为"model.pth"的文件中加载模型的状态字典。

7. 结论

本教程介绍了如何使用PyTorch进行目标检测微调。我们首先了解了目标检测的基本概念和检测器的架构。然后,我们介绍了如何使用PyTorch构建目标检测模型,并使用预训练的模型进行微调。最后,我们介绍了如何保存和加载模型。

PyTorch提供了强大的工具和库,使得目标检测微调变得非常容易。希望这个教程能够帮助您进一步探索目标检测领域,并构建更准确和高效的检测器。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值