如何从PyTorch预训练fasterrcnn_resnet50_fpn提取指定形状特征
报错原因
你遇到的'FasterRCNN' object has no attribute 'features'报错,是因为torchvision.models.detection.fasterrcnn_resnet50_fpn属于封装好的目标检测模型,和普通图像分类ResNet的结构逻辑完全不同:
- 它没有直接暴露
features属性,骨干网络、FPN、RPN、ROI检测头都是拆分挂载在不同子模块下 - 带FPN的骨干输出是多尺度特征字典,不是单路串行的张量流,不能直接拆层拼接成
nn.Sequential跑前向,你原来的写法只适配单路结构的分类CNN,用在检测模型上必然报错。
可行实现方案
你需要的2048维特征,是Faster RCNN中ROI Align池化后、送入分类/回归头之前,经过roi_heads.box_head计算得到的每个候选框的表征,单框特征维度刚好是2048。如果最终筛选得到36个有效检测框,输出形状就是你需要的(36, 2048)。
注意:官方Faster RCNN的num_classes参数默认包含背景类,如果你需要适配35个前景类+1个背景类的36类检测场景,直接把分类头替换为对应类别数即可
完整实现代码如下:
import torch import torchvision from torch import nn from torchvision.models.detection.faster_rcnn import FastRCNNPredictor device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 1. 加载预训练模型,替换检测头适配36类场景 model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) # 获取检测头输入特征维度 in_channel = model.roi_heads.box_predictor.cls_score.in_features # 替换分类预测头,num_classes设为你需要的总类别数(含背景) model.roi_heads.box_predictor = FastRCNNPredictor(in_channel, num_classes=36) model.to(device) model.eval() # 2. 注册前向钩子提取box_head输出的2048维特征 roi_feature_storage = [] def get_roi_feature(module, input, output): # output形状为[N, 2048],N为单张图中经过筛选的候选框数量 roi_feature_storage.append(output.detach().cpu()) # 给输出2048维特征的box_head模块绑定钩子 feature_hook = model.roi_heads.box_head.register_forward_hook(get_roi_feature) # 3. 前向推理提取特征 dummy_img = torch.zeros((1, 3, 800, 800)).float().to(device) with torch.no_grad(): # 检测模型eval模式下输入为图像列表即可,不需要传入标签 det_result = model([dummy_img]) # 取出提取到的特征,当检测结果有36个有效框时,形状即为(36, 2048) target_features = roi_feature_storage[0].squeeze(0) print(target_features.shape) # 推理结束移除钩子 feature_hook.remove()
补充说明
如果你需要固定输出(36, 2048)形状的特征,可以根据自身业务逻辑做后续处理:
- 按检测置信度排序取Top36个框的特征
- 按类别对同类别框的特征做均值聚合,得到每个类别对应1个2048维特征,最终输出36类共36个特征
内容的提问来源于stack exchange,提问作者puhuk
相关产品推荐
相关产品推荐

