SppNet 多尺度训练

本文介绍了如何通过SPPNet在训练过程中处理不同尺度输入,解决了网络对图片尺寸变化的适应性问题。通过自适应卷积和多批次训练策略,实现跨尺度的模型优化。实例代码展示了如何在PyTorch中实现ResNet+SPPNet的多尺度训练流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SppNet 多尺度训练

 

原理网上非常多了,这里不再赘述。

感觉我看了很多博客,对我帮助较大的两个是:

https://blog.youkuaiyun.com/qq_42052229/article/details/90446073

https://zhuanlan.zhihu.com/p/42732128

 

使用过程中的重点总结:

 

1、网络目的确实是解决input的图像size大小不同的问题

但是:

训练的时候,我们需要一个batch一个batch的训练,这每一个batch的维度是相同的,意味着,这一个batch内的图像input size是相同的,才能训练。除非我们一张一张的训练,这样就会带来其他的很多问题。

所以在训练的时候,往往采用几种不同尺度的size的input,对同一个网络分别进行训练。

而测试时候,因为一般是一张一张的,所以可以任意size的图像input。

 

2、使用自适应卷积一样可以。

 

3、代码拆解,不一定要按照网上人家的来,最后全连接数量自己可以任意调整。

 

4、例子pytorch:

多尺度训练:不同尺度size分别跑一个epoch



if __name__ == '__main__':
    train_loader_350, test_loader_350 = load(350)
    train_loader_400, test_loader_400 = load(400)
    train_loader_450, test_loader_450 = load(450)
    train_loader_500, test_loader_500 = load(500)
    train_loaders = [train_loader_350, train_loader_400, train_loader_450, train_loader_500]
    test_loaders = [test_loader_350, test_loader_400, test_loader_450, test_loader_500]

    model = SPPNet().to(device)
    optimizer = optim.Adam(model.parameters(), lr=0.0001, betas=(0.9, 0.99))
    criterion = nn.CrossEntropyLoss()

    for epoch in range(1, EPOCH + 1):
        for train_loader, test_loader in zip(train_loaders, test_loaders):
            train(model, device, train_loader, criterion, optimizer, epoch)
            test(model, device, test_loader, criterion, epoch)

torch.save(model, save_path)

resnet+sppnet,或者 自适应卷积


import torch
from torch import nn
from torchvision import models
import torch.nn.functional as F
import os, math
from torch.nn.modules.pooling import AdaptiveAvgPool2d, AdaptiveMaxPool2d


class ResNet(nn.Module):
    def __init__(self, layers=18, num_class=2, pretrained=True):
        super(ResNet, self).__init__()
        if layers == 18:
            self.resnet = models.resnet18(pretrained=pretrained)
        elif layers == 34:
            self.resnet = models.resnet34(pretrained=pretrained)
        elif layers == 50:
            self.resnet = models.resnet50(pretrained=pretrained)
        elif layers == 101:
            self.resnet = models.resnet101(pretrained=pretrained)
        elif layers == 152:
            self.resnet = models.resnet152(pretrained=pretrained)
        else:
            raise ValueError('layers should be 18, 34, 50, 101.')
        self.num_class = num_class
        if layers in [18, 34]:
            self.fc = nn.Linear(512, num_class)
        if layers in [50, 101, 152]:
            self.fc = nn.Linear(512 * 4, num_class)

    def conv_base(self, x):
        x = self.resnet.conv1(x)
        x = self.resnet.bn1(x)
        x = self.resnet.relu(x)
        x = self.resnet.maxpool(x)

        layer1 = self.resnet.layer1(x)
        layer2 = self.resnet.layer2(layer1)
        layer3 = self.resnet.layer3(layer2)
        layer4 = self.resnet.layer4(layer3)
        return layer1, layer2, layer3, layer4

    def forward(self, x):
        layer1, layer2, layer3, layer4 = self.conv_base(x)
        x = self.resnet.avgpool(layer4)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x


class SPPNet(nn.Module):
    def __init__(self, backbone=101, num_class=2, pool_size=(1, 2, 6), pretrained=True):
        # Only resnet is supported in this version
        super(SPPNet, self).__init__()
        if backbone in [18, 34, 50, 101, 152]:
            self.resnet = ResNet(backbone, num_class, pretrained)
        else:
            raise ValueError('Resnet{} is not supported yet.'.format(backbone))

        if backbone in [18, 34]:
            self.c = 512
        if backbone in [50, 101, 152]:
            self.c = 2048

        self.spp = SpatialPyramidPool2D(out_side=pool_size)
        num_features = self.c * (pool_size[0] ** 2 + pool_size[1] ** 2 + pool_size[2] ** 2)
        self.classifier = nn.Linear(num_features, num_class)

    def forward(self, x):
        _, _, _, x = self.resnet.conv_base(x)
        x = self.spp(x)
        x = self.classifier(x)
        return x


class SpatialPyramidPool2D(nn.Module):
    """
    Args:
        out_side (tuple): Length of side in the pooling results of each pyramid layer.
    Inputs:
        - `input`: the input Tensor to invert ([batch, channel, width, height])
    """

    def __init__(self, out_side):
        super(SpatialPyramidPool2D, self).__init__()
        self.out_side = out_side

    def forward(self, x):
        # batch_size, c, h, w = x.size()
        out = None
        for n in self.out_side:
#             w_r, h_r = map(lambda s: math.ceil(s / n), x.size()[2:])  # Receptive Field Size
#             s_w, s_h = map(lambda s: math.floor(s / n), x.size()[2:])  # Stride
#             max_pool = nn.MaxPool2d(kernel_size=(w_r, h_r), stride=(s_w, s_h))
            max_pool = AdaptiveMaxPool2d(output_size=(n, n))
            y = max_pool(x)
            if out is None:
                out = y.view(y.size()[0], -1)
            else:
                out = torch.cat((out, y.view(y.size()[0], -1)), 1)
        return out

code源地址:

https://github.com/mmmmmmiracle/SPPNet/blob/master/multi.py

https://github.com/stanleykao72/Deepfake-Detector/blob/934749da71ae31f6e689f2ca2e015cd3e2d5c50a/py_utils/DL/sppnet/models/classifier.py

 

### 多尺度目标检测概述 多尺度目标检测是一种解决目标大小变化的技术,旨在应对图像中小目标和大目标共存的情况。这种技术能够帮助模型更有效地识别不同尺寸的目标,从而提升整体检测精度。 #### 1. 多尺度目标检测的核心概念 多尺度目标检测的关键在于通过多种方式捕捉到不同尺度上的特征信息。通常可以通过调整输入图像的分辨率、在网络的不同层提取特征或者引入金字塔结构等方式实现[^1]。这些方法可以增强网络对小目标和大目标的同时感知能力。 #### 2. 常见的多尺度目标检测技术 以下是几种常见的多尺度目标检测技术及其特点: - **图像金字塔 (Image Pyramid)** 图像金字塔通过对原始图像进行多次缩放构建多个尺度版本,然后分别在每个尺度上运行目标检测器。这种方法简单直观,但由于需要对每张图像生成多个副本并逐一处理,计算成本较高[^3]。 - **特征金字塔网络 (Feature Pyramid Network, FPN)** 特征金字塔网络是在卷积神经网络的基础上设计的一种架构,它利用自顶向下的路径和横向连接机制融合来自高层语义丰富的特征图与低层高分辨率的特征图。FPN能够在不增加太多额外参数的情况下显著改善多尺度目标检测的效果。 - **空间金字塔池化 (Spatial Pyramid Pooling, SPP)** 空间金字塔池化允许固定长度的输出表示任意大小的输入区域,这使得即使输入图像尺寸发生变化也能保持一致性的特征表达形式。SPPNet 是最早采用这一思想的经典工作之一[^2]。 - **锚点框 (Anchor Boxes with Multi-Scale Design)** 锚点框的设计本身支持多尺度特性,即预定义一系列具有不同宽高比例及中心位置的边界框作为初始假设。现代框架如 Faster R-CNN 和 YOLOv5 中都广泛采用了此类设计方案来覆盖各种可能的对象形状和大小范围。 #### 3. 实现中的注意事项 当实施上述任何一种或多尺度目标检测方案时需要注意以下几点事项: - 数据增广(Data Augmentation): 使用随机裁剪(Random Crop),翻转(Flipping)等手段扩充训练集有助于提高泛化能力和鲁棒性; - 平衡损失函数(Loss Function Balancing): 对于存在严重类别不平衡现象的数据分布情况特别重要,比如加权交叉熵或 focal loss 可以缓解该问题带来的负面影响; - 后处理(Post-processing Techniques): NMS(non-maximum suppression)操作对于去除重复预测至关重要;另外还可以考虑 soft-NMS 或者 DIoU-NMS 提升效果。 ```python import torch from torchvision.models.detection import fasterrcnn_resnet50_fpn def load_model(): model = fasterrcnn_resnet50_fpn(pretrained=True) device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') model.to(device) return model.eval() model = load_model() ``` 以上代码片段展示了如何加载一个基于 ResNet-50 背骨网路并且启用了 FPN 结构的标准 Faster R-CNN 模型实例用于执行推理任务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值