《深度学习 第五章 深度学习用于计算机视觉3》

卷积神经网络可视化

深度学习模型很多很难可视化,但卷积神经网络学到的表示非常适合可视化
1.可视化中间激活
可视化中间激活,指对于给定输入,展示网络中各个卷积层,池化层的输出特征图,(输出通常被称为该层的激活,即激活函数的输出)

首先加载之前的‘cats_and_dogs_smal_2.h5’模型

from keras.models import load_model
model = load_model('cats_and_dogs_small_2.h5')
model.summary()

在这里插入图片描述

#导入模型
from keras.models import load_model
model = load_model('cats_and_dogs_small_2.h5')
#model.summary()

#预处理单张图片
img_path = 'E:\\dataset\\cats_and_dogs_small\\test\\cats\\cat.1700.jpg'

from keras.preprocessing import image
import numpy as np

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.

#print(img_tensor.shape)#其形状为(1,150,150,3)

#显示图片
import matplotlib.pyplot as plt

plt.imshow(img_tensor[0])#显示的是一个三维张量(150,150,3),即一张rgb图片
plt.show()

在这里插入图片描述

#用一个输入张量和一个输出张量列表将模型实例化
from keras import models

layer_outputs = [layer.output for layer in model.layers[:8]]#提取前八层的输出
activation_model = models.Model(inputs = model.input,outputs = layer_outputs)
#Model与Sequential模型不一样,Sequantial模型是n输入对应n输出,Model是一输入也可以n输出


#以预测模式运行模型
activations = activation_model.predict(img_tensor)
#返回八个Numpy数组组成的列表,每个层激活对应一个Numpy数组

在这里插入图片描述

first_layer_activation = activations[0]#第一个卷积层
print(first_layer_activation.shape)

(1, 148, 148, 32)
第一层的输出,一个大小为(148,148)的特征图,有32个通道

现在我们将第四个通道可视化:

#将第四个通道可视化
import matplotlib.pyplot as plt
plt.matshow(first_layer_activation[0,:,:,4],cmap = 'viridis')

在这里插入图片描述
可视化第七个通道:

#将第七个通道可视化
plt.matshow(first_layer_activation[0,:,:,7],cmap = 'viridis')

在这里插入图片描述
每个通道都是一个检测器,对不同的特征进行检测

下面对八层输出的所有通道可视化:

#对八层的输出的所有通道可视化
layer_names = []
for layer in model.layers[:8]:
    layer_names.append(layer.name) #对八层的名称进行储存,作为画图的时候使用
    
images_per_row = 16#一行画16个

for layer_name,layer_activation in zip(layer_names,activations):
    n_features = layer_activation.shape[-1]#取shape的最后一个数,即通道数
    size = layer_activation.shape[1]#取shape的第二个数,就是图片大小
    #layer_activation.shape表示为(n_features,size,size,3)
    
    n_cols = n_features//images_per_row #一行16个看能有多少列
    display_grid = np.zeros((size*n_cols,images_per_row*size))
    #构造一个大矩阵全为0,再往里铺图,像铺瓷砖一样
    
    for col in range(n_cols):
        for row in range(images_per_row):
            channel_image = layer_activation[0,:,:,col*images_per_row + row]
            #选中第col行row列的图片,就是当前通道的输出
            
            #对特征进行后处理,使其看上去美观
            channel_image -= channel_image.mean()
            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')

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以得到深度神经网络的重要特征,随着层数增加,层所提取的特征越来越抽象,更高层的激活包括对特定输入的信息越来越少,关于目标的信息越来越多(猫或狗的类别)

2.可视化卷积神经网络过滤器

3.可视化类激活的热力图
类激活图: 类激活图(CAM,class activation map)是与特定输出类别相关的二维分数网格,对于输入图像的每个位置进行计算,它表示每个位置对该类别的重要程度。
类激活图可视化:
类激活图可视化有助于了解一张图像的哪一部分让卷积神经网络做出了最终的分类决策。这有助于对卷积神经网络的决策过程进行调试,特别是分类错误的情况下。

同时,这种方法可以定位图像中的特定目标。

具体实现方法是:给定一张输入图像,对于一个卷积层的输出特征图,用类别相对于每一个通道的梯度对这个特征图中的每个通道进行加权。

###加载带有预训练权重的VGG16网络
from keras.applications.vgg16 import VGG16

model = VGG16(weights = 'imagenet')


###为VGG16模型预处理输入图像
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input,decode_predictions
import numpy as np
import matplotlib.pyplot as plt

img_path = 'E:/elephant.jpg'#图像存储路径
img = image.load_img(img_path,target_size = (224,224))#将图像大小调整为(224,224)
plt.imshow(img)
x = image.img_to_array(img)#将图片变成(224,224,3)的numpy数组
x = np.expand_dims(x,axis = 0)#添加一个维度,axis表示添加的维度的位置,这里是指在第一个位置加一个维度
#print(x.ndim)#添加维度后的维度,得到的是(1,224,224,3)形状的批量,一个批量包含一张图片
x = preprocess_input(x)

preds = model.predict(x)
print('这张图片可能是:',decode_predictions(preds,top = 1)[0][0][1])
print('可能性为:',decode_predictions(preds,top = 1)[0][0][2])
print('索引为:',np.argmax(preds[0]))

在这里插入图片描述
在这里插入图片描述
这里用的VGG16模型与前面特征提取时的VGG16模型不一样:
.keras\models文件夹下重新下载了一个模型:
vgg16_weights_tf_dim_ordering_tf_kernels.h5大概有500多M

元组的索引参考
在这里插入图片描述
top = 1,说明这里只看了可能性最大的一个分类

为了知道图像中哪部分信息是的最终识别出来非洲象,我们使用Grad-CAM算法

在这里插入代码片

**K.gradients(y,x)**用于求y关于x 的导数(梯度),(y和x可以是张量tensor也可以是张量列表,形如 [tensor1, tensor2, …, tensorn]),返回的是一个张量列表,列表长度是张量列表y的长度,列表元素是与x具有一样shape的张量。

grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]
african_elephant_output是(1,)张量,last_conv_layer.output是(1,7,7,512)张量,所以返回的是只有一个元素的(1,7,7,512)张量列表,grads取了列表中唯一一个元素。

###Grad-CAM算法,看哪些部分看起来最像非洲象
african_elephant_output = model.output[:,386]#预测向量中的‘非洲象’元素

last_conv_layer = model.get_layer('block5_conv3')#这是VGG16的最后一层

#'非洲象'类别相对于block5_conv3输出特征图的梯度,形状为(1,7,7,512)
grads = K.gradients(african_elephant_output,last_conv_layer.output)[0]

pooled_grads = K.mean(grads,axis = (0,1,2))
#得到的是一个形状为(512,)的向量,每个元素的前三个数(索引为0,1,2)的平均梯度大小

interate = K.function([model.input],[pooled_grads,last_conv_layer.output[0]])

pooled_grads_value,conv_layer_output_value = interate([x])
#pooled_grads_value是通道对‘大象’的重要程度
#conv_layer_output_value是特征图数组的512个通道,(14,14,512)

for i in range(512):
    conv_layer_output_value[:,:,i] *= pooled_grads_value[i]
#将特征图数组的每个通道乘以“这个通道对‘大象’的重要程度”

    
heatmap = np.mean(conv_layer_output_value,axis = -1)
#得到的特征图的通道平均值为类激活的热力图(14,14)



###热力图处理
heatmap = np.maximum(heatmap,0)
heatmap /= np.max(heatmap)
plt.matshow(heatmap)

在这里插入图片描述
思路就是:
先得到’非洲象’类别相对于block5_conv3输出特征图的梯度,形状为(1,7,7,512)
该梯度前三个数取平均值得到(512,)
在这里插入图片描述
得到pooled_grads_value是通道对‘大象’的重要程度;conv_layer_output_value是特征图数组的512个通道,(14,14,512),对应相乘,取所有通道的平均值得到heatmap,heatmap为一个(14,14)的图:
在这里插入图片描述
这里,因为我的当前环境下没有安装opencv,所以我们先将热力图保存下来:

#把热力图保存起来
import pickle
with open('E:/heatmap.pickle','wb')as f: #python路径要用反斜杠
    pickle.dump(heatmap,f) #将变量dump进f里面

热力图与原始图叠加:

###热力图与原始图叠加

#下载heatmap变量
import pickle
with open('E:/heatmap.pickle','rb') as f:
    heatmap = pickle.load(f)#从f文件中提取出heatmap
    
    
#叠加
import cv2
import numpy as np
import matplotlib.pyplot as plt

img_path = 'E:/elephant1.jpeg'
img = cv2.imread(img_path)

heatmap = cv2.resize(heatmap,(img.shape[1],img.shape[0]))#将heatmap调整为和img一样的大小

heatmap = np.uint8(255*heatmap)#将热力图转换为RGB格式

heatmap = cv2.applyColorMap(heatmap,cv2.COLORMAP_JET)#将热力图应用于原始图像

superimposed_img = heatmap * 0.4 + img #热力强度因子0.4

save_path = 'E:/elephant1_and_heatmap.jpg'
cv2.imwrite(save_path,superimposed_img) 

img_and_heatmap = plt.imread(save_path)
plt.imshow(img_and_heatmap)  

在这里插入图片描述
可以看到小象耳朵的激活强度较大,这是分辨为非洲象的关键地方

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
本课程适合具有一定深度学习基础,希望发展为深度学习计算机视觉方向的算法工程师和研发人员的同学们。基于深度学习计算机视觉是目前人工智能最活跃的领域,应用非常广泛,如人脸识别和无人驾驶中的机器视觉等。该领域的发展日新月异,网络模型和算法层出不穷。如何快速入门并达到可以从事研发的高度对新手和中级水平的学生而言面临不少的挑战。精心准备的本课程希望帮助大家尽快掌握基于深度学习计算机视觉的基本原理、核心算法和当前的领先技术,从而有望成为深度学习计算机视觉方向的算法工程师和研发人员。本课程系统全面地讲述基于深度学习计算机视觉技术的原理并进行项目实践。课程涵盖计算机视觉的七大任务,包括图像分类、目标检测、图像分割(语义分割、实例分割、全景分割)、人脸识别、图像描述、图像检索、图像生成(利用生成对抗网络)。本课程注重原理和实践相结合,逐篇深入解读经典和前沿论文70余篇,图文并茂破译算法难点, 使用思维导图梳理技术要点。项目实践使用Keras框架(后端为Tensorflow),学员可快速上手。通过本课程的学习,学员可把握基于深度学习计算机视觉的技术发展脉络,掌握相关技术原理和算法,有助于开展该领域的研究与开发实战工作。另外,深度学习计算机视觉方向的知识结构及学习建议请参见本人CSDN博客。本课程提供课程资料的课件PPT(pdf格式)和项目实践代码,方便学员学习和复习。本课程分为上下两部分,其中上部包含课程的前五章(课程介绍、深度学习基础、图像分类、目标检测、图像分割),下部包含课程的后四章(人脸识别、图像描述、图像检索、图像生成)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值