如果是你自己构建的模型,那么可以再forward函数中,返回特定层的输出特征图。

下面是介绍针对预训练模型,获取指定层的输出的方法。

如果你只想得到模型最后全连接层之前的输出,那么只需要将最后一个全连接层去掉:

import torchvision
import torch
net = torchvision.models.resnet18(pretrained=False)
print("model ", net)
net.fc = nn.Sequential([])

当然,对于vgg19网络,如果你想获得vgg19, classifier子模块中第一个全连接层的输出,则可以只更改其classifier子模块。

import torchvision
import torch
net = models.vgg19_bn(pretrained=False).cuda()
net.classifier = nn.Sequential(*list(net.classifier.children())[:-6])
# 只保留第一个全连接层, 输出特征为4096

接下来是一些通用方法:

方法1:

对于简单的模型,可以采用直接遍历子模块的方法

import torchvision
import torch
net = torchvision.models.resnet18(pretrained=False)
print("model ", net)
out = []
x = torch.randn(1, 3, 224, 224)
return_layer = "maxpool"
for name, module in net.named_children():print(name)# print(module)x = module(x)print(x.shape)if name == return_layer:out.append(x.data)break
print(out[0].shape)

该方法的缺点在于,只能得到其子模块的输出,而对于使用nn.Sequensial()中包含很多层的模型,无法获得其指定层的输出。

方法2:

使用torchvison提供内置方法,参考:Pytorch获取中间层输出的几种方法 - 知乎 (zhihu.com)

该方法与方法1 存在一样的问题。 不能获得其子模块内部特定层的输出。

from collections import OrderedDictimport torch
from torch import nnclass IntermediateLayerGetter(nn.ModuleDict):"""Module wrapper that returns intermediate layers from a modelIt has a strong assumption that the modules have been registeredinto the model in the same order as they are used.This means that one should **not** reuse the same nn.Moduletwice in the forward if you want this to work.Additionally, it is only able to query submodules that are directlyassigned to the model. So if `model` is passed, `model.feature1` canbe returned, but not `model.feature1.layer2`.Arguments:model (nn.Module): model on which we will extract the featuresreturn_layers (Dict[name, new_name]): a dict containing the namesof the modules for which the activations will be returned asthe key of the dict, and the value of the dict is the nameof the returned activation (which the user can specify)."""def __init__(self, model, return_layers):if not set(return_layers).issubset([name for name, _ in model.named_children()]):raise ValueError("return_layers are not present in model")orig_return_layers = return_layersreturn_layers = {k: v for k, v in return_layers.items()}layers = OrderedDict()for name, module in model.named_children():layers[name] = moduleif name in return_layers:del return_layers[name]if not return_layers:breaksuper(IntermediateLayerGetter, self).__init__(layers)self.return_layers = orig_return_layersdef forward(self, x):out = OrderedDict()for name, module in self.named_children():x = module(x)if name in self.return_layers:out_name = self.return_layers[name]out[out_name] = xreturn out# example
m = torchvision.models.resnet18(pretrained=True)
# extract layer1 and layer3, giving as names `feat1` and feat2`
new_m = torchvision.models._utils.IntermediateLayerGetter(m,{'layer1': 'feat1', 'layer3': 'feat2'})
out = new_m(torch.rand(1, 3, 224, 224))
print([(k, v.shape) for k, v in out.items()])
# [('feat1', torch.Size([1, 64, 56, 56])), ('feat2', torch.Size([1, 256, 14, 14]))]

补充:

使用 create_feature_extractor方法,创建一个新的模块,该模块将给定模型中的中间节点作为字典返回,用户指定的键作为字符串,请求的输出作为值。

该方法比 IntermediateLayerGetter方法更通用, 不局限于获得模型第一层子模块的输出。因此推荐使用create_feature_extractor方法。

# Feature extraction with resnet
from torchvision.models.feature_extraction import create_feature_extractor
model = torchvision.models.resnet18()
# extract layer1 and layer3, giving as names `feat1` and feat2`
model = create_feature_extractor(
model, {'layer1': 'feat1', 'layer3': 'feat2'})
out = model(torch.rand(1, 3, 224, 224))
print([(k, v.shape) for k, v in out.items()])

提取vgg16,features子模块下的特征层:

# vgg16
backbone = torchvision.models.vgg16_bn(pretrained=True)
# print(backbone)
backbone = create_feature_extractor(backbone, return_nodes={"features.42": "0"})        #“0”字典的key
out = backbone(torch.rand(1, 3, 224, 224))
print(out["0"].shape)

方法3:

使用hook函数,获取任意层的输出。

import torchvision
import torch
from torch import nn
from torchvision.models import resnet50, resnet18resnet = resnet18()
print(resnet)features_in_hook = []
features_out_hook = []
# 使用 hook 函数
def hook(module, fea_in, fea_out):features_in_hook.append(fea_in.data)         # 勾的是指定层的输入# 只取前向传播的数值features_out_hook.append(fea_out.data)      # 勾的是指定层的输出return Nonelayer_name = 'avgpool'
for (name, module) in resnet.named_modules():print(name)if name == layer_name:module.register_forward_hook(hook=hook)
# 测试
x = torch.randn(1, 3, 224, 224)
resnet(x)
# print(features_in_hook)  # 勾的是指定层的输入
print(features_out_hook[0].shape)  # 勾的是指定层的输出  # 1, 64, 56, 56
print(features_out_hook[0])

方法3的优点在于:

通过遍历resnet.named_modules()可以获取任意中间层的输入和输出。

比较通过方法2和方法3获得的指定层输出是否相等。,结果为True,说明两种方法获得的结果相同。

new_m = torchvision.models._utils.IntermediateLayerGetter(resnet, {'avgpool': "feat1"})
out = new_m(x)
print(out['feat1'].data)
# print([(k, v.shape) for k, v in out.items()])
print(torch.equal(features_out_hook[0], out['feat1'].data))    # True

补充:使用net._modules可以获得子模块内的层,但对于复杂模型,使用起来太过繁琐。

for name, module in resnet._modules['layer1']._modules.items():print(name)

冻结模型指定子模块的权重:

net = torchvision.models.vgg19_bn(pretrained=False)
for param in net.features.parameters():param.requires_grad=False# define optimizer
params = [p for p in net.parameters() if p.requires_grad]
optimizer = torch.optim.SGD(params, lr=0.005,momentum=0.9, weight_decay=0.0005)

获取模型的子模块,并保存其权重:

import torchvision
import torch
from torch import nn
from torchvision.models import resnet50, resnet18resnet = resnet18()
layer1 = resnet.get_submodule("layer1")
torch.save(layer1.state_dict(), './layer1.pth')
# 子模块载入相应权重
layer1.load_state_dict(torch.load("./layer1.pth"))

Pytorch提取预训练模型特定中间层的输出相关推荐

  1. Pytorch——BERT 预训练模型及文本分类(情感分类)

    BERT 预训练模型及文本分类 介绍 如果你关注自然语言处理技术的发展,那你一定听说过 BERT,它的诞生对自然语言处理领域具有着里程碑式的意义.本次试验将介绍 BERT 的模型结构,以及将其应用于文 ...

  2. linux载入pytorch的预训练模型时遇到_pickle.UnpicklingError: unpickling stack underflow

    linux试图载入pytorch的预训练模型resnet101时遇到如下报错: Traceback (most recent call last): File "train_baseline ...

  3. Pytorch——XLNet 预训练模型及命名实体识别

    介绍 在之前我们介绍和使用了 BERT 预训练模型和 GPT-2 预训练模型,分别进行了文本分类和文本生成次.我们将介绍 XLNet 预训练模型,并使用其进行命名实体识别次. 知识点 XLNet 在 ...

  4. Pytorch使用预训练模型进行图像分类

    在本文中,我们将介绍一些使用预训练网络的实际例子,这些网络出现在TorchVision模块的图像分类中. Torchvision包包括流行的数据集,模型体系结构,和通用的图像转换为计算机视觉.基本上, ...

  5. pytorch载入预训练模型后,训练指定层

    1.有了已经训练好的模型参数,对这个模型的某些层做了改变,如何利用这些训练好的模型参数继续训练: pretrained_params = torch.load('Pretrained_Model') ...

  6. Pytorch Resnet预训练模型参数地址

    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',  'resnet34': 'https://downl ...

  7. pytorch bert预训练模型的加载地址

    https://blog.csdn.net/weixin_39331401/article/details/109328681

  8. 载入pytorch的预训练模型时遇到_pickle.UnpicklingError: unpickling stack underflow

    转载自https://blog.csdn.net/iteapoy/article/details/106193500

  9. Pytorch:NLP 迁移学习、NLP中的标准数据集、NLP中的常用预训练模型、加载和使用预训练模型、huggingface的transfomers微调脚本文件

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) run_glue.py微调脚本代码 python命令执行run ...

最新文章

  1. C#:Guid.NewGuid()和DateTime.Now该选择哪个???
  2. easyNeurons 神经网络入门教程
  3. BZOJ 4974: 字符串大师
  4. python for net_转:.NET 4.0 下使用 Python for .NET
  5. mysql找不到performance_Mysql安装完毕运行时没有mysql和performance_schema数据库_MySQL
  6. 脆弱的是生命 不脆弱的是精神 雅安 挺住!
  7. 消息服务器mq集群出现假死,排查tomcat项目假死原因的简单方法
  8. dnf时装预览怎么打开_dnf怎么查找各职业时装代码
  9. mysql java uuid_Java生成UUID 与 MySQL数据库如何生成uuid数据
  10. java服务写在哪里_【Java学习笔记】如何写一个简单的Web Service
  11. SQL 随机抽取样本
  12. 挑战年薪50万不是梦,你要的高级架构师课程来袭!
  13. UE4 Slate二 用UMG思想去理解Slate+Slate编码
  14. kettle中报org.gjt.mm.mysql.Driver 解决办法
  15. Java基础-Java概述(第一、二章)
  16. 宝塔环境使用微软OneDrive云盘免费自动备份网站数据最佳方案!
  17. C++编程 学习笔记(六)函数(续)
  18. 目标检测任务超大图像的切图实现
  19. python 费马检测
  20. 【数据分析与挖掘(一)】笔试题汇总(附答案)

热门文章

  1. Android 之路44---四大组件之ContentProvider
  2. Ubuntu 快捷键使用说明(一)--截图
  3. 产品3周迭代一次,启信宝驾驭8000万企业征信的平台架构
  4. 武汉大学计算机学院学生工作处,学生工作部
  5. “一帮一学习小组”是中小学中常见的学习组织方式,老师把学习成绩靠前的学生跟学习成绩靠后的学生排在一组.
  6. 从README开始吧
  7. 计算机用户密码最长使用期限,密码最短使用期限
  8. 1688平台商品详情接口采集方法
  9. 理解z-index属性
  10. 【锐捷交换机】设备有网关的ARP缓存记录,但是ping不通网关地址——重置systemMac