深度学习 --- VGG16能让某个指定的feature map激活值最大化图片的可视化(JupyterNotebook实战)

   VGG16能让某个指定的feature map激活值最大化图片的可视化

        在前面的文章中,我用jupyter notebook分别实现了,预训练好的VGG16模型各层filter权重的可视化和给VGG16输入了一张图像,可视化VGG16各层的feature map。深度学习 --- VGG16卷积核的可视化(JupyterNotebook实战)-优快云博客文章浏览阅读653次,点赞11次,收藏8次。本文是基于JupyterNotebook的VGG16卷积核的可视化实战,有代码也有详细说明https://blog.youkuaiyun.com/daduzimama/article/details/141460156

深度学习 --- VGG16各层feature map可视化(JupyterNotebook实战)-优快云博客文章浏览阅读1k次,点赞16次,收藏24次。在VGG16模型中输入任意一张图片VGG16模型就能给出预测结果,但为什么会得到这个预测结果,通过观察每层的feature map或许有助于我们更好的理解模型。https://blog.youkuaiyun.com/daduzimama/article/details/140279255        

        在这篇文章中需要可视化的是看看究竟什么的图像会令众多feature map/activation map中的某个activation map的激活值最大化。例如,看看什么样的图像会让block2_conv2中的第123个feature map的激活值最大化。

这个算法的整体思路如下:

1,利用已有的不包含顶层的VGG16模型创建一个输出为指定层指定feature map的新模型

2,创建一个图像尺寸和模型输入层维度相同的随机噪声图,并假设他就是那个能够令指定feature map激活最大化的输入图像作为初值。

3,定义损失函数,这个损失函数的输入是刚才创建随机噪声图像,输出为指定feature map的激活值总和。

4,创建优化器使用梯度上升的反向传播方式,使得损失函数的函数值最大化。逐步迭代,最终把原始的随机噪声图像变成我们想要的能够最大化feature map的输入图像。

1,导入需要用到的库函数

import tensorflow as tf
print(tf.__version__)
print(tf.keras.__version__)

from tensorflow.keras.applications import VGG16
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import preprocess_input
import numpy as np
import matplotlib.pyplot as plt

2,加载不包括顶层VGG16的模型

model=VGG16(weights='imagenet',include_top=False)
model.summary()

# 获取该模型的总层数
total_layers = len(model.layers)

# 输出总层数
print(f"模型的总层数为: {total_layers}")

# 输出每一层所对应的名字便于后续选择feature map时使用
for i in range(total_layers):
    print(f"第{i}层是{model.layers[i].name}")


3,定义损失函数

        定义损失函数也就是定义feature map关于输入图像的函数。因此,损失函数的输入是我们后面自定义的模型model,输入图像和指定feature map的index。输出是整张指定feature map值的均值。

# 损失函数的输入为你所使用的model,输入图像和指定feature map的index,输出是指定层的某个卷积核的激活值的均值
def loss_function(model,input_image,feature_map_num):
    activations = model(input_image)#获得input_image在新模型中产生的所有特征图
    '''
    activations 是一个四维张量,其维度如下:

    第一个维度 (batch size): 代表输入批次的大小。通常情况下,如果只输入了一张图像,这个维度的值为 1。

    第二个维度 (height): 代表特征图的高度。随着网络层数的增加,通常由于池化层(Pooling Layer)的作用,这个维度会逐渐减小。

    第三个维度 (width): 代表特征图的宽度。和高度一样,宽度通常也会随着网络的加深而减小。

    第四个维度 (channels/filters): 代表特征图的通道数,或者说在当前层中使用的滤波器的数量。这个维度表示在每一层中所提取的不同特征的数量。

    '''
    loss = tf.reduce_mean(activations[:, :, :, feature_map_num])
    return loss

        ”activations = model(input_image)“这句话的意思是:把随机生成的输入图像喂给新建的模型计算,输出相应层所有的output,output即feature map。并且把指定层所有的feature map保存在activations中。 

        “loss = tf.reduce_mean(activations[:, :, :, feature_map_num])”这句话的意思是:根据函数输入的feature_map_num,在activations选择当前层指定的feature map,也就是我们需要最大化的那个feature map,并计算这个张量的均值。

        最终把整张feature map的均值通过loss函数传出去。

上述过程如果用数学模型来表示的话大致可写成(这里不一定严谨,仅供参考):

feature\; map_{i}=f(input\; image)

L(feature\; map)=mean(feature\; map)

这样看来,损失函数L是input image的复合函数,feature map是input image的函数。


4,定义计算梯度的函数
 

        梯度是用于反向传播的,这里所计算的梯度是损失函数相对于输入图像的梯度。

def gradient_function(model,image,feature_map_num):
    
    #创建 tf.GradientTape 对象:
    #TensorFlow 的 tf.GradientTape 是一个自动微分工具,它可以记录运算过程中涉及的所有变量,并计算这些变量相对于某个损失函数的梯度。
    with tf.GradientTape() as tape:
        
        #监视输入图像:这里明确告诉 GradientTape 需要监视 image 这个张量,确保后续可以计算相对于 image 的梯度。
        tape.watch(image)
        
        #计算损失函数
        loss = loss_function(model,image,feature_map_num)
        
    #通过 tape.gradient() 计算损失 loss 相对于输入图像 image 的梯度。
    #这会返回一个张量 gradient,表示如何调整输入图像以最大化或最小化损失。    
    gradient = tape.gradient(loss, image)
    return loss,gradient

        计算损失函数相对于输入图像的梯度的目的是为了通过反向传播,也就是梯度上升,不断地优化输入图像。这一过程也可以用数学公式简单的表示如下:

grad(input\; image)=\frac{\partial L(input\; image)}{\partial input\; image}

因此,第一步是调用先前定义的损失函数计算loss。

第二步就调用tensorflow自带的计算梯度的函数tf.GradientTape去计算梯度。其中,tape.gradient的第一个输入是损失函数的值loss,第二个要输入的变量是损失函数相对于谁的梯度,比如说在本例中要计算损失函数相对于输入图像input image的梯度,所以这里输入的就是随机初始化的input image。


5,定义用于优化图像显示效果的函数

        通过梯度上升反向传播得到的能够令某个feature map最大化的input image无法直接通过imshow函数显示,因此,这里定义了一个专门

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

松下J27

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值