可视化可以帮助我们更好的理解卷积网络每一层学到了什么,或者说每一个卷积核究竟学到了什么,他是怎么理解图像的
这种的话当我们神经网络结果不太好时,我们可以分析不好的原因
图片来源于李飞飞老师的内容
梯度上升方法做可视化
直接可视化
因为第一层的卷积核通道是3,可以和RGB对应,所以可以直接可视化
发现学到的是一些纹理表示,而我们知道复杂的物体都是可以由简单的纹理组成
降维法
倒数第二层全连接层会输出4096维度的特征
我们通过降维法把他缩小到2维度(x,y)
可以把库中的所有图片进行降维操作,这样一张图片会得到一个x,y的坐标
然后把这张图片放到坐标系里
会发现相近的会在一起
可视化卷积层就很难看到了
输入一张图片,对于某一层的某一个卷积核,看卷积核的输出大小,越大越亮(响应值较大)
输入一张图片,对于某一层的某一个卷积核,看卷积核对哪些区域的响应值比较大,然后再把对应区域在原图抠出来
可以看到每一行是一个感兴趣区域
比如第二行这个卷积只对人脸感兴趣,
到后面我们会发现神经网络学习到的是更高层的更有语义信息的内容
输入一张图片,对于分类关键的内容进行遮挡,看看卷积网络的分类置信度有没有下降,下降说明网络学到了关键内容
遮住一些区域,看最后的概率输出
记录一些规则的
反向梯度传递
以往都是利用输出对参数求导然后更新
但现在我们利用输出y对输入图片x的每一个像素进行求导
比如有300×400分辨率图片,通道数是3
我们对输入的每一个像素求导,每一个像素R,G,B各得到1个,总共3个,取3个里面的最大值,然后可视化导数
可以看到
从这里可以看出网络对哪些像素信息感兴趣,如果是对小狗周围感兴趣,说明网络学习是OK的,如果可视化后是其他区域,则不OK
之前方法都得需要输入一张图片
直接对神经元反向传递,感觉输出
通常用于生成神经网络中某一层的激活或过滤器的可视化。这种技术的主要思想是通过最大化神经网络某一层的激活或过滤器的响应,来生成图像,从而可以观察该层在输入图像上响应最强的特征。以下是可视化的梯度上升算法的一般步骤:
(1)选择层和目标: 首先,选择要可视化的神经网络的层某一个神经元。比如最后一层1000维的第3维
原始图像为输入全零的图像
(2)计算梯度: 接下来,计算这一个神经元相对于输入图像的梯度。把其他神经元的梯度置零,回传到原始图像加到像素全为零的图像上去
(3)反复进行(1)(2)步
就可以看到下图的情况
风格转移网络很好玩
我们可以输入一张风格图
输入一张原图,内容图
输入一张噪声图
(1)初始化网络参数并且固定网络参数
(2)输入噪声图片和风格图片,在每一层计算两者提取特征的损失,计算损失对于输入噪声图片的梯度,然后更新原噪声图片
(3)输入噪声图片和原图,在某一层计算两者提取特征的损失,计算损失对于输入噪声图片的梯度,然后更新原噪声图片
(4)不断迭代(3)(4)
但是后来人们发现这个需要迭代很多次,耗时较长
就把这个噪声图直接取消了,直接传入原图到一个网络中,使得这个网络的输出尽量的既符合风格图特征,又符合内容图特征
下次给一张图只需要过一个网络就可以了
keras-vis
Keras-vis 是一个基于 Keras 深度学习库的可视化工具,里面实现了上面我们讲到的一些可视化方法原理的工具
显著性图salinecy: 原理就是上面讲到的3.5
利用 visualize_saliency函数实现
以下是使用 Keras-vis 中的 saliency 技术的一般步骤:
以下是一个简单的示例
import numpy as np
import matplotlib.pyplot as plt
from keras.applications import VGG16
from vis.visualization import visualize_saliency
from vis.utils import utils
from keras import activations
# 加载预训练的VGG16模型
model = VGG16(weights='imagenet', include_top=True)
# 选择一个输入图像
input_image_path = 'path_to_your_input_image.jpg'
# 加载输入图像并进行预处理
img = utils.load_img(input_image_path, target_size=(224, 224))
img = utils.preprocess_input(img)
# 获取模型的预测类别
pred_class = np.argmax(model.predict(img))
# 使用Saliency技术生成显著性图
saliency_map = visualize_saliency(model, layer_idx=-1, filter_indices=pred_class, seed_input=img, backprop_modifier='guided')
# 可视化显著性图
plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.imshow(utils.load_img(input_image_path, target_size=(224, 224)))
plt.title('Input Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(saliency_map, cmap='jet')
plt.title('Saliency Map')
plt.axis('off')
plt.tight_layout()
plt.show()
最大化激活activation: 原理就是上面讲到的3.6
利用 visualize_activation函数实现
方法
layer_name
参数选择你想要可视化的神经网络层。通常,这是卷积神经网络(CNN)中的某一卷积层或其他感兴趣的层。visualize_activation
函数生成激活图像。你可以通过 filter_indices
参数来选择特定过滤器(卷积核)的激活,也可以通过 input_range
参数来指定输入图像的像素范围。utils.draw_text
函数将生成的激活图像可视化,通常是与输入图像一起显示,以更好地理解模型在输入数据上的激活模式。from vis.visualization import visualize_activation
from vis.utils import utils
from keras.models import load_model
# 加载已经训练好的模型
model = load_model('your_model.h5')
# 选择一个层进行可视化
layer_name = 'conv2d_1' # 选择你想可视化的层
# 使用可视化函数生成激活图像
activations = visualize_activation(model, layer_name, filter_indices=0, input_range=(0., 1.))
# 显示可视化结果
utils.draw_text(activations, 'Filter 0')
我们常常说神经网络是黑盒
为什么说黑盒?不是说不知道神经网络学习到了什么,而是不知道他为什么会学到这些信息