Deep learning with Python 学习笔记(4)
本节讲卷积神经网络的可视化
三种方法
- 可视化卷积神经网络的中间输出(中间激活)
有助于理解卷积神经网络连续的层如何对输入进行变换,也有助于初步了解卷积神经网络每个过滤器的含义
- 可视化卷积神经网络的过滤器
有助于精确理解卷积神经网络中每个过滤器容易接受的视觉模式或视觉概念
- 可视化图像中类激活的热力图
有助于理解图像的哪个部分被识别为属于某个类别,从而可以定位图像中的物体
可视化中间激活
是指对于给定输入,展示网络中各个卷积层和池化层输出的特征图,这让我们可以看到输入如何被分解为网络学到的不同过滤器。我们希望在三个维度对特征图进行可视化:宽度、高度和深度(通道)。每个通道都对应相对独立的特征,所以将这些特征图可视化的正确方法是将每个通道的内容分别绘制成二维图像
Keras加载模型方法
from keras.models import load_model
model = load_model('cats_and_dogs_small_2.h5')
可视化方法
from keras.models import load_model
from keras.preprocessing import image
import numpy as np
import matplotlib.pyplot as plt
from keras import models
model = load_model('dogVScat.h5')
# 查看模型
model.summary()
img_path = "C:\\Users\\fan\\Desktop\\testDogVSCat\\test\\cats\\cat.1700.jpg"
img = image.load_img(img_path, target_size=(150, 150))
img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
img_tensor /= 255
# shape(1, 150, 150, 3)
print(img_tensor.shape)
plt.title("original cat")
plt.imshow(img_tensor[0])
plt.show()
# 提取前 8 层的输出
layer_outputs = [layer.output for layer in model.layers[:8]]
# 创建一个模型,给定模型输入,可以返回这些输出
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
# 返回8个Numpy数组组成的列表,每个层激活对应一个 Numpy 数组
activations = activation_model.predict(img_tensor)
first_layer_activation = activations[0]
# 将第 4 个通道可视化
plt.matshow(first_layer_activation[0, :, :, 4])
plt.show()
# 将每个中间激活的所有通道可视化
layer_names = []
for layer in model.layers[:8]:
layer_names.append(layer.name)
images_per_row = 16
for layer_name, layer_activation in zip(layer_names, activations):
# 特征图中的特征个数
n_features = layer_activation.shape[-1]
size = layer_activation.shape[1]
# 在这个矩阵中将激活通道平铺
n_cols = n_features // images_per_row
display_grid = np.zeros((size * n_cols, images_per_row * size))
for col in range(n_cols):
for row in range(images_per_row):
channel_image = layer_activation[0, :, :, col * images_per_row + row]
# 对特征进行后处理,使其看起来更美观
channel_image -= channel_image.mean()
if channel_image.std() != 0:
channel_image /= channel_image.std()
channel_image *= 64
channel_image += 128
channel_image = np.clip(channel_image, 0, 255).astype('uint8')
display_grid[col * size: (col + 1) * size,
row * size: (row + 1) * size] = channel_image
scale = 1. / size
plt.figure(figsize=(scale * display_grid.shape[1],
scale * display_grid.shape[0]))
plt.title(layer_name)
plt.grid(False)
plt.imshow(display_grid, aspect='auto', cmap='viridis')
plt.show()
结果
原始猫

模型,使用之上第一个介绍的猫狗二分类的模型

第一层

第四层

第七层

第八层

随着层数的加深,激活变得越来越抽象,并且越来越难以直观地理解。它们开始表示更高层次的概念
即,随着层数的加深,层所提取的特征变得越来越抽象。更高的层激活包含关于特定输入的信息越来越少,而关于目标的信息越来越多
可视化卷积神经网络的过滤器
想要观察卷积神经网络学到的过滤器,另一种简单的方法是显示每个过滤器所响应的视觉模式。这可以通过在输入空间中进行梯度上升来实现:从空白输入图像开始,将梯度下降应用于卷积神经网络输入图像的值,其目的是让某个过滤器的响应最大化。得到的输入图像是选定过滤器具有最大响应的图像
过程
首先,需要构建一个损失函数,其目的是让某个卷积层的某个过滤器的值最大化;然后,我们要使用随机梯度下降来调节输入图像的值,以便让这个激活值最大化
from keras import backend as K
import numpy as np
from keras.applications import VGG16
import matplotlib.pyplot as plt
from keras.preprocessing import image
# 将张量转换为有效图像
def deprocess_image(x):
x -= x.mean()
x /= (x.std() + 1e-5)
x *= 0.1
x += 0.5
# 将 x 裁切(clip)到 [0, 1] 区间
x = np.clip(x, 0, 1)
x *= 255
# 将 x 转换为 RGB 数组
x = np.clip(x, 0, 255).astype('uint8')
return x
# 生成过滤器可视化
def generate_pattern(layer_name, filter_index, size=150):
layer_output = model.get_layer(layer_name).output
loss = K.mean(layer_output[:, :, :, filter_index])
grads = K.gradients(loss, model.input)[0]
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
iterate = K.function([model.input], [loss, grads])
input_img_data = np.random.random((1, size, size, 3)) * 20 + 128.
step = 1.
for i in range(40):
loss_value, grads_value = iterate([input_img_data])
input_img_data += grads_value * step
img = input_img_data[0]
return deprocess_image(img)
# 为过滤器的可视化定义损失张量
model = VGG16(weights='imagenet', include_top=False)
layer_name = 'block3_conv1'
filter_index = 0
layer_output = model.get_layer(layer_name).output
loss = K.mean(layer_output[:, :, :, filter_index])
# 获取损失相对于输入的梯度
grads = K.gradients(loss, model.input)[0]
# 将梯度张量除以其 L2 范数来标准化
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
# 给定 Numpy 输入值,得到 Numpy 输出值
iterate = K.function([model.input], [loss, grads])
loss_value, grads_value = iterate([np.zeros((1, 150, 150, 3))])
# 通过随机梯度下降让损失最大化
# 从一个带噪声的随机图像开始
input_img_data = np.random.random((1, 150, 150, 3)) * 20 + 128.
plt.imshow(image.array_to_img(input_img_data[0]))
plt.show()
step = 1.
for i in range(40):
loss_value, grads_value = iterate([input_img_data])
input_img_data += grads_value * step
def draw_layer_filter(layer_name):
size = 64
margin = 5
results = np.zeros((8 * size + 7 * margin, 8 * size + 7 * margin, 3))
for i in range(8):
for j in range(8):
filter_img = generate_pattern(layer_name, i + (j * 8), size=size)
horizontal_start = i * size + i * margin
horizontal_end = horizontal_start + size
vertical_start = j * size + j * margin
vertical_end = vertical_start + size
results[horizontal_start: horizontal_end, vertical_start: vertical_end, :] = filter_img
plt.figure(figsize=(20, 20))
results = image.array_to_img(results)
plt.imshow(results)
plt.show()
draw_layer_filter(layer_name='block1_conv1')
draw_layer_filter(layer_name='block4_conv1')
结果
输入图像

过滤器: block1_conv1

过滤器:block4_conv1

通过对比发现
模型第一层(block1_conv1)的过滤器对应简单的方向边缘和颜色(还有一些是彩色边缘)
高层的过滤器类似于自然图像中的纹理
可视化类激活的热力图
这种可视化方法有助于了解一张图像的哪一部分让卷积神经网络做出了最终的分类决策。这有助于对卷积神经网络的决策过程进行调试,特别是出现分类错误的情况下。这种方法还可以定位图像中的特定目标
这种通用的技术叫作类激活图(CAM,class activation map)可视化,它是指对输入图像生成类激活的热力图。类激活热力图是与特定输出类别相关的二维分数网格,对任何输入图像的每个位置都要进行计算,它表示每个位置对该类别的重要程度
[一种方法](Grad-CAM: visual explanations from deep networks via gradientbased localization)
给定一张输入图像,对于一个卷积层的输出特征图,用类别相对于通道的梯度对这个特征图中的每个通道进行加权
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
from keras import backend as K
import matplotlib.pyplot as plt
from PIL import Image
import cv2
model = VGG16(weights='imagenet')
img_path = 'E:\\study\\研究生\\笔记\\studyNote\\bookStudy\\bookNote\\imgs\\testImg.png'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
# 添加一个维度,将数组转换为(1, 224, 224, 3) 形状的批量
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
print('Predicted:', decode_predictions(preds, top=3)[0])
# 索引编号
np.argmax(preds[0])
# 来使用 Grad-CAM 算法展示图像中哪些部分最像非洲象
african_elephant_output = model.output[:, 386]
last_conv_layer = model.get_layer('block5_conv3')
grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]
pooled_grads = K.mean(grads, axis=(0, 1, 2))
iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]])
pooled_grads_value, conv_layer_output_value = iterate([x])
for i in range(512):
conv_layer_output_value[:, :, i] *= pooled_grads_value[i]
heatmap = np.mean(conv_layer_output_value, axis=-1)
# 热力图后处理
heatmap = np.maximum(heatmap, 0)
heatmap /= np.max(heatmap)
plt.matshow(heatmap)
plt.show()
# 将热力图与原始图像叠加
img = Image.open(img_path).convert('RGB')
img = np.array(img)
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img = heatmap * 0.4 + img
cv2.imwrite('elephant_cam.jpg', superimposed_img)
superimposed_img = image.array_to_img(superimposed_img)
plt.imshow(superimposed_img)
plt.show()
原始图像

热力图

混合图像

保存的图像

此处保存的图像和显示的图像不一致
Deep learning with Python 学习笔记(5)
Deep learning with Python 学习笔记(3)
Deep learning with Python 学习笔记(4)的更多相关文章
- Deep learning with Python 学习笔记(11)
总结 机器学习(machine learning)是人工智能的一个特殊子领域,其目标是仅靠观察训练数据来自动开发程序[即模型(model)].将数据转换为程序的这个过程叫作学习(learning) 深 ...
- Deep learning with Python 学习笔记(10)
生成式深度学习 机器学习模型能够对图像.音乐和故事的统计潜在空间(latent space)进行学习,然后从这个空间中采样(sample),创造出与模型在训练数据中所见到的艺术作品具有相似特征的新作品 ...
- Deep learning with Python 学习笔记(9)
神经网络模型的优化 使用 Keras 回调函数 使用 model.fit()或 model.fit_generator() 在一个大型数据集上启动数十轮的训练,有点类似于扔一架纸飞机,一开始给它一点推 ...
- Deep learning with Python 学习笔记(8)
Keras 函数式编程 利用 Keras 函数式 API,你可以构建类图(graph-like)模型.在不同的输入之间共享某一层,并且还可以像使用 Python 函数一样使用 Keras 模型.Ker ...
- Deep learning with Python 学习笔记(7)
介绍一维卷积神经网络 卷积神经网络能够进行卷积运算,从局部输入图块中提取特征,并能够将表示模块化,同时可以高效地利用数据.这些性质让卷积神经网络在计算机视觉领域表现优异,同样也让它对序列处理特别有效. ...
- Deep learning with Python 学习笔记(6)
本节介绍循环神经网络及其优化 循环神经网络(RNN,recurrent neural network)处理序列的方式是,遍历所有序列元素,并保存一个状态(state),其中包含与已查看内容相关的信息. ...
- Deep learning with Python 学习笔记(5)
本节讲深度学习用于文本和序列 用于处理序列的两种基本的深度学习算法分别是循环神经网络(recurrent neural network)和一维卷积神经网络(1D convnet) 与其他所有神经网络一 ...
- Deep learning with Python 学习笔记(3)
本节介绍基于Keras的使用预训练模型方法 想要将深度学习应用于小型图像数据集,一种常用且非常高效的方法是使用预训练网络.预训练网络(pretrained network)是一个保存好的网络,之前已在 ...
- Deep learning with Python 学习笔记(2)
本节介绍基于Keras的CNN 卷积神经网络接收形状为 (image_height, image_width, image_channels)的输入张量(不包括批量维度),宽度和高度两个维度的尺寸通常 ...
随机推荐
- python_列表、元组、字典、集合对比
列表.元组.字典.集合 列表.元组.字典.集合对比 比较项 列表 元组 字典 集合 类型名称 list tuple dict set 定界符 [] () {} {} 是否可变 是 否 是 是 是否有序 ...
- unigui如何连接数据库
unigui如何连接数据库 UNIGUI既可以二层直连数据库,也可以通过中间件连接数据库. 这里只介绍UNIGUI二层直连数据库. 数据库连接控件.数据集控件都要拖放在MainModule窗体上.UN ...
- Android-available for offline mode
出现 available for offline mode 字样的异常: 取消打钩 Offine work 点击sync project ..... 成功解决:
- WinRAR试用过期决绝方法
一.WinRAR 试用过期决绝方法 直接去WINRAR官方下个版本装上然后这样 复制以下内容(红色)到记事本,保存为rarreg.key文件(即文件名是rarreg,扩展名是key),把这文件拷贝到W ...
- C# 动态创建SQL数据库(一)
最近在做项目中要求能够要求动态添加数据库并建表.具体思路如下 1 提供数据名,根据数据库创建数据库 2 自定数据库与数据表,提供数据表自定与数据类型创建表 创建sqlhelper类,用于数据库操作 u ...
- AJPFX:外汇的点差和点值
外汇“点差”就是交易商买卖货币之间产生的差值. 要了解点差我们先解释一下“点”的含义:为了精确和方便地表示汇价,一般用5位数字表示,其中最小变化的单位就称为"点".例如:英镑美元货 ...
- 17_python_成员
一.类成员 1.字段 class Province: country = '中国' # 实例 (静态) 字段:类变量. 不属于对象, 对象可以访问 def __init__(self, name): ...
- Redis---Hash(字典)
1. 概述 Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象. Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿). ...
- 一步步Cobol 400上手自学入门教程05 - 表
在COBOL中有几类典型结构的表.这几类典型结构的表在大体上可分为下标表和索引表两大类.另外,根据表的重复次数定义又有定长表和变长表.此外,表还允许嵌套,因此还有嵌套表.这几类表均符合表的基本定义,都 ...
- [Leetcode]146.LRU缓存机制
Leetcode难题,题目为: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key ...