PSP-Net的理解(多尺度特征融合分割)

Pyramid Scene Parsing Network

收录:CVPR 2017 (IEEE Conference on Computer Vision and Pattern Recognition)

原文地址: PSPNet

代码:

    pspnet-github
    Keras
    tensorflow

效果图:

mark
Abstract

本文提出的金字塔池化模块( pyramid pooling module)能够聚合不同区域的上下文信息,从而提高获取全局信息的能力。实验表明这样的先验表示(即指代PSP这个结构)是有效的,在多个数据集上展现了优良的效果。
Introduction

场景解析(Scene Parsing)的难度与场景的标签密切相关。先大多数先进的场景解析框架大多数基于FCN,但FCN存在的几个问题:

mark

    Mismatched Relationship:上下文关系匹配对理解复杂场景很重要,例如在上图第一行,在水面上的大很可能是“boat”,而不是“car”。虽然“boat和“car”很像。FCN缺乏依据上下文推断的能力。
    Confusion Categories: 许多标签之间存在关联,可以通过标签之间的关系弥补。上图第二行,把摩天大厦的一部分识别为建筑物,这应该只是其中一个,而不是二者。这可以通过类别之间的关系弥补。
    Inconspicuous Classes:模型可能会忽略小的东西,而大的东西可能会超过FCN接收范围,从而导致不连续的预测。如上图第三行,枕头与被子材质一致,被识别成到一起了。为了提高不显眼东西的分割效果,应该注重小面积物体。

总结这些情况,许多问题出在FCN不能有效的处理场景之间的关系和全局信息。本论文提出了能够获取全局场景的深度网络PSPNet,能够融合合适的全局特征,将局部和全局信息融合到一起。并提出了一个适度监督损失的优化策略,在多个数据集上表现优异。

本文的主要贡献如下:

    提出了一个金字塔场景解析网络,能够将难解析的场景信息特征嵌入基于FCN预测框架中
    在基于深度监督损失ResNet上制定有效的优化策略
    构建了一个实用的系统,用于场景解析和语义分割,并包含了实施细节

Related Work

受到深度神经网络的驱动,场景解析和语义分割获得了极大的进展。例如FCN、ENet等工作。许多深度卷积神经网络为了扩大高层feature的感受野,常用dilated convolution(空洞卷积)、coarse-to-fine structure等方法。本文基于先前的工作,选择的baseline是带dilated network的FCN。

大多数语义分割模型的工作基于两个方面:

    一方面:具有多尺度的特征融合,高层特征具有强的语义信息,底层特征包含更多的细节。
    另一方面:基于结构预测。例如使用CRF(条件随机场)做后端细化分割结果。

为了充分的利用全局特征层次先验知识来进行不同场景理解,本文提出的PSP模块能够聚合不同区域的上下文从而达到获取全局上下文的目的。
Architecture
Pyramid Pooling Module

前面也说到了,本文的一大贡献就是PSP模块。

在一般CNN中感受野可以粗略的认为是使用上下文信息的大小,论文指出在许多网络中没有充分的获取全局信息,所以效果不好。要解决这一问题,常用的方法是:

    用全局平均池化处理。但这在某些数据集上,可能会失去空间关系并导致模糊。
    由金字塔池化产生不同层次的特征最后被平滑的连接成一个FC层做分类。这样可以去除CNN固定大小的图像分类约束,减少不同区域之间的信息损失。

论文提出了一个具有层次全局优先级,包含不同子区域之间的不同尺度的信息,称之为pyramid pooling module。

mark

该模块融合了4种不同金字塔尺度的特征,第一行红色是最粗糙的特征–全局池化生成单个bin输出,后面三行是不同尺度的池化特征。为了保证全局特征的权重,如果金字塔共有N个级别,则在每个级别后使用的卷积将对于级别通道降为原本的1/N。再通过双线性插值获得未池化前的大小,最终concat到一起。

金字塔等级的池化核大小是可以设定的,这与送到金字塔的输入有关。论文中使用的4个等级,核大小分别为。
整体架构

在PSP模块的基础上,PSPNet的整体架构如下:

mark

    基础层经过预训练的模型(ResNet101)和空洞卷积策略提取feature map,提取后的feature map是输入的1/8大小
    feature map经过Pyramid Pooling Module得到融合的带有整体信息的feature,在上采样与池化前的feature map相concat
    最后过一个卷积层得到最终输出

PSPNet本身提供了一个全局上下文的先验(即指代Pyramid Pooling Module这个结构),后面的实验会验证这一结构的有效性。
基于ResNet的深度监督网络

论文用了一个很“玄学”的方法搞了一个基础网络层,如下图:

mark

在ResNet101的基础上做了改进,除了使用后面的softmax分类做loss,额外的在第四阶段添加了一个辅助的loss,两个loss一起传播,使用不同的权重,共同优化参数。后续的实验证明这样做有利于快速收敛。
Experiment

论文在ImageNet scene parsing challenge 2016, PASCAL VOC 2012,Cityscapes 三个数据集上做了实验。

训练细节:
项目     设置
学习率     采用“poly”策略,即,衰减动量设置为0.9 and 0.0001
迭代次数     ImageNet上设置150K,PASCAL VOC设置30K,Cityscapes设置90K
数据增强     随机翻转、尺寸在0.5到2之间缩放、角度在-10到10之间旋转、随机的高斯滤波
batchsize     batch很重要,设置batch=16(这很吃显存啊~)
训练分支网络     设置辅助loss的权重为0.4
平台     Caffe
ImageNet scene parsing challenge 2016

    测试不同配置下的ResNet的性能,找到比较好的预训练模型:
    mark

    ResNet50-Baseline: 基于FCN的ResNet50结构,带空洞卷积的baseline
    ResNet50+B1+MAX:只带的平均池化,池化后做通道降维

可以看到做平均池化的都比最大池化效果要好,最后将多个操作结合得到最终最好的效果。

测试辅助loss的影响:
mark

实验都是以ResNet50-Baseline为基准,最后以为最佳。

测试预训练模型的深度:
mark

mark
可以看到在测试的{50,101,152,269}这四个层次的网络中,网络越深,效果越好。

多种技巧融合
mark
带有DA即数据增强,AL即带辅助loss,PSP带金字塔池化模块,MS多尺度。

在IamgeNet上的表现:
mark
PASCAL VOC 2012

mark

可以看到在MS-COCO上预训练过的效果最好。
Cityscapes

mark

在Cityscapes上表现也是很不错的。
Conclusion

论文在结构上提供了一个pyramid pooling module,在不同层次上融合feature,达到语义和细节的融合。 模型的性能表现很大,但感觉主要归功于一个良好的特征提取层。在实验部分讲了很多训练细节,但还是很难复现,这里值得好好推敲一下。
https://blog.csdn.net/u011974639/article/details/78985130
 

好的,这是一个比较复杂的任务,需要分步骤来完成。首先需要了解EfficientNetPSPNet的结构和原理,然后再进行迁移。 EfficientNet是一种高效的卷积神经网络,它采用了一种称为Compound Scaling的方法来同时缩放模型的深度、宽度和分辨率,从而在保持准确性的同时,显著减少了模型的计算复杂度。PSPNet则是一种用于语义分割的神经网络,它通过引入金字塔池化模块来增强模型对不同尺度的信息的理解和表示能力。 下面是将EfficientNet迁移至PSPNet的步骤: 1. 导入所需的库和模块,包括PyTorch、EfficientNetPSPNet: ```python import torch import torch.nn as nn from efficientnet_pytorch import EfficientNet from models.pspnet import PSPNet ``` 2. 定义EfficientNet的基本结构,包括卷积层、BN层和激活函数: ```python class EfficientNetEncoder(nn.Module): def __init__(self, backbone='efficientnet-b0'): super(EfficientNetEncoder, self).__init__() self.backbone = EfficientNet.from_pretrained(backbone) self.conv1 = self.backbone._conv_stem self.bn1 = self.backbone._bn0 self.act1 = self.backbone._swish self.blocks = self.backbone._blocks self.conv2 = self.backbone._conv_head self.bn2 = self.backbone._bn1 self.act2 = self.backbone._swish ``` 3. 定义PSPNet的金字塔池化模块和解码器部分: ```python class PSPDecoder(nn.Module): def __init__(self, in_channels, out_channels): super(PSPDecoder, self).__init__() self.conv1 = nn.Conv2d(in_channels, in_channels // 4, 1) self.bn1 = nn.BatchNorm2d(in_channels // 4) self.act1 = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(in_channels // 4, out_channels, 3, padding=1) self.bn2 = nn.BatchNorm2d(out_channels) self.act2 = nn.ReLU(inplace=True) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.act1(x) x = self.conv2(x) x = self.bn2(x) x = self.act2(x) return x class PSPNet(nn.Module): def __init__(self, n_classes=21, sizes=(1, 2, 3, 6), psp_size=2048, deep_features_size=1024): super(PSPNet, self).__init__() self.feats = EfficientNetEncoder() self.psp = PSPModule(psp_size, sizes) self.drop_1 = nn.Dropout2d(p=0.3) self.up_1 = PSPDecoder(psp_size // len(sizes) + deep_features_size, 512) self.drop_2 = nn.Dropout2d(p=0.3) self.up_2 = PSPDecoder(512, 256) self.drop_3 = nn.Dropout2d(p=0.3) self.up_3 = PSPDecoder(256, 128) self.drop_4 = nn.Dropout2d(p=0.3) self.final = nn.Sequential( nn.Conv2d(128, n_classes, kernel_size=1), nn.LogSoftmax(dim=1) ) def forward(self, x): f = self.feats(x) p = self.psp(f) p = self.drop_1(p) p = self.up_1(torch.cat([p, f[-1]], dim=1)) p = self.drop_2(p) p = self.up_2(p) p = self.drop_3(p) p = self.up_3(p) p = self.drop_4(p) return self.final(p) ``` 4. 将EfficientNet特征提取部分和PSPNet的解码器部分进行融合: ```python class EfficientNetPSPNet(nn.Module): def __init__(self, n_classes): super(EfficientNetPSPNet, self).__init__() self.encoder = EfficientNetEncoder() self.decoder = PSPNet(n_classes=n_classes) def forward(self, x): x = self.encoder(x) x = self.decoder(x) return x ``` 现在我们已经完成了EfficientNetPSPNet的迁移,可以像下面这样使用它: ```python model = EfficientNetPSPNet(n_classes=21) x = torch.rand(2, 3, 512, 512) y = model(x) print(y.size()) # torch.Size([2, 21, 512, 512]) ``` 希望这个例子能够对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值