目录标题
- 中间特征层可视化
- 导入ImageNet VGG16网络
- 加载任一图片
- 构建多特征层输出模型
- 所有中间层的显示
- 参考
中间特征层可视化
导入ImageNet VGG16网络
导入基础包
1 2 3 | import numpy as np import matplotlib.pyplot as plt import tensorflow as tf |
导入ImageNet VGG16网络
1 2 | VGG16_model = tf.keras.applications.VGG16(include_top=True) VGG16_model.summary() |
加载任一图片
随便网上找一张图,比如使用率最高的猫星人
读取本地图片
1 2 3 4 5 6 7 8 9 10 11 12 | 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模型
1 2 3 | 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层的模型 |
图片输入网络,输出各中间层的特征
1 2 3 | input_image=tf.expand_dims(img, 0) # 扩维 activations = activation_model.predict(input_image) #12组特征层输出 activations[0].shape #对应summary表中的内容跟,0层对应输入层 |
举例展示第1卷积层的第1和第2特征层
1 2 | plt.matshow(activations[1][0,:,:,0], cmap='viridis') #第1卷积层的第1特征层输出 plt.matshow(activations[1][0,:,:,1], cmap='viridis') #第1卷积层的第0特征层输出 |
可以看出第1特征层主要捕获了猫星人的轮廓特征,第2特征层主要捕获毛脸部的特征
所有中间层的显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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》