可能是史上最详细-Faster RCNN Pytorch 复现全纪录

Faster RCNN复现

文章之前,我们先来明确检测类任务都在干些什么:

需求:

对图像中的特定种类目标做出分类,并求出目标在图像中所处的位置即最终需要的信息:

  • object-classes_name
  • object-position

在一般的检测任务中类别信息通常由索引代替,例如1-> apple,2 - > cat,3 - > dog,… > 而位置一般可以由两组坐标代替:> 矩形的左上角,右下角坐标(x1,y1,x2,y2)

Faster R-CNN作为两阶段检测网络发展中最重要的一个网络,基本可以视为检测任务的里程碑性成果。

延伸扩展的MaskRCNN,CascadeRCNN都成为了2019年这个时间点上除了各家AI大厂私有网络范围外,支撑很多业务得以开展的基础。所以,Pytorch为基础来从头复现FasterRCNN网络是非常有必要的,其中包含了太多的招数和理论中不会包括的先验知识。

甚至,以Faster RCNN为基础去复现其他的检测网络 所需要的精力和时间都会大大降低

我们的目标:用最简洁,最贴合原文得写法复现Resnet - Faster R-CNN

注:> > 本文中的代码为结构性示例的代码片段,不能够复制粘贴直接运行

架构

VGG16-19因为参数的急剧膨胀和深层结构搭建导致参数量暴涨,网络在反向传播过程中要不断地传播梯度,而当网络层数加深时,梯度在逐层传播过程中会逐渐衰减,导致无法对前面网络层的权重进行有效的调整。

因此vgg19就出现了它的局限性。

而在之后提出的残差网络中,加入了短连接为梯度带来了一个直接向前面层的传播通道,缓解了梯度的减小问题,同时,将整个网络的深度加到了100层+,甚至后来的DenseNet出现了实用的200层+网络。并且大量使用了1 * 1卷积来降低参数量因此本文将尝试ResNet 101 +FasterRCNN,以及衔接DenseNet和FasterRCNN的可能性。

从以上图中我们可以看出Faster R-CNN除了作为特征提取部分的主干网络,剩下的最关键的也就是以下部分

  • RPN`
  • RPN LossFunction
  • ROI Pooling
  • Faster-R-CNN Loss Function

也就是说我们的复现工作要着重从这些部分开始。现在看到的最优秀的复现版本应该是Jianwei Yang page

本文的代码较多的综合了多种写法,以及pytorch标准结构的写法

0.整体流程

先来看看代码(只是大概的看一下就行):

#################################非Resnet版本只看看基本结构就可以
class FasterRCNN(nn.Module):
    n_classes = 21
    classes = np.asarray(['__background__',
                       'aeroplane', 'bicycle', 'bird', 'boat',
                       'bottle', 'bus', 'car', 'cat', 'chair',
                       'cow', 'diningtable', 'dog', 'horse',
                       'motorbike', 'person', 'pottedplant',
                       'sheep', 'sofa', 'train', 'tvmonitor'])
    PIXEL_MEANS = np.array([[[102.9801, 115.9465, 122.7717]]])
    SCALES = (600,)
    MAX_SIZE = 1000

    def __init__(self, classes=None, debug=False):
        super(FasterRCNN, self).__init__()

        if classes is not None:
            self.classes = classes
            self.n_classes = len(classes)

        self.rpn = RPN()
        self.roi_pool = RoIPool(7, 7, 1.0/16)
        self.fc6 = FC(512 * 7 * 7, 4096)
        self.fc7 = FC(4096, 4096)
        self.score_fc = FC(4096, self.n_classes, relu=False)
        self.bbox_fc = FC(4096, self.n_classes * 4, relu=False)

        # loss
        self.cross_entropy = None
        self.loss_box = None



    @property
    def loss(self):
        return self.cross_entropy + self.loss_box * 10

    def forward(self, im_data, im_info, gt_boxes=None, gt_ishard=None, dontcare_areas=None):
        features, rois = self.rpn(im_data, im_info, gt_boxes, gt_ishard, dontcare_areas)

        if self.training:
            roi_data = self.proposal_target_layer(rois, gt_boxes, gt_ishard, dontcare_areas, self.n_classes)
            rois = roi_data[0]

        # roi pool
        pooled_features = self.roi_pool(features, rois)
        x = pooled_features.view(pooled_features.size()[0], -1)
        x = self.fc6(x)
        x = F.dropout(x, training=self.training)
        x = self.fc7(x)
        x = F.dropout(x, training=self.training)

        cls_score = self.score_fc(x)
        cls_prob = F.softmax(cls_score)
        bbox_pred = self.bbox_fc(x)

        if self.training:
            self.cross_entropy, self.loss_box = self.build_loss(cls_score, bbox_pred, roi_data)

        return cls_prob, bbox_pred, rois

这段代码并不是完整定义,只显示了主要流程,辅助性,功能性的方法全部被省略。
结构也被大大简化
当我们以数据为线索则会产生以下的流程
在这里插入图片描述

我们在主干网络中可以清晰地看到,向前按照什么样的顺序执行了整个流程(just take a look)

值得注意的是,在以上执行流程中,有些过程需要相应的辅助函数来进行
比如loss的构建,框生成等等,都需要完备的函数库来辅助进行。

以上流程图 ,以及本文的叙述顺序与线索,都是以数据为依托的,明确各个部分数据之间的计算
输入输出信息是非常重要的

初始训练数据包含了:

1.DataLoader

数据加载部分十分自然地,要输入我们的数据集,我们这篇文章使用按最常用的

coco2014/17标准

pascal VOC标准

自定义数据集标准

全部部分当然不能展现 但是我们会在开源项目中 演示Voclike数据集,以及自定义数据集如何方便的被加载->开源-快速训练工具(未完成)

在本文中为了关注主旨我们只介绍自定义数据集和VocLike数据集的加载过程

Data2Dataset

数据的原始形式,当然是以图片为主
我们以一张图为例.
在这里插入图片描述
使用labelme标注之后
在这里插入图片描述
保存之后软件就会自动生成例如:

{
   
    "version": "3.4.1",
    "flags": {
   },
    "shapes": [
        {
   
            "label": "dog",
            "line_color": null,
            "fill_color": null,
            "points": [
                [
                    7,
                    144
                ],
                [
                    307,
                    588
                ]
            ],
            "shape_type": "rectangle"
        },
        ......
        {
   
            "label": "dog",
            "line_color": null,
            "fill_color": null,
            "points": [
                [
                    756,
                    130
                ],
                [
                    974,
                    507
                ]
            ],
            "shape_type": "rectangle"
        }
    ],
    "lineColor": [
        0,
        255,
        0,
        128
    ],
    "fillColor": [
        255,
        0,
        0,
        128
    ],
    "imagePath": "timg.jpeg",
    "imageData": "此处为base64编码过得图像数据"
}

还有labelimg xml标准的数据样本

<annotation>
	<folder>图片</folder>
	<filename>timg.jpeg</filename>
	<path>/home/winshare/图片/timg.jpeg</path>
	<source>
		<database>Unknown</database>
	</source>
	<size>
		<width>1000</width>
		<height>612</height>
		<depth>3</depth>
	</size>
	<segmented>0</segmented>
	<object>
		<name>dog</name>
		<pose>Unspecified</pose>
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>
			<xmin>9</xmin>
			<ymin>163</ymin>
			<xmax>309</xmax>
			<ymax>584</ymax>
		</bndbox>
	</object>
....
	<object>
		<name>dog</name>
		<pose>Unspecified</pose>
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>
			<xmin>748</xmin>
			<ymin>142</ymin>
			<xmax>977</xmax>
			<ymax>508</ymax>
		</bndbox>
	</object>
</annotation>

以及yolo标准的bbox

class_id box
0 0.159000 0.610294 0.300000 0.687908
0 0.346000 0.433824 0.216000 0.638889
0 0.491500 0.449346 0.191000 0.588235
0 0.650000 0.511438 0.246000 0.614379
0 0.863000 0.535948 0.230000 0.588235

yolo的box值最终会由下面的方法转换为标准的框数据(xywh)

def convert(size, box):  # 归一化操作
    #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)
Dataset2Dataloader

很多对Faster RCNN复现的版本中,标准的数据加载流程没有被固定化,所以数据被以各种datalayer ,roidb等等方法包装,Pytorch0.4之后,实质上已经出现了最标准化的数据输入形式
即:

transfrom
Data
Datalist
Dataset
Dataloader

一般情况下数据从原始形式,也就是上一节获取到的图片以及label的类别坐标信息。
我们假设以字典单位来承载这个数据单元

Fast R-CNN是一种基于区域提议的目标检测算法,它是目标检测领域的一个重要里程碑。PyTorch是一个流行的深度学习框架,你可以通过以下步骤来复现Fast R-CNN模型: 1. **安装依赖**:首先,你需要安装必要的库,如`torch`, `torchvision`, `numpy`, `matplotlib`等。如果你尚未安装,可以使用以下命令: ``` pip install torch torchvision numpy matplotlib ``` 2. **数据准备**:Fast R-CNN通常使用COCO数据集,你需要下载并处理数据,将其转化为模型所需的格式。你可以使用`cocoapi`工具和`torch.utils.data.Dataset`类来创建数据加载器。 3. **网络结构搭建**:Fast R-CNN的核心是Faster R-CNN架构,它包含一个卷积神经网络(CNN)用于特征提取(如VGG、ResNet等),加上Region Proposal Network (RPN) 和 RoI Pooling 层。在PyTorch中,你可以使用`torch.nn`模块构建这些组件。 4. **模型训练**:定义损失函数(如分类损失和回归损失)、优化器以及训练循环。使用`nn.Module`作为基础,编写自定义的`FastRCNN`类,并调用`forward()`方法计算预测结果。 5. **训练和评估**:将数据加载到`DataLoader`,然后迭代训练过程。每轮迭代包括前向传播、反向传播和优化步骤。评估阶段则会用验证集测试模型性能。 6. **代码示例**:在GitHub上能找到很多Fast R-CNN的PyTorch实现例子,例如官方的`maskrcnn-benchmark`仓库就有完整代码。你可以参考那些代码片段来理解并调整。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值