FPN个人理解小结

FPN

特征金字塔是目标检测识别系统中的一个基础组件,但是最近深度目标检测器避免使用金字塔的表示方式,部分原因是因为特征金字塔是强计算和强内存的,计算非常昂贵。

原有的目标检测算法通常都是只采用顶层特征做检测,原因是网络顶层特征的语义信息比较丰富。然而,虽顶层特征的语义信息丰富,但其中的目标位置信息却比较粗略,不利于目标包围框的准确定位;相反,虽然底层特征的语义信息比较少,但其中目标的位置信息却非常准确。

再次背景下,作者利用深度卷积神经网络固有的多尺度、多层级的金字塔结构去构建特征金字塔网络

FPN构建了一个自顶向下,横向连接的结构,以此来构建一个多尺度,高级语义的特征图

现有的几种特征金字塔结构

在这里插入图片描述

  1. 图像金字塔来构建特征金字塔,其中每一个特征独立的在每一个图片尺度上计算。缺点:慢
  2. 只采用单一尺度的特征图用于快速检测,这里只使用了最高层级的特征图进行预测
  3. 由卷积网络计算得到的特征金字塔层次结构,分层预测,例如SSD
  4. FPN方式:和2,3速度相同,但是使得每一层有更强的语义信息

注:其中蓝色线条的粗细表示了语义特征的强弱

建立在图像金字塔上的特征金字塔

​ 在识别任务中,特征工程大量的被深度卷积网络计算的特征所替代,除了能够表示更高层次的语义外,深度卷积网络对尺度规模也更健壮,因此有助于从单一输入尺度上计算的特征进行识别。
​ 其中图像金字塔的每一层的特征的优势是其产生的特征每一层的语义信息都是很强的,包括高分辨率的低层。其缺点也很明显,无法做到实时监测,并且在图片金字塔训练深度的端到端的网络是不可行的,由于内存的局限性。图像金字塔只有在测试时间使用,这也导致了训练和测试的不连续。由此,在fast rcnn和faster rcnn中并没有使用基于图片的特征金字塔。
​ 但是,图片金字塔并不是唯一构建多尺度特征表示的方式,深层卷积网络逐层计算特征层次结构,通过下采样层,特征层次结构具有内在的多尺度金字塔形状。这种网络内的特征层次结构产生了不同空间分辨率的特征图,但由于深度不同,引入了很大的语义差距。这种高分辨率的特征图有低水平的特征,这可能会导致损失目标识别的表现能力。
​ SSD是以上方式的尝试,理想情况下,SSD金字塔在前向传播的过程中,将会重用来自不同特征层的特征图,这时便没有多余的消耗。但是也有明显的缺点,避免使用低层次的特征,SSD将其丢弃,从网络的高层开始构建金字塔网络结构。它错过了重用特征层次结构的高分辨率图的机会。

作者目标

​ 利用深度网络特征层次结构的金字塔形状,创建一个特征金字塔,使得每一尺度都有很强的语义信息。

现有情况:

低特征层:高分辨率,语义不强,利于小目标检测

高特征层:低分辨率,语义强

思想:利用低层次的高分辨率和高层次的强语义进行融合

在这里插入图片描述

对比跳连接和作者思路:

图一目标: 他们的目标是生成一个高分辨率的单一高级特征图,并据此进行预测

图二:利用上采样和横向连接结构构建特征金字塔,在每一层独立的进行预测,实现语义从低到高,建立一个高语义的特征图像金字塔,并进行预测。可以在所有尺度上达到端到端,并且保持训练和测试连续,这是使用图片金字塔所达不到的。

FPN主干

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TX3vJwhf-1631257292961)(images/image-20210910144347352.png)]

自底向上:即深度卷积网络主干前向传播的过程,它计算一个由多个尺度的特征图组成的特征层次结构,有许多层产生相同大小的输出特征图,将其视为在网络的同一个阶段,将每个阶段定义为一个金字塔层级,选择该阶段的最后一层,作为输出,由于其每个阶段的最后一层拥有最强的语义信息。

ResNet:

将每一个block视为一个stage,将stage的最后一层进行输出,其中[c2,c3,c4,c5]对应网络的[2,3,4,5]的输出。其中每层的步幅为[4,8,16,32]

自顶向下,侧连接高层次特征图与低层次特征图融合

  1. 自上而下路径将从主干网络提取到的最强语义信息进行上采样,使得下层的空间信息更加粗糙但是语义更强。

  2. 再通过横向连接,将自底向上的时的特征图,与上采样得到的特征图进行融合,将其融合成一个特征图,横向链接的特征图具有低级特征,但是融合会使得其定位更加准确(其下采样次数较少)

1x1的卷积网络会使得该层变得的粗糙,并调整通道数为256.

3x3的卷积操作得到最终的特征图,这样会降低混叠效应

输出特征图对应的预测结果:[c2,c3,c4,c5]得到[p2,p3,p4,p5]

在这里插入图片描述
与faster rcnn结构类似:
在这里插入图片描述

Fpn–fixed

import math
from collections import OrderedDict

import torch
from torch import nn


class BasicBlock(nn.Module):

    def __init__(self, in_channel, out_channel):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channel, out_channel, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(out_channel)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2d(out_channel, out_channel, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(out_channel)

    def forward(self, x):

        residual = x
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))

        return self.relu(out + residual)


class ResNet(nn.Module):

    def __init__(self, layer):
        super(ResNet, self).__init__()
        self.inplanes = 64
        self.b1 = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False),
            nn.BatchNorm2d(64),
            nn.ReLU()
        )
        # backbone
        self.c2 = self._make_layer([64, 256], layer[0])
        self.c3 = self._make_layer([256, 512], layer[1])
        self.c4 = self._make_layer([512, 1024], layer[2])
        self.c5 = self._make_layer([1024, 2048], layer[3])

        self.max = nn.MaxPool2d(kernel_size=1)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()

    def _make_layer(self, planes, blocks):
        layer = []
        # 下采样
        layer.append(("down_sample", nn.Conv2d(self.inplanes, planes[1], kernel_size=1, stride=2, bias=False)))
        layer.append(("bn", nn.BatchNorm2d(planes[1])))
        layer.append(("relu", nn.ReLU()))

        self.inplanes = planes[1]

        for i in range(0, blocks):
            layer.append(("residual_{}".format(i), BasicBlock(self.inplanes, planes[1])))
        # print(layer)
        return nn.Sequential(OrderedDict(layer))

    def forward(self, x):
        out = self.b1(x)
        out = self.max(out)

        # 提取特征
        c2 = self.c2(out)
        c3 = self.c3(c2)
        c4 = self.c4(c3)
        c5 = self.c5(c4)

        return c2, c3, c4, c5


class Fpn(nn.Module):
    def __init__(self, layer):
        super(Fpn, self).__init__()
        self.backbone = ResNet(layer)
        # 改变通道数
        self.lateral2 = nn.Conv2d(256, 256, kernel_size=1)
        self.lateral3 = nn.Conv2d(512, 256, kernel_size=1)
        self.lateral4 = nn.Conv2d(1024, 256, kernel_size=1)
        self.lateral5 = nn.Conv2d(2048, 256, kernel_size=1)
        # last conv
        self.smooth = nn.Conv2d(256, 256, kernel_size=3)
        self.max = nn.MaxPool2d(kernel_size=1)

    def upSample(self, x, y):
        trans = nn.Upsample(scale_factor=2, mode="nearest")
        x = trans(x)
        return x + y

    def forward(self, x):
        c2, c3, c4, c5 = self.backbone(x)
        # fpn lateral
        c5 = self.lateral5(c5)
        c4 = self.lateral4(c4)
        c3 = self.lateral3(c3)
        c2 = self.lateral2(c2)
        # up sample smooth
        p5 = self.smooth(c5)
        p6 = self.max(p5)

        c4 = self.upSample(c5, c4)
        p4 = self.smooth(c4)

        c3 = self.upSample(c4, c3)
        p3 = self.smooth(c3)

        c2 = self.upSample(c3, c2)
        p2 = self.smooth(c2)

        return p2, p3, p4, p5, p6


net = Fpn([2, 2, 2, 2])
X = torch.rand(size=(1, 3, 224, 224))
print(net(X))
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPN (Feature Pyramid Network) 是一种用于目标检测和语义分割任务的神经网络架构。它由 Tsung-Yi Lin 等人在论文 "Feature Pyramid Networks for Object Detection" 中提出。 FPN 的主要目标是解决目标检测任务中的多尺度问题。传统的目标检测方法通常使用单一尺度特征图进行预测,这会导致小目标难以被准确检测到,而大目标则可能丢失细节信息。FPN 使用了一种金字塔式的特征提取方法,将不同尺度特征图进行融合,以便在不同尺度上进行目标检测。 FPN 的核心思想是通过建立自顶向下和自底向上的路径来构建特征金字塔。自底向上的路径从底层的高分辨率特征图开始,通过下采样操作逐渐降低分辨率,生成一系列特征图。自顶向下的路径则通过上采样操作逐渐增加分辨率,将高层语义信息传递到低层特征图中。最后,不同层级的特征图通过横向连接进行融合,形成一个多尺度特征金字塔。 在目标检测任务中,FPN 可以用作特征提取网络的一部分,提供多尺度特征图用于目标检测器的预测。它可以帮助检测器更好地适应不同尺度的目标,并提高检测精度。 在语义分割任务中,FPN 可以用于生成密集的像素级预测。通过将特征金字塔的不同层级特征图进行上采样和融合,可以得到高分辨率的语义分割结果。 总结来说,FPN 是一种有效解决多尺度问题的神经网络架构,可用于目标检测和语义分割任务。通过构建特征金字塔,提供多尺度特征图,从而提高模型在不同尺度上的表现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值