【hook 特征图可视化】

hook的使用场景多种多样,本文将使用hooks来简单可视化卷积神经网络的特征提取,主要包括以下几个步骤:

  1. 创建CNN特征提取器(即需要可视化特征图的模型)
  2. 创建一个保存hook内容的对象
  3. 为需要可视化的卷积层创建hook
  4. 可视化特征图

1.创建CNN特征提取器

import torch
import torchvision
 
model= torchvision.models.resnet34(pretrained=True)
if torch.cuda.is_available():
    model.cuda()
 
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

 2.创建保存hook内容的对象

class SaveOutput:
    def __init__(self):
        self.outputs = []
    def __call__(self, module, module_in, module_out):
        self.outputs.append(module_out)
    def clear(self):
        self.outputs=[]
 
save_output = SaveOutput()

3.为需要可视化的卷积层创建hook

可视化卷积层之前,需要查看模型网络层对应的名称,

比如下图中需要查看layer1的特征图,需要找到对应特征图名称【model.module.backbone.layer1[2].relu3】

layer_name = [
model.module.backbone.layer1[2].relu3,
model.module.backbone.layer2[3].relu3,
model.module.backbone.layer3[5].relu3,
model.module.backbone.layer4[2].relu3]
for layer in layer_name:
    handle = layer.register_forward_hook(save_output)
    hook_handles.append(handle)

4.特征图可视化

该部分主要是讲第三部分提取到的特征图进行可视化,可视化的方法有两种,一种是将各个通道的特征图求和相加,输出完整特征图,还有一种是将各个通道的特征图进行拼接,将每个通道的特征图分别输出。

# 将特征图进行拼接,输出每个通道特征图
def grid_gray_image(imgs, each_row: int):
    '''
    imgs shape: batch * size (e.g., 64x32x32, 64 is the number of the gray images, and (32, 32) is the size of each gray image)
    each_row: Number of feature maps per line
    '''
    row_num = imgs.shape[0]//each_row
    for i in range(row_num):
        img = imgs[i*each_row]
        img = (img - img.min()) / (img.max() - img.min())
        for j in range(1, each_row):
            tmp_img = imgs[i*each_row+j]
            tmp_img = (tmp_img - tmp_img.min()) / (tmp_img.max() - tmp_img.min())
            img = np.hstack((img, tmp_img))
        if i == 0:
            ans = img
        else:
            ans = np.vstack((ans, img))
    return ans
#将特征图转换成热力图(将各个通道特征图相加求和)
def featuremap_2_heatmap(feature_map):
    assert isinstance(feature_map, torch.Tensor)
    feature_map = feature_map.detach()
    heatmap = feature_map[:,0,:,:]*0
    heatmaps = []
    for c in range(feature_map.shape[1]):
        heatmap+=feature_map[:,c,:,:]
    heatmap = heatmap.cpu().numpy()
    heatmap = np.mean(heatmap, axis=0)
 
    heatmap = np.maximum(heatmap, 0)
    heatmap /= np.max(heatmap)
    heatmaps.append(heatmap)
 
    return heatmaps
# 绘制特征图
def draw_feature_map(features,save_dir = '',name = None):
    i=0
    if isinstance(features,torch.Tensor):
        for heat_maps in features:
            heat_maps=heat_maps.unsqueeze(0)
            heatmaps = featuremap_2_heatmap(heat_maps)
            for heatmap in heatmaps:
                heatmap = np.uint8(255 * heatmap)
                # 下面这行将热力图转换为RGB格式 ,如果注释掉就是灰度图
                heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
                superimposed_img = heatmap
                plt.imshow(superimposed_img,cmap='gray')
                plt.show()
    else:
        a = -1
        for i , featuremap in enumerate(features):
            heatmaps = featuremap_2_heatmap(featuremap)
            for heatmap in heatmaps:
                # heatmap = (heatmap-heatmap.min())/(heatmap.max()-heatmap.min())
                heatmap = np.uint8(255 * heatmap)  # 将热力图转换为RGB格式
                heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
                superimposed_img = heatmap
                plt.title(name[i%len(name)])
                plt.imshow(superimposed_img,cmap='gray')
                plt.show()
                cv2.imwrite(os.path.join(save_dir, 'rpn_cls'+ str(i) +'.jpg'), superimposed_img)

5.特征图效果展示

本文以旋转目标检测网络ReDet特征图进行展示

第一行为backbone提取的特征图,第二行为rpn_cls特征图,第三行为rpn_reg特征图

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要可UNet模型中的特征,您可以使用PyTorch中的hook函数。hook函数允许您在模型的特定层上注册一个函数,该函数将在每次前向传播时被调用,并且可以访问该层的特征。 下面是一个示例,展示了如何使用hook函数可UNet模型的特征: ```python import torch import torch.nn as nn import torchvision.utils as vutils # 定义UNet模型 class UNet(nn.Module): def __init__(self): super(UNet, self).__init__() # 定义UNet的结构 def forward(self, x): # UNet的前向传播过程 return output # 创建UNet模型实例 model = UNet() # 注册hook函数的回调函数 def hook_fn(module, input, output): # 可特征的代码 fmap_grid = vutils.make_grid(output, normalize=True, scale_each=True) writer.add_image('feature map', fmap_grid, global_step=322) # 找到要可特征的层 target_layer = model.conv1 # 注册hook函数 hook_handle = target_layer.register_forward_hook(hook_fn) # 执行前向传播 output = model(input) # 移除hook函数 hook_handle.remove() ``` 在上面的代码中,您需要替换`UNet`类中的代码以定义您自己的UNet模型。然后,选择要可特征的目标层,并将其传递给`register_forward_hook`函数以注册hook函数。 在hook函数中,您可以执行特征的可操作,并使用TensorBoard将其添加到像中。确保根据您的设置正确导入`torch`、`torch.nn`和`torchvision.utils`模块,并将`writer`替换为您用于记录TensorBoard事件的实际写入器。 请注意,在执行完前向传播后,不要忘记使用`remove()`方法移除hook函数,以免在之后的前向传播中再次调用hook函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值