【目标检测】FPN

Feature Pyramid Networks for Object Detection

摘要

5 FPS on a GPU(有点慢)

1. 引言

d 为FPN,速度和 b、c相似,但是更精准。图中,蓝色框表示特征图,粗的框表示语义强壮的特征。

These pyramids are scale-invariant in the sense that an object’s scale change is offset by shifting its level in the pyramid. Intuitively, this property enables a model to detect objects across a large range of scales by scanning the model over both positions and pyramid levels.

上文的意思是:每层特征金字塔的尺度是固定的,一个目标的尺度变化通过金字塔的层级来抵消。直观地, 该属性使模型能够通过在位置和金字塔层级上扫描模型来检测大范围尺度的物体。

上图中,a是图像金字塔特征,在手工特征时代大量使用,但是很挑剔,像DPM目标检测器需要密集尺度的采样才能获得好的结果。

手工特征被ConvNets取代。除了能够表示更高级别的语义,ConvNets对于尺度变化也更加稳健,从而有助于从单一输入尺度(图b)上计算的特征进行识别。

但即使有了这种稳健性, 仍然需要金字塔得到最准确的结果。最近在 ImageNet和COCO 检测挑战中的所有顶级项目都使用 featurized image pyramids上的多尺度测试。featurizing image pyramids 的每个层次的原理优势是它产生了一个多尺度特征表示, 其中所有level都在语义上很强, 包括高分辨率level。

featurized image pyramids缺点:推理时间增加,由于内存无法 end-to-end 训练,只能test 时候用,这造成了训练和测试时候推理的不一致。所以Fast 和 Faster R-CNN 默认不使用。

但是,featurized image pyramids 并不是计算多尺度特征表示的唯一方法。深层ConvNet逐层计算特征层级,而对于下采样层,特征层级具有天然的多尺度金字塔形状。这种网络特征层级产生不同空间分辨率的特征映射,但引入了由不同深度引起的较大的语义鸿沟。高分辨率映射具有损害其目标识别表示能力的低级特征。

 Single Shot Detector (SSD)是第一次尝试使用 ConvNet 的金字塔特征层, 就好像它是一个 featurized image pyramid (图 1 (c))。理想情况下, SSD 风格的金字塔将重用在正向传递中计算的不同层的多尺度特征映射, 并且没有成本。但为了避免使用低 level 特征 SSD 放弃重用已经计算的层, 取而代之的是在网络中从高处开始构建金字塔 (例如, conv4_3 of VGG nets), 然后添加几个新层。因此, 它错失了重用特征层的高分辨率映射的机会。我们表明, 这些对检测小物体很重要

本文的目标是自然地利用 ConvNet 的特征层的金字塔形状, 同时在所有尺度创建一个具有强烈语义的特征金字塔。为了实现这一目标, 我们依赖于一种架构, 它将低分辨率、语义强的特征高分辨率、语义较弱的特征结合起来, 通过自上而下的途径和横向连接 (图 1 (d))。其结果是一个特征金字塔, 它在所有level都具有丰富的语义, 并且从单一输入图像比例快速构建。换言之, 我们展示了如何创建网络内特征金字塔, 可用于替换 featurized image pyramids而不牺牲表达能力、速度或内存。

采用top-down and skip connections的类似体系结构在最近的研究中很受欢迎。他们的目标是制作细粒度分辨率的a single high-level feature map , 在上面进行预测 (图2顶部)。相反, 我们的方法利用架构作为一个特征金字塔, 在每个level上独立地进行预测 (如物体检测) (图2底部)。我们的模型与一个 featurized image pyramid相似, 这没有在那些工作中探索。

 在消融实验中, 我们发现, 对于bounding box proposals , FPN 显著增加Average Recall (AR) 8.0 点; 对于物体检测, 它提高了COCO-style Average Precision (AP) 2.3 点和PASCAL-style AP 3.8 点, 超越了一个强大的单尺度 在ResNets上 Faster R-CNN 的 baseline 。我们的方法也很容易扩展到mask proposals, 并改进了实例分割AR 并且速度超越了严重依赖于 image pyramids 的state-of-the-art方法。

此外,我们的金字塔结构可以通过所有的尺度进行end-to-end的训练,并且在训练/测试时一样使用,而这样使用 image pyramids 是内存-不可行的。因此,FPN 能够实现比所有现有的最先进的方法更高的精度。此外,这种改进是在不增加测试时间的情况下实现的。

Feature Pyramid Networks

 对于 ResNets, 我们使用每个阶段的最后一个residual block的特征激活输出。我们将这些最后一个residual block的输出表示为 conv2、conv3、conv4 和 conv5 输出的 {C2、C3、C4、C5}, 并注意到它们在输入图像方面具有 {4、8、16、32} 像素的步长。由于内存占用量大, 我们不包括 conv1 到金字塔中。

自顶而下的特征通过粗糙的上采样幻化出了更高分辨率的特征,这些来自特征金字塔上方的特征语义更强。然后 这些特征 通过横向连接增强了 那些自下而上 的特征。每个横向连接都融合了自下而上路径自顶向下路径的相同空间大小的特征图。自下而上的特征映射是低级语义,  它的激活更加精确的局部化,因为它被下采样的次数更少。

图3显示了构建自上而下特征映射的构建块。用一个粗糙分辨率的特征图, 我们上采样的空间分辨率的系数为 2 (使用简单的最近邻上采样)。然后, 上采样特征图与相应的自底向上特征图 (通过1×1卷积层来减少通道尺寸) 合并, 通过element-wise的加法。此过程将被迭代, 直到生成最佳分辨率映射为止。要开始迭代, 我们只需在 C5 上附加一个1×1卷积层即可生成粗糙分辨率映射。最后, 我们在每个合并的映射上追加 3 x 3 卷积, 以生成最终的特征映射, 这是为了减少上采样的混淆效果。这最后一组特征映射称为 {P2、P3、P4、P5}, 对应于分别为相同空间大小的 {C2、C3、C4、C5}。

由于金字塔的所有level都使用共享分类器/回归器, 就像在传统的 featurized image pyramids中一样, 我们在所有特征映射中固定了特征维度 (通道数, 表示为 d)。我们在本文中设置了 d = 256, 因此所有额外的卷积层都有256通道输出。在这些额外的层中没有non-linearities , 我们经验中发现它有轻微的影响。

简单性是我们设计的核心, 我们发现我们的模型对许多设计选择是健壮的。我们已经试验了更复杂的block (例如, 使用多层residual block 作为连接), 并观察到了稍微更好的结果。设计更好的连接模块不是本文的重点, 所以我们选择了上面描述的简单设计。

结论

我们提供了一个简洁的框架,用于在卷积神经网络中构建feature pyramids。我们的方法显示了几个强大的基线和竞争获胜者的显著改进。因此,它为feature pyramids的研究和应用提供了一种实用的解决方案,而不需要计算image pyramids。最后,我们的研究表明,尽管深度卷积神经网络具有很强的表征能力和对尺度变化的隐式鲁棒性,但使用金字塔表示显式地解决多尺度问题仍然至关重要。

参考:

http://openaccess.thecvf.com/content_cvpr_2017/papers/Lin_Feature_Pyramid_Networks_CVPR_2017_paper.pdf

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用Swin Transformer、FPN和PAN进行目标检测的代码示例: 首先,我们需要安装必要的库和工具: ```bash pip install torch torchvision opencv-python tqdm ``` 接下来,我们需要下载COCO数据集和预训练的Swin Transformer模型。我们可以使用以下命令来下载它们: ```bash mkdir data cd data # Download COCO dataset wget http://images.cocodataset.org/zips/train2017.zip wget http://images.cocodataset.org/zips/val2017.zip wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip unzip train2017.zip unzip val2017.zip unzip annotations_trainval2017.zip rm train2017.zip val2017.zip annotations_trainval2017.zip # Download pre-trained Swin Transformer model mkdir models cd models wget https://github.com/SwinTransformer/storage/releases/download/v1.0.0/swin_tiny_patch4_window7_224.pth ``` 接下来,我们可以编写一个Python脚本来训练我们的模型。以下是一个简单的示例: ```python import torch import torchvision import torch.nn as nn import torch.optim as optim import torchvision.transforms as transforms from torch.utils.data import DataLoader from torchvision.datasets import CocoDetection from swin_transformer import SwinTransformer from fpn import FPN from pan import PAN # Define hyperparameters batch_size = 16 num_epochs = 10 lr = 1e-4 # Define data transforms transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # Load COCO dataset train_dataset = CocoDetection(root='./data', annFile='./data/annotations/instances_train2017.json', transform=transform) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # Define Swin Transformer model swin = SwinTransformer() swin.load_state_dict(torch.load('./data/models/swin_tiny_patch4_window7_224.pth')) # Define FPN and PAN models fpn = FPN(in_channels=[96, 192, 384, 768], out_channels=256) pan = PAN(in_channels=[256, 256, 256, 256], out_channels=256) # Define detection head detection_head = nn.Sequential( nn.Conv2d(256, 256, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.Conv2d(256, 4, kernel_size=1), nn.Sigmoid() ) # Define optimizer and loss function optimizer = optim.Adam(list(swin.parameters()) + list(fpn.parameters()) + list(pan.parameters()) + list(detection_head.parameters()), lr=lr) criterion = nn.MSELoss() # Train the model for epoch in range(num_epochs): for images, targets in train_loader: # Forward pass features = swin(images) fpn_features = fpn(features) pan_features = pan(fpn_features) output = detection_head(pan_features[-1]) # Compute loss loss = criterion(output, targets) # Backward pass and update weights optimizer.zero_grad() loss.backward() optimizer.step() # Print statistics print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) ``` 在上面的代码中,我们首先加载了预训练的Swin Transformer模型,并使用它提取特征。然后,我们将这些特征输入到FPN和PAN模型中,以生成具有不同分辨率的特征图。最后,我们使用一个简单的检测头来预测边界框。 在训练期间,我们使用均方误差(MSE)作为损失函数,并使用Adam优化器来更新模型的权重。 请注意,上面的代码仅提供了一个简单的示例,实际上,您可能需要进行一些其他的调整和修改,以便使其适用于您的具体任务和数据集。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理心炼丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值