pytorch提取网络任意层输出的特征图

网上很多教程教我们怎么获取某一层网络输出的feature map。
原理很简单,对于我们自己写的网络其实很容易,我们只要在return 的时候返回我们想要的特征就可以了,但是对于一些别人写好的,我们又不方便改原代码的网络,提取特定层的feature map就有点麻烦了。
下面我以torchvision的vgg16为例,提取第一个全连接层输出的feature map
首先我们看看网络都由什么层

import torchvision
model = torchvision.models.vgg16(pretrained=True)
print(model)

输出:

VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

可以看到这里有conv,ReLU,MaxPool2d,等等,我们让我们的输入依次经过这些层,然后获取我们需要的输出就可以了。

import torchvision
model = torchvision.models.vgg16(pretrained=True)
#实际实用的时候,a可以换成我们需要输出的图片
a=torch.zeros((2,3,224,224))
#我们枚举整个网络的所有层
for i,m in enumerate(model.modules()):
	#让网络依次经过和原先结构相同的层,我们就可以获取想要的层的输出
	if isinstance(m, nn.Conv2d) or isinstance(m, nn.BatchNorm2d) or\
			isinstance(m, nn.ReLU) or isinstance(m, nn.MaxPool2d) or isinstance(m, nn.AdaptiveAvgPool2d):
		print(m)
		a= m(a)
	#我只想要第一个全连接层的输出
	elif isinstance(m, nn.Linear):
		print(m)	
		#和源代码一样,将他展平成一维的向量
		a = torch.flatten(a, 1)
		#获取第一个全连接层的输出
		a= m(a)
		break
print(a)

这样子,a就是我们最后想要的第一个全连接层的输出了。

更新
没想到这么多人看,那再更新一些比较简单的方法。
当我们需要用一些像VGG之类的作为backbone时,只想要feature层,最后的全连接可以去掉,可以这样做:

import torchvision.models as m
import torch.nn as nn
model = m.resnet50(pretrained=True)
#直接将最后一层赋值为空,模型的输出就是池化后的特征图了
model.fc = nn.Sequential([])
input_ = torch.zeros((2,3,224,224))
output_ = model(input_)
#(2,2048)
print(output_.shape)
  • 27
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 可以通过在网络中添加一个特征提取获取网络输出特征。这可以通过以下方式实现: 1. 在网络的最后添加一个特征提取,例如全局平均池化或全局最大池化。 2. 在前向传递期间,将输入数据传递到网络中,并同时记录特征提取输出。 3. 返回特征提取输出作为网络输出。 以下是示例代码: ```python import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) self.pool = nn.MaxPool2d(2, 2) self.fc1 = nn.Linear(64 * 8 * 8, 128) self.fc2 = nn.Linear(128, 10) self.feature_layer = nn.AdaptiveAvgPool2d((1, 1)) # 添加全局平均池化提取特征 def forward(self, x): x = F.relu(self.conv1(x)) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 64 * 8 * 8) x = F.relu(self.fc1(x)) x = self.fc2(x) feature = self.feature_layer(x) # 获取特征 return feature net = Net() # 前向传递并获取特征 input_data = torch.randn(1, 3, 32, 32) output_feature = net(input_data) print(output_feature.shape) ``` 在此示例中,我们添加了一个全局平均池化,将其作为特征提取,以获取网络输出特征。在前向传递期间,我们记录了特征提取输出,并将其作为网络输出返回。 ### 回答2: 在PyTorch获取网络输出特征可以通过多种方式实现,下面介绍两种常见的方法。 方法一:使用hook函数 我们可以通过在模型的某一层注册一个hook函数来获取输出特征。首先,定义一个hook函数来记录特征值: ```python feature = None def hook_fn(module, input, output): global feature feature = output ``` 然后,在需要获取特征的地方,注册这个hook函数到相关的上: ```python model.layer.register_forward_hook(hook_fn) ``` 在模型前向传播时,当模型经过注册了hook函数的时,该输出会被保存到我们定义的feature变量中。最后,我们就可以通过访问feature变量来获取这个特定输出特征。 方法二:使用intermediate layer 另一种方法是通过修改模型结构,在网络中的某一层输出特征。假设我们想要获取模型的第n输出特征,可以按照以下步骤进行: 1. 将模型拆分成两部分:前n为一个模型,后面的为一个模型。 2. 通过前n模型的forward方法传递输入数据,得到输出特征。 3. 将输出特征作为另一个模型的输入,通过该模型的forward方法得到最终的输出。 通过这种方式,我们可以获取到指定输出特征。 总结:以上介绍了两种常见的方法来获取PyTorch网络输出特征。通过使用hook函数或调整模型结构,我们可以方便地获取任意输出特征。 ### 回答3: 在PyTorch中,可以通过在网络模型中的某一层之后添加一个特征提取器(feature extractor)来获取网络输出特征特征提取器是一个新的网络模型,其中包含了原始网络模型中感兴趣的之后的所有。 要获取网络输出特征,首先需要定义原始网络模型。然后,通过将原始网络模型作为一个子模块添加到特征提取器中,并将所需的之后的所有从原始网络复制到特征提取器中。这样,特征提取器模型就会从原始网络模型的所需之后开始输出特征。 接下来,可以将输入数据通过特征提取器模型进行正向传播,从而获得网络输出特征特征提取器模型会将输入数据经过原始网络模型的所需之后的所有处理,并给出输出特征。 在获取网络输出特征后,可以进一步对这些特征进行处理和分析,比如进行分类、聚类、可视化等操作,以更好地理解网络输出。 总的来说,利用PyTorch获取网络输出特征可以通过定义特征提取器模型,在原始网络模型的所需之后添加对应来实现。这样可以获得网络输出特征,并进行进一步的处理和分析。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值