前面一个博客,介绍了训练之类的详情:https://blog.csdn.net/qq_43433255/article/details/93855517
下面,就用得到.h5文件继续。
这里是所有的头文件的汇总:
import keras
keras.__version__
from keras.models import load_model
from keras.preprocessing import image
import numpy as np
from keras import models
import matplotlib.pyplot as plt
from keras.applications import VGG16
from keras import backend as K
因为使用的是anaconda下的python,后面一步一步运行的时候,我也会贴上引入的库,
import keras
keras.__version__
from keras.models import load_model
model = load_model('G:\\WangLuoRuanJian\\Pythondaima\\qianrushi\\cats_and_dogs_small_2.h5')
model.summary() # 作为提醒
from keras.preprocessing import image
import numpy as np
img_path = 'G:/2018and2019two/qianrushi/kaggle_dogandcat_small/test/cats/cat.1700.jpg'
#我们将图像预处理成4d张量。
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.
#它的形状是(1150,150,3)
print(img_tensor.shape)
plt.imshow(img_tensor[0])
plt.show()
from keras import models
import matplotlib.pyplot as plt
'''
为了提取我们想要查看的特征图,我们将创建一个以成批图像为输入的keras模型,并输出所有卷积和池层的激活。为此,我们将使用keras类模型。使用两个参数来实例化模型:输入张量(或输入张量列表)和输出张量(或输出张量列表)。结果类是一个keras模型,就像您熟悉的顺序模型一样,将指定的输入映射到指定的输出。使模型类与众不同的是,它允许具有多个输出的模型,与顺序的不同。
'''
#提取前8层的输出:
layer_outputs = [layer.output for layer in model.layers[:8]]
#创建一个将返回这些输出的模型,给定模型输入:
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
#这将返回5个numpy数组的列表:
#每层激活一个阵列
activations = activation_model.predict(img_tensor)
first_layer_activation = activations[0]
print(first_layer_activation.shape)
plt.matshow(first_layer_activation[0, :, :, 3], cmap='viridis')
plt.show()
#这个通道似乎编码了一个对角边缘检测器。
#让我们试试第30个通道——但是请注意,您自己的通道可能会有所不同,
#因为卷积层学习的特定过滤器并不具有确定性。
plt.matshow(first_layer_activation[0, :, :, 30], cmap='viridis')
plt.show()
import keras
#这些是图层的名称,因此可以将它们作为绘图的一部分
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]
#功能图具有形状(1, size, size, n_features)
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()
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.applications import VGG16
from keras import backend as K
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])
#对“渐变”的调用返回张量列表 (of size 1 in this case)
#因此我们只保留第一个元素——张量。
grads = K.gradients(loss, model.input)[0]
#我们在除法之前加上1e-5,以避免意外地被0除法。
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
iterate = K.function([model.input], [loss, grads])
# 测试它
import numpy as np
loss_value, grads_value = iterate([np.zeros((1, 150, 150, 3))])
#我们从有噪声的灰色图像开始
input_img_data = np.random.random((1, 150, 150, 3)) * 20 + 128.
#这是每个梯度更新的幅度
step = 1.
for i in range(40):
#计算损失值和梯度值
loss_value, grads_value = iterate([input_img_data])
#在这里,我们调整输入图像的方向,使损失最大化。
input_img_data += grads_value * step
def deprocess_image(x):
#归一化张量:以0为中心,确保std为0.1。
x -= x.mean()
x /= (x.std() + 1e-5)
x *= 0.1
# 剪辑到 [0, 1]
x += 0.5
x = np.clip(x, 0, 1)
# 转换为RGB数组
x *= 255
x = np.clip(x, 0, 255).astype('uint8')
return x
def generate_pattern(layer_name, filter_index, size=150):
#构建一个最大化激活的丢失函数
#所考虑层的第n个过滤器。
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.
#40层
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)
plt.imshow(generate_pattern('block3_conv1', 0))
plt.show()
for layer_name in ['block1_conv1', 'block2_conv1', 'block3_conv1', 'block4_conv1']:
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): #遍历结果网格的列
#在层名称中为筛选器'i+(j*8)'生成模式`
filter_img = generate_pattern(layer_name, i + (j * 8), size=size)
#将结果放入结果网格的平方`(i,j)`
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))
plt.imshow(results)
plt.show()
plt.imshow(img_tensor[0])
plt.show()
这些过滤器可视化告诉我们很多关于convnet层如何看待世界的信息;
convnet中的每一层都只是学习一组过滤器,这样它们的输入就可以表示为过滤器的组合。这类似于傅立叶变换如何将信号分解成一组余弦函数。随着我们在模型中的提升,这些convnet过滤器组中的过滤器变得越来越复杂和精细;
模型中第一层的过滤器(block1_conv1)编码简单的方向性边和颜色(在某些情况下为彩色边);
Block2_Conv1的过滤器对由边和颜色组合而成的简单纹理进行编码。
更高层的过滤器开始类似于自然图像中的纹理:羽毛、眼睛、树叶等。
参考链接:https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.4-visualizing-what-convnets-learn.ipynb