【TensorFlow-windows】keras接口——卷积核可视化

前言

在机器之心上看到了关于卷积核可视化相关理论,但是作者的源代码是基于fastai写的,而fastai的底层是pytorch,本来准备自己用Keras复现一遍的,但是尴尬地发现Keras还没玩熟练,随后发现了一个keras-vis包可以用于做卷积核可视化。以下理论是在不熟悉fastai的运行机制的基础上做的简单理解,可能有误,欢迎指正。

国际惯例,参考博客:

40行Python代码,实现卷积特征可视化

github:visualizing-cnn-feature-maps

Keras Visualization Toolkit

Keras官方可视化卷积核

理论

简单概率为一句话就是:优化输入以最大化指定层特征图的平均激活

先贴一下GitHub上的可视化部分代码:

class FilterVisualizer():def __init__(self, size=56, upscaling_steps=12, upscaling_factor=1.2):self.size, self.upscaling_steps, self.upscaling_factor = size, upscaling_steps, upscaling_factorself.model = vgg16(pre=True).cuda().eval()set_trainable(self.model, False)def visualize(self, layer, filter, lr=0.1, opt_steps=20, blur=None):sz = self.sizeimg = np.uint8(np.random.uniform(150, 180, (sz, sz, 3)))/255  # generate random imageactivations = SaveFeatures(list(self.model.children())[layer])  # register hookfor _ in range(self.upscaling_steps):  # scale the image up upscaling_steps timestrain_tfms, val_tfms = tfms_from_model(vgg16, sz)img_var = V(val_tfms(img)[None], requires_grad=True)  # convert image to Variable that requires gradoptimizer = torch.optim.Adam([img_var], lr=lr, weight_decay=1e-6)for n in range(opt_steps):  # optimize pixel values for opt_steps timesoptimizer.zero_grad()self.model(img_var)loss = -activations.features[0, filter].mean()loss.backward()optimizer.step()img = val_tfms.denorm(img_var.data.cpu().numpy()[0].transpose(1,2,0))self.output = imgsz = int(self.upscaling_factor * sz)  # calculate new image sizeimg = cv2.resize(img, (sz, sz), interpolation = cv2.INTER_CUBIC)  # scale image upif blur is not None: img = cv2.blur(img,(blur,blur))  # blur image to reduce high frequency patternsself.save(layer, filter)activations.close()def save(self, layer, filter):plt.imsave("layer_"+str(layer)+"_filter_"+str(filter)+".jpg", np.clip(self.output, 0, 1))

很容易发现,可视化流程为:

  • 载入训练好的模型,设置权重为不可训练
  • 随机初始化一个噪声,预处理一下,并将其转换为可训练张量,也就是可以对这个输入求梯度,我们以前的神经网络是对权重求梯度去优化权重,这里刚好反过来,是对输入求梯度去优化梯度
  • 目标损失就是想要可视化的卷积核对应的特征图的平均激活值。额外多一句嘴,都知道卷积核的大小是(m,n,s1,s2)(m,n,s1,s2)(m,n,s1,s2)大小,其中mmm是上一层特征图数目,nnn是卷积核个数也是下一层特征图的个数,所以每一个卷积核对应下一层特征图其中的一个,也就说每个特征图都是独立的,只和与它相关的那一个卷积核有关,我们想可视化第几个卷积核,平均激活就这个卷积核对应的特征图的平均值。
  • 接下来就是在一定迭代次数内不断更新对输入求梯度并更新输入值,这就是输入从噪声到特征响应图的可视化过程。

如果用公式表示就是:
input=input−learn_rate×∂loss∂inputinput=input - learn\_rate\times\frac{\partial loss}{\partial input} input=inputlearn_rate×inputloss
区分于传统的训练神经网络时候的:
w=w−learn_rata×∂loss∂ww=w-learn\_rata\times \frac{\partial loss}{\partial w} w=wlearn_rata×wloss
至于外层还有一个循环是,迭代完opt_steps后,将当前更新完的输入resize成一个大点的尺寸,再迭代,如此反复折腾,至于原因,在机器之心的文章上有写:

我们现在有了一个分辨率好得多的低频模式,并且没有太多的噪音。为什么这样做会有用呢?我的想法是:当我们从低分辨率开始时,我们会得到低频模式。放大后,放大后的模式图相比直接用大尺度图像优化生成的模式图有较低的频率。因此,在下一次迭代中优化像素值时,我们处于一个更好的起点,看起来避免了局部最小值。这有意义吗?为了进一步减少高频模式,我在放大后稍微模糊了图像。
我发现以 1.2 的倍数放大 12 次之后得到的结果不错。

Keras-vis工具包的使用

预备工作

  • 导入模型与载入权重

    from keras.applications import VGG16
    model=VGG16(weights='imagenet',include_top=True)
    

    查看模型每层的名字,以便后续可视化

    model.summary()
    

    输出

    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 224, 224, 3)       0         
    _________________________________________________________________
    block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
    _________________________________________________________________
    block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
    _________________________________________________________________
    block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
    _________________________________________________________________
    block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
    _________________________________________________________________
    block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
    _________________________________________________________________
    block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
    _________________________________________________________________
    block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
    _________________________________________________________________
    block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
    _________________________________________________________________
    block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
    _________________________________________________________________
    block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
    _________________________________________________________________
    block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
    _________________________________________________________________
    block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
    _________________________________________________________________
    block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
    _________________________________________________________________
    block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
    _________________________________________________________________
    block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
    _________________________________________________________________
    block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
    _________________________________________________________________
    block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
    _________________________________________________________________
    block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
    _________________________________________________________________
    flatten (Flatten)            (None, 25088)             0         
    _________________________________________________________________
    fc1 (Dense)                  (None, 4096)              102764544 
    _________________________________________________________________
    fc2 (Dense)                  (None, 4096)              16781312  
    _________________________________________________________________
    predictions (Dense)          (None, 1000)              4097000   
    =================================================================
    Total params: 138,357,544
    Trainable params: 138,357,544
    Non-trainable params: 0
    

可视化最后一层全连接层

因为最后一层是全连接层,使用softmax激活,本质是将最后一层归一化得到属于每一类的概率,所以他的每个节点与其它节点相关,这就是softmax的特殊性。反观其它层,每个特征图或者全连接的节点都是互相独立的。所以为了消除最后一层受到softmax导致各节点不独立的影响,在优化的时候使用线性激活替代softmax激活,方法如下:

引入相关包:

from vis.utils import utils
from keras import activations

用名字找到最后一层的索引,并更改它的激活函数

layer_idx=utils.find_layer_idx(model=model,layer_name='predictions')
model.layers[layer_idx].activation=activations.linear
model=utils.apply_modifications(model)

接下来就可以可视化了

引入相关包

from vis.visualization import visualize_activation
import matplotlib.pyplot as plt

不迭代可视化,结果不太整洁

img=visualize_activation(model,layer_idx=layer_idx,filter_indices=20)
plt.imshow(img)

在这里插入图片描述

迭代可视化,结果会整洁一点

img=visualize_activation(model,layer_idx=layer_idx,filter_indices=20,max_iter=500,verbose=False)
plt.imshow(img)

在这里插入图片描述

加入Jitter,获得更好的可视化结果:

#得到更加干净的可视化结果图
from vis.input_modifiers import Jitter
img=visualize_activation(model=model,layer_idx=layer_idx,filter_indices=20,max_iter=500,verbose=False,input_modifiers=[Jitter(16)])
plt.imshow(img)

在这里插入图片描述

可视化任意层卷积核

block3_conv3的第56个卷积核为例

layer_idx=utils.find_layer_idx(model=model,layer_name='block3_conv3')
img=visualize_activation(model=model,layer_idx=layer_idx,filter_indices=56,verbose=False,input_modifiers=[Jitter(16)])
plt.imshow(img)

在这里插入图片描述
看着像饼干。

可视化响应热度图

通过最后一层全连接层可视化可以发现,第20个权重会响应鸟嘴和上半身的羽毛,试试将一只鸟丢进去,看看最终响应的部位。

先引入对应包:

import numpy as np 
import matplotlib.cm as cm
from vis.visualization import visualize_cam,overlay

读取图像,以及三种显示方案(区别我也不清楚,没看):

img=utils.load_img('ouzel1.jpg',target_size=(224,224))
modifier=[None,'guided','relu']

在这里插入图片描述

可视化

i=0
for m in modifier:    plt.subplot(str(13)+str(i))layer_idx=utils.find_layer_idx(model=model,layer_name='predictions')grads=visualize_cam(model,layer_idx,filter_indices=20,seed_input=img,backprop_modifier=modifier[0])jet_heatmap=np.uint8(cm.jet(grads)[...,:3]*255)plt.imshow(overlay(jet_heatmap,img))i=i+1

在这里插入图片描述

不太放心,再试试第379个节点响应的什么,从类别标签上看,第379个标签是howler_monkey,应该是一种猴子,可视化响应内容看看:

img=visualize_activation(model=model,layer_idx=layer_idx,filter_indices=379,max_iter=300,verbose=False,input_modifiers=[Jitter(16)])
plt.imshow(img)

在这里插入图片描述

看着像猴子,应该有猴脸和尾巴。
找一张猴子
在这里插入图片描述
看看响应情况:

img=utils.load_img('monkey.jpg',target_size=(224,224))
i=0
for m in modifier:    plt.subplot(str(13)+str(i))layer_idx=utils.find_layer_idx(model=model,layer_name='predictions')grads=visualize_cam(model,layer_idx,filter_indices=379,seed_input=img,backprop_modifier=modifier[0])jet_heatmap=np.uint8(cm.jet(grads)[...,:3]*255)plt.imshow(overlay(jet_heatmap,img))i=i+1

在这里插入图片描述

Bingo~~!!响应了猴子脸

后记

此博客只介绍了Keras_vis包中的部分功能,其余功能以后有机会再探索,博客介绍的卷积核可视化与响应热度图还是比较有用的。

博客代码:

百度网盘链接:https://pan.baidu.com/s/1SpcSoPkQE6aWx2HfoXX-Aw
提取码:xuox

好久没写博客, 逃~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246597.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【TensorFlow-windows】投影变换

前言 没什么重要的,就是想测试一下tensorflow的投影变换函数tf.contrib.image.transform中每个参数的含义 国际惯例,参考文档 官方文档 描述 调用方法与默认参数: tf.contrib.image.transform(images,transforms,interpolationNEAREST,…

【TensorFlow-windows】扩展层之STN

前言 读TensorFlow相关代码看到了STN的应用,搜索以后发现可替代池化,增强网络对图像变换(旋转、缩放、偏移等)的抗干扰能力,简单说就是提高卷积神经网络的空间不变性。 国际惯例,参考博客: 理解Spatial Transformer…

【TensorFlow-windows】MobileNet理论概览与实现

前言 轻量级神经网络中,比较重要的有MobileNet和ShuffleNet,其实还有其它的,比如SqueezeNet、Xception等。 本博客为MobileNet的前两个版本的理论简介与Keras中封装好的模块的对应实现方案。 国际惯例,参考博客: 纵…

【TensorFlow-windows】keras接口——ImageDataGenerator裁剪

前言 Keras中有一个图像数据处理器ImageDataGenerator,能够很方便地进行数据增强,并且从文件中批量加载图片,避免数据集过大时,一下子加载进内存会崩掉。但是从官方文档发现,并没有一个比较重要的图像增强方式&#x…

【TensorFlow-windows】TensorBoard可视化

前言 紧接上一篇博客,学习tensorboard可视化训练过程。 国际惯例,参考博客: MNIST机器学习入门 Tensorboard 详解(上篇) Tensorboard 可视化好帮手 2 tf-dev-summit-tensorboard-tutorial tensorflow官方mnist_…

深度学习特征归一化方法——BN、LN、IN、GN

前言 最近看到Group Normalization的论文,主要提到了四个特征归一化方法:Batch Norm、Layer Norm、Instance Norm、Group Norm。此外,论文还提到了Local Response Normalization(LRN)、Weight Normalization(WN)、Batch Renormalization(BR)…

【TensorFlow-windows】keras接口——利用tensorflow的方法加载数据

前言 之前使用tensorflow和keras的时候,都各自有一套数据读取方法,但是遇到一个问题就是,在训练的时候,GPU的利用率忽高忽低,极大可能是由于训练过程中读取每个batch数据造成的,所以又看了tensorflow官方的…

骨骼动画——论文与代码精读《Phase-Functioned Neural Networks for Character Control》

前言 最近一直玩CV,对之前学的动捕知识都忘得差不多了,最近要好好总结一下一直以来学习的内容,不能学了忘。对2017年的SIGGRAPH论文《Phase-Functioned Neural Networks for Character Control》进行一波深入剖析吧,结合源码。 额…

颜色协调模型Color Harmoniztion

前言 最近做换脸,在肤色调整的那一块,看到一个有意思的文章,复现一波玩玩。不过最后一步掉链子了,有兴趣的可以一起讨论把链子补上。 主要是github上大佬的那个复现代码和原文有点差异,而且代码复杂度过高&#xff0…

Openpose推断阶段原理

前言 之前出过一个关于openpose配置的博客,不过那个代码虽然写的很好,而且是官方的,但是分析起来很困难,然后再opencv相关博客中找到了比较清晰的实现,这里分析一波openpose的推断过程。 国际惯例,参考博…

换脸系列——眼鼻口替换

前言 想着整理一下换脸相关的技术方法,免得以后忘记了,最近脑袋越来越不好使了。应该会包含三个系列: 仅换眼口鼻;换整个面部;3D换脸 先看看2D换脸吧,网上已经有现成的教程了,这里拿过来整理一…

换脸系列——整脸替换

前言 前面介绍了仅替换五官的方法,这里介绍整张脸的方法。 国际惯例,参考博客: [图形算法]Delaunay三角剖分算法 维诺图(Voronoi Diagram)分析与实现 Delaunay Triangulation and Voronoi Diagram using OpenCV (…

3D人脸重建——PRNet网络输出的理解

前言 之前有款换脸软件不是叫ZAO么,分析了一下,它的实现原理绝对是3D人脸重建,而非deepfake方法,找了一篇3D重建的论文和源码看看。这里对源码中的部分函数做了自己的理解和改写。 国际惯例,参考博客: 什…

tensorflow官方posenet模型解析

前言 tensorflow官方有个姿态估计项目,这个输入和openpose还有点不一样,这里写个单人情况下的模型输出解析方案。 国际惯例,参考博客: 博客: 使用 TensorFlow.js 在浏览器端上实现实时人体姿势检测 tensorflow中posnet的IOS代…

tensorflow2安装时候的一个dll找不到的错误

电脑环境: vs2015python3.7.6,使用anaconda安装的CUDA 10.1cuDnn 7.6.5tensorflow2.1.0 错误内容 File "C:\Users\zb116\anaconda3\lib\imp.py", line 242, in load_modulereturn load_dynamic(name, filename, file)File "C:\Users\z…

PCA、SVD、ZCA白化理论与实现

简介 在UFLDL中介绍了主成分分析这一块的知识,而且当时学机器学习的时候,老师是将PCA和SVD联系起来将的,同时UFLDL也讲到了使用PCA做数据白化whitening处理,这个词经常在论文里面看到。 国际惯例,参考博客&#xff1…

OpenCV使用Tensorflow2-Keras模型

前言 最近工作上需要在C上快速集成Tensorflow/Keras训练好的模型,做算法验证。首先想到的就是opencv里面的dnn模块了,但是它需要的格式文件比较郁闷,是pb格式的模型,但是keras通常保存的是h5文件,查阅了很多资料&…

3D人脸表情驱动——基于eos库

前言 之前出过三篇换脸的博文,遇到一个问题是表情那一块不好处理,可行方法是直接基于2D人脸关键点做网格变形,强行将表情矫正到目标人脸,还有就是使用PRNet的思想,使用目标人脸的顶点模型配合源人脸的纹理&#xff0c…

3D姿态估计——ThreeDPose项目简单易用的模型解析

前言 之前写过tensorflow官方的posenet模型解析,用起来比较简单,但是缺点是只有2D关键点,本着易用性的原则,当然要再来个简单易用的3D姿态估计。偶然看见了ThreeDPose的项目,感觉很强大的,所以把模型扒下来…

简易的素描图片转换流程与实现

前言 之前经常在网上看到用PS实现真实图片到素描图片的转换,但是流程都大同小异,身为一只程序猿,必须来个一键转化额。 国际惯例,参考博客: Photoshop基础教程:混合模式原理篇 颜色减淡的原理讲解以及应…