使用Python可视化卷积神经网络方法汇总
仅做学术分享,如有侵权,联系删除
转载于 :深度学习与计算机视觉
目录
CNN模型可视化的重要性 可视化方法 显著图 基于梯度的类激活图 最大激活 图像遮挡 绘制模型架构 可视化滤波器 基本方法 基于激活的方法 基于梯度的方法
CNN模型可视化的重要性
了解模型的工作原理 超参数调整 找出模型的失败之处并能够解决失败 向消费者/最终用户或业务主管解释决策
CNN模型的可视化方法
基本方法-向我们展示训练模型总体架构的简单方法 基于激活的方法-在这些方法中,我们破译单个神经元或一组神经元的激活函数,以理解它们正在做什么 基于梯度的方法-这些方法倾向于在训练模型时操纵由向前和反向传播形成的梯度
1.基本方法
1.1 绘制模型架构
model.summary()
_________________________________________________________________Layer (type) Output Shape Param # =================================================================conv2d_1 (Conv2D) (None, 26, 26, 32) 320 _________________________________________________________________conv2d_2 (Conv2D) (None, 24, 24, 64) 18496 _________________________________________________________________max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64) 0 _________________________________________________________________dropout_1 (Dropout) (None, 12, 12, 64) 0 _________________________________________________________________flatten_1 (Flatten) (None, 9216) 0 _________________________________________________________________dense_1 (Dense) (None, 128) 1179776 _________________________________________________________________dropout_2 (Dropout) (None, 128) 0 _________________________________________________________________preds (Dense) (None, 10) 1290 =================================================================Total params: 1,199,882Trainable params: 1,199,882Non-trainable params: 0
1.2 可视化滤波器
top_layer = model.layers[0]
plt.imshow(top_layer.get_weights()[0][:, :, :, 0].squeeze(), cmap='gray')
2. 基于激活的方法
2.1 最大激活
from vis.visualization import visualize_activation
from vis.utils import utils
from keras import activations
from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (18, 6)
# 按名称搜索图层索引。
# 或者,我们可以将其指定为-1,因为它对应于最后一层。
layer_idx = utils.find_layer_idx(model, 'preds')
#用线性层替换softmax
model.layers[layer_idx].activation = activations.linear
model = utils.apply_modifications(model)
# 这是我们要最大化的输出节点。
filter_idx = 0
img = visualize_activation(model, layer_idx, filter_indices=filter_idx)
plt.imshow(img[..., 0])
for output_idx in np.arange(10):
# 让我们这次关闭详细输出以避免混乱
img = visualize_activation(model, layer_idx, filter_indices=output_idx, input_range=(0., 1.))
plt.figure()
plt.title('Networks perception of {}'.format(output_idx))
plt.imshow(img[..., 0])
2.2 图像遮挡
def iter_occlusion(image, size=8):
occlusion = np.full((size * 5, size * 5, 1), [0.5], np.float32)
occlusion_center = np.full((size, size, 1), [0.5], np.float32)
occlusion_padding = size * 2
# print('padding...')
image_padded = np.pad(image, ( \
(occlusion_padding, occlusion_padding), (occlusion_padding, occlusion_padding), (0, 0) \
), 'constant', constant_values = 0.0)
for y in range(occlusion_padding, image.shape[0] + occlusion_padding, size):
for x in range(occlusion_padding, image.shape[1] + occlusion_padding, size):
tmp = image_padded.copy()
tmp[y - occlusion_padding:y + occlusion_center.shape[0] + occlusion_padding, \
x - occlusion_padding:x + occlusion_center.shape[1] + occlusion_padding] \
= occlusion
tmp[y:y + occlusion_center.shape[0], x:x + occlusion_center.shape[1]] = occlusion_center
yield x - occlusion_padding, y - occlusion_padding, \
tmp[occlusion_padding:tmp.shape[0] - occlusion_padding, occlusion_padding:tmp.shape[1] - occlusion_padding]
i = 23 # 例如
data = val_x[i]
correct_class = np.argmax(val_y[i])
# model.predict的输入向量
inp = data.reshape(1, 28, 28, 1)
# matplotlib imshow函数的图片
img = data.reshape(28, 28)
# 遮盖
img_size = img.shape[0]
occlusion_size = 4
print('occluding...')
heatmap = np.zeros((img_size, img_size), np.float32)
class_pixels = np.zeros((img_size, img_size), np.int16)
from collections import defaultdict
counters = defaultdict(int)
for n, (x, y, img_float) in enumerate(iter_occlusion(data, size=occlusion_size)):
X = img_float.reshape(1, 28, 28, 1)
out = model.predict(X)
#print('#{}: {} @ {} (correct class: {})'.format(n, np.argmax(out), np.amax(out), out[0][correct_class]))
#print('x {} - {} | y {} - {}'.format(x, x + occlusion_size, y, y + occlusion_size))
heatmap[y:y + occlusion_size, x:x + occlusion_size] = out[0][correct_class]
class_pixels[y:y + occlusion_size, x:x + occlusion_size] = np.argmax(out)
counters[np.argmax(out)] += 1
3. 基于梯度的方法
3.1 显著性图
class_idx = 0
indices = np.where(val_y[:, class_idx] == 1.)[0]
# 从这里选取一些随机输入。
idx = indices[0]
# 让sanity检查选中的图像。
from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (18, 6)
plt.imshow(val_x[idx][..., 0])
from vis.visualization import visualize_saliency
from vis.utils import utils
from keras import activations
# 按名称搜索图层索引
# 或者,我们可以将其指定为-1,因为它对应于最后一层。
layer_idx = utils.find_layer_idx(model, 'preds')
# 用线性层替换softmax
model.layers[layer_idx].activation = activations.linear
model = utils.apply_modifications(model)
grads = visualize_saliency(model, layer_idx, filter_indices=class_idx, seed_input=val_x[idx])
# 可视化为热图。
plt.imshow(grads, cmap='jet')
# 线性层。
for class_idx in np.arange(10):
indices = np.where(val_y[:, class_idx] == 1.)[0]
idx = indices[0]
f, ax = plt.subplots(1, 4)
ax[0].imshow(val_x[idx][..., 0])
for i, modifier in enumerate([None, 'guided', 'relu']):
grads = visualize_saliency(model, layer_idx, filter_indices=class_idx,
seed_input=val_x[idx], backprop_modifier=modifier)
if modifier is None:
modifier = 'vanilla'
ax[i+1].set_title(modifier)
ax[i+1].imshow(grads, cmap='jet')
3.2 基于梯度的类激活图
from vis.visualization import visualize_cam
# 线性层。
for class_idx in np.arange(10):
indices = np.where(val_y[:, class_idx] == 1.)[0]
idx = indices[0]
f, ax = plt.subplots(1, 4)
ax[0].imshow(val_x[idx][..., 0])
for i, modifier in enumerate([None, 'guided', 'relu']):
grads = visualize_cam(model, layer_idx, filter_indices=class_idx,
seed_input=val_x[idx], backprop_modifier=modifier)
if modifier is None:
modifier = 'vanilla'
ax[i+1].set_title(modifier)
ax[i+1].imshow(grads, cmap='jet')
赞 (0)