0,可视化的重要性:

深度学习很多方向所谓改进模型、改进网络都是在按照人的主观思想在改进,常常在说模型的本质是提取特征,但并不知道它提取了什么特征、哪些区域对于识别真正起作用、也不知道网络是根据什么得出了分类结果。为了增强结果的可解释性,需要给出模型的一些可视化图来证明模型或新methods对于任务的作用,这一点不仅能增加新模型或新methods可信度;还可以根据可视化某个网络的结果分析其不足之处,从而提出新的改进方法。(写论文还可以用来凑字数、凑工作量:)

无特殊说明,本文中所用的网络是:

  1. torchvision.models.resnet50(pretrained=True)

所用的图片为

1,特征图(feture map)

  • 概念

    特征图是一个在深度学习的研究过程中经常会遇到的概念,简单来说就是对输入进行一次计算处理后的输出,通过对特征图的可视化可以看出输入样本在网络中的变化情况。
  • 可视化方法:
    • 直接可视化:直接让输入数据经过各层网络,获取各层网络处理后的输出,然后绘制想要展示的特征图即可。
    • 反卷积网络(deconvnet)From 'Visualizing and Understanding Convolutional Networks':对一个训练好的神经网络中任意一层feature map经过反卷积网络后重构出像素空间,主要操作是
      • Unpooling/反池化:将最大值放到原位置,而其他位置直接置零。
      • Rectification:同样使用Relu作为激活函数。
      • Filtering/反卷积:使用原网络的卷积核的转置作为卷积核,对Rectification后的输出进行卷积。
    • 导向反向传播(Guided-backpropagation)From 'Striving for simplicity: The all convolutional net':其与反卷积网络的区别在于对ReLU的处理方式,在反卷积网络中使用ReLU处理梯度,只回传梯度大于0的位置;而在普通反向传播中只回传feature map中大于0的位置;在导向反向传播中结合这两者,只回传输入和梯度都大于0的位置。
  • 例子
  1. '''方法1,直接可视化'''
  2. import torch
  3. import torchvision
  4. import cv2
  5. from PIL import Image
  6. import torchvision.models as models
  7. import torch.nn as nn
  8. from matplotlib import pyplot as plt
  9. import math
  10. '''1,加载训练模型'''
  11. resnet50 = models.resnet50(pretrained=True)
  12. print(resnet50)
  13. '''2,提取CNN层,非必须'''
  14. conv_layers = []
  15. model_weights = []
  16. model_children = list(models.resnet50().children())
  17. counter = 0
  18. for i in range(len(model_children)):
  19. if type(model_children[i]) == nn.Conv2d:
  20. counter += 1
  21. model_weights.append(model_children[i].weight)
  22. conv_layers.append(model_children[i])
  23. elif type(model_children[i]) == nn.Sequential:
  24. for j in range(len(model_children[i])):
  25. for child in model_children[i][j].children():
  26. if type(child) == nn.Conv2d:
  27. counter += 1
  28. model_weights.append(child.weight)
  29. conv_layers.append(child)
  30. '''3,读取数据'''
  31. img = cv2.cvtColor(cv2.imread('data.jpg'), cv2.COLOR_BGR2RGB)
  32. img = torchvision.transforms.Compose([
  33. torchvision.transforms.ToPILImage(),
  34. torchvision.transforms.Resize((1050, 1680)),
  35. torchvision.transforms.ToTensor(),
  36. torchvision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  37. ])(img).unsqueeze(0)
  38. '''4,特征映射,这里绘制第一层卷积的feature map'''
  39. featuremaps = [conv_layers[0](img)]
  40. plt.figure(1)
  41. for i in range(64):
  42. plt.subplot(8, 8, i + 1)
  43. plt.axis('off')
  44. plt.imshow(featuremaps[0][0, i, :, :].detach(), cmap='gray')
  45. plt.show()

2,卷积核权重

  • 概念

    卷积核的计算可以看作是在计算相似度,二维卷积核本身可以看作是一副缩略图,一维卷积核本身也可以看作是一段一维信号,卷积核权重的可视化就是将这些信息可视化。(虽然这些信息几乎都是杂乱无章的,没什么用:)
  • 可视化方法

    取出某个想要可视化的卷积核权重,然后绘图即可。
  • 例子
    1. for i in range(64):
    2. plt.subplot(8, 8, i+1)
    3. plt.axis('off')
    4. plt.imshow(model_weights[0][i][0, :, :].detach(), cmap='gray')
    5. plt.show()

3,卷积核最匹配样本

  • 概念

    正如2中提到的,卷积核的计算可以看作是在计算相似度,那么在一批样本中经过卷积核计算以后的相似度值肯定有高有底,那么相似度越高也就越满足这个卷积核的“口味”,这也意味着该样本与该卷积核越匹配。那么,有没有方法能够超越有限的训练样本,生成与特定卷积核最匹配的样本呢?答案是肯定的。一个可行的思路是:随机初始化生成一个样本(指的是对样本的各个数据点随机取值,而不是在数据集中随机选一个样本),然后经过前向传播到该卷积核;我们希望这个随机生成的样本在经过这一层卷积核时响应值能尽可能的大(响应值比较大的样本是这个卷积核比较认可的,是与识别任务更相关的);我们要做的就是不断调整样本各个数据点的值,直到响应值足够大,我们就可以认为此时的样本就是这个卷积核所认可的,从而达到生成卷积核最匹配样本的目的。
  • 可视化方法

    设计一个损失函数(例如:经过变换后的响应值),使用梯度上升,更新数据点的值,使响应值最大。
  • 例子

    下图展示的是pytorch中的resnet50中的layer1的最后一次卷积操作中的256个卷积核中的0,10,...,150这16个卷积核的最匹配样本。优化过程中用了两种方法,结果如图:

    方法1



    方法2,可以明显看出方法2的结果区别性更大

4,类别激活图(Class Activation Map/CAM)

  • 概念

    特征图可视化、卷积核权重可视化、卷积核最匹配样本这些方法更多是用于分析模型在某一层学习到的东西;但是对于不同的类,我们又如何知道模型是根据哪些信息进行识别的?是否能将这些信息在原始数据上表示出来(比如说热力图)?答案依旧是肯定的。这个方法主要是CAM系列,目前有CAM, Grad-CAM, Grad-CAM++。其中CAM需要特定的结构-GAP,但大部分现有的模型没有这个结构,想要使用该方法便需要修改原模型结构,并重新训练,因此适用范围有限。针对CAM的缺陷,有了之后Grad-CAM的提出。
  • 可视化方法

    Grad-CAM的最大特点就是不再需要修改现有的模型结构,也不需要重新训练,可以直接在原模型上可视化。Grad-CAM对于想要可视化的类别C,使最后输出的类别C的概率值通过反向传播到最后一层feature maps,得到类别C对该feature maps的每个像素的梯度值;对每个像素的梯度值取全局平均池化,即可得到对feature maps的加权系数alpha;接下来对特征图加权求和,使用ReLU进行修正,再进行上采样。使用ReLU的原因是对于那些负值,可认为与识别类别C无关,这些负值可能是与其他类别有关,而正值才是对识别C有正面影响的。

计算梯度及全局平均池化:

\[\alpha_k^c=\overbrace{\frac{1}{Z}\displaystyle{\sum_i\sum_j}}^{global~average~pooling}\underbrace{\frac{\partial{y^c}}{\partial{A^k_{ij}}}}_{grdients~via~backprop}
\]

加权:

\[L^c_{Grad-CAM}=ReLU\underbrace{\left(\displaystyle\sum_k\alpha^c_kA^k\right)}_{linear~combination}
\]
  • 例子

    1,由蓝到红,越红代表关注度越高,对于类别分配的结果影响越大,这个例子将图片识别为n02909870 水桶,从关注的区域也可以看出预测是失败的,没有关注到有效的信息



    这个预训练模型眼里好像不是水桶就是钩子。。。

2,从网上找了一个模型,效果就挺好的

识别青蛙的结果很有意思,这意味着网络关注的重点不在于青蛙,反而在于青蛙周围的环境,而且网络的预测结果还是正确的!

5,网络结构的可视化

  • 可视化方法

    用tensorboard直接绘制就行,注意两点

    • 路径不要有中文
    • pytorch版本在1.3.0及以上(低版本不显示)
  • 例子
  1. from torch.utils.tensorboard import SummaryWriter
  2. import torch
  3. import torch.nn as nn
  4. import torch.nn.functional as F
  5. '''
  6. 1,初始化writer
  7. '''
  8. writer = SummaryWriter('runs/resnet50') # 指定写入文件的位置
  9. '''
  10. 2,加载模型
  11. '''
  12. class Net(nn.Module):
  13. def __init__(self):
  14. super(Net, self).__init__()
  15. self.conv1 = nn.Conv2d(1, 6, 5)
  16. self.pool = nn.MaxPool2d(2, 2)
  17. self.fc1 = nn.Linear(6 * 12 * 12, 120)
  18. self.fc2 = nn.Linear(120, 84)
  19. def forward(self, x):
  20. x = self.pool(F.relu(self.conv1(x)))
  21. x = x.view(-1, 6 * 12 * 12)
  22. x = F.relu(self.fc1(x))
  23. x = F.relu(self.fc2(x))
  24. return x
  25. net = Net()
  26. '''
  27. 3,添加网络结构
  28. '''
  29. writer.add_graph(net, torch.randn(1, 1, 28, 28))
  30. writer.close()

pytorch中网络特征图(feture map)、卷积核权重、卷积核最匹配样本、类别激活图(Class Activation Map/CAM)、网络结构的可视化方法的更多相关文章

  1. CNN中feature map、卷积核、卷积核的个数、filter、channel的概念解释

    CNN中feature map.卷积核.卷积核的个数.filter.channel的概念解释 参考链接: https://blog.csdn.net/xys430381_1/article/detai ...

  2. 使用DeepWalk从图中提取特征

    目录 数据的图示 不同类型的基于图的特征 节点属性 局部结构特征 节点嵌入 DeepWalk简介 在Python中实施DeepWalk以查找相似的Wikipedia页面 数据的图示 当你想到" ...

  3. 详解Pytorch中的网络构造,模型save和load,.pth权重文件解析

    转载:https://zhuanlan.zhihu.com/p/53927068 https://blog.csdn.net/wangdongwei0/article/details/88956527 ...

  4. Pytorch中自定义神经网络卷积核权重

    1. 自定义神经网络卷积核权重 神经网络被深度学习者深深喜爱,究其原因之一是神经网络的便利性,使用者只需要根据自己的需求像搭积木一样搭建神经网络框架即可,搭建过程中我们只需要考虑卷积核的尺寸,输入输出 ...

  5. Pytorch中RoI pooling layer的几种实现

    Faster-RCNN论文中在RoI-Head网络中,将128个RoI区域对应的feature map进行截取,而后利用RoI pooling层输出7*7大小的feature map.在pytorch ...

  6. (原)CNN中的卷积、1x1卷积及在pytorch中的验证

    转载请注明处处: http://www.cnblogs.com/darkknightzh/p/9017854.html 参考网址: https://pytorch.org/docs/stable/nn ...

  7. pytorch中的激励函数(详细版)

          初学神经网络和pytorch,这里参考大佬资料来总结一下有哪些激活函数和损失函数(pytorch表示)      首先pytorch初始化:   import torch import t ...

  8. pytorch中tensorboardX的用法

    在代码中改好存储Log的路径 命令行中输入 tensorboard --logdir /home/huihua/NewDisk1/PycharmProjects/pytorch-deeplab-xce ...

  9. pytorch 中的重要模块化接口nn.Module

    torch.nn 是专门为神经网络设计的模块化接口,nn构建于autgrad之上,可以用来定义和运行神经网络 nn.Module 是nn中重要的类,包含网络各层的定义,以及forward方法 对于自己 ...

随机推荐

  1. 结构感知图像修复:ICCV2019论文解析

    结构感知图像修复:ICCV2019论文解析 StructureFlow: Image Inpainting via Structure-aware Appearance Flow 论文链接: http ...

  2. Mask-RCNN技术解析

    Mask-RCNN技术解析 MaskR-CNN 论文链接:https://arxiv.org/pdf/1703.06870.pdf 代码链接:https://github.com/CharlesSha ...

  3. CodeGen用户定义的扩展令牌

    CodeGen用户定义的扩展令牌 用户定义的扩展令牌是一种特殊的令牌,开发人员可以确定令牌的名称以及在代码生成过程中遇到令牌时要插入的值. CodeGen支持多种机制,允许通过以下方式实现用户定义的令 ...

  4. 一文教会你认识Vuex状态机

    摘要:简单来说,Vuex就是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享. 本文分享自华为云社区<Vuex状态机快速了解与应用>,原文作者:北极光之夜. 一. ...

  5. C#-防止用户输入具有风险的敏感字符

    最近有涉及到要防止用户在网页文本框中输入具有风险的敏感字符所以特地编写了一套针对用户输入的字符进行安全过滤的一个方法,在后台接收到用户输入的字符后调用执行该方法即可完成过滤操作,主要使用正则来匹配并替 ...

  6. 作为一名双非本科毕业的Java程序员,我该如何在日益严重的内卷化中避免被裁?

    前言 对一个 Java 程序员而言,并发编程能否熟练掌握是判断他是不是优秀的重要标准之一.因为并发编程在 Java 语言中最为晦涩的知识点,它涉及内存.CPU.操作系统.编程语言等多方面的基础能力,更 ...

  7. 狂神说JUC学习笔记(一)

    狂神说JUC的原版笔记: 链接:https://pan.baidu.com/s/12zrGI4JyZhmkQh0cqEO4BA 提取码:d65c 我的笔记在狂神的笔记上增加了一些知识点或者做了些许修改 ...

  8. 【NX二次开发】Block UI 曲线收集器

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  9. spring + spring mvc + tomcat 面试题(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  10. spring赌上未来的一击:WebFlux性能实测

    最近花了一点时间系统的测试验证了在SpringBoot框架下使用SpringMVC和Spring WebFlux两种框架开发接口,对比了响应时间以及压测吞吐量的区别. WebFlux&Spri ...