导入基础包
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
导入ImageNet VGG16网络
VGG16_model = tf.keras.applications.VGG16(include_top=True)
VGG16_model.summary()
def prepocess(x):
x = tf.io.read_file(x)
x = tf.image.decode_jpeg(x, channels=3)
print(x.shape)
x = tf.image.resize(x, [224,224])
x = tf.cast(x, dtype=tf.float32)/255.
return x
img_path='Cat.jpg'
img=prepocess(img_path)
plt.figure()
plt.imshow(img)
对模型中16层特征层建立输出layers和多输出model模型
from tensorflow.keras import models
layer_outputs = [layer.output for layer in VGG16_model.layers[:16]] #前16层输出
activation_model = models.Model(inputs=VGG16_model.input, outputs=layer_outputs) #构建能够输出前16层的模型
图片输入网络,输出各中间层的特征
input_image=tf.expand_dims(img, 0) # 扩维
activations = activation_model.predict(input_image) #12组特征层输出
activations[0].shape #0对应summary表中的输入层
(1, 224, 224, 3)
plt.matshow(activations[1][0,:,:,0], cmap='viridis') #第1卷积层的第1特征层输出
plt.matshow(activations[1][0,:,:,1], cmap='viridis') #第1卷积层的第0特征层输出
可以看出第1特征层主要捕获了猫星人的轮廓特征,第2特征层主要捕获毛脸部的特征
layer_names = []
for layer in VGG16_model.layers[:16]:
layer_names.append(layer.name) #特征层的名字
images_per_row=16
for layer_name, layer_activation in zip (layer_names[1:16], activations[1:16]):
n_feature = layer_activation.shape[-1] # 每层输出的特征层数
size = layer_activation.shape[1] #每层的特征大小
n_cols = n_feature//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): #平铺每行
# print(layer_activation.shape)
# print(col*images_per_row+row)
channel_image = layer_activation[0,:,:,col*images_per_row+row] # 写入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')
# print(channel_image.shape)
# print(display_grid[col*size:(col+1)*size, row*size:(row+1)*size].shape)
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')
康康结果,确实符合随着层数的加深,激活变得越来越抽象,以及激活的稀疏度(sparsity)随着层数的加深而增大的预期结果。
《Deep Learning with Python》