使用Tensorflow实现可视化中间层和卷积层

1. 简介

在深度学习中,可视化中间层和卷积层可以帮助我们更好地理解神经网络的运作方式和优化空间,从而更好地优化模型。在使用Tensorflow训练模型时,我们可以使用tf.keras模块提供的可视化工具,通过plot_model函数将模型的结构可视化出来,也可以使用Tensorboard可视化训练过程中的指标和图像。本文将以MNIST数据集为例,介绍使用Tensorflow实现可视化中间层和卷积层的方法。

2. 数据集处理和模型构建

2.1 数据集处理

在MNIST数据集上训练一个简单的神经网络来进行图像分类。

我们可以使用tf.keras.datasets中的mnist.load_data()加载MNIST数据集。对于每个样本,它将是28×28的灰度图像,所以每个样本都是一个有784个整数的一维数组。我们需要将数据处理成0~1之间的浮点数,并对标签进行one-hot编码。

import tensorflow as tf

from tensorflow import keras

from tensorflow.keras import layers

import numpy as np

# 载入数据集

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# 图像归一化(0~1)

x_train = x_train.astype("float32") / 255.0

x_test = x_test.astype("float32") / 255.0

# one-hot标签编码

y_train = keras.utils.to_categorical(y_train, num_classes=10)

y_test = keras.utils.to_categorical(y_test, num_classes=10)

2.2 模型构建

在使用Tensorflow实现可视化中间层和卷积层之前,我们首先需要构建一个简单的神经网络模型。

这里我们使用两个卷积层和一个全连接层。每个卷积层的输出通过ReLU激活函数进行非线性变换,第一个卷积层还包含Max Pooling操作。

inputs = keras.Input(shape=(28, 28, 1))

x = layers.Conv2D(filters=32, kernel_size=(3, 3), activation="relu")(inputs)

x = layers.MaxPooling2D(pool_size=(2, 2))(x)

x = layers.Conv2D(filters=64, kernel_size=(3, 3), activation="relu")(x)

x = layers.Flatten()(x)

x = layers.Dense(units=128, activation="relu")(x)

outputs = layers.Dense(units=10, activation="softmax")(x)

model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")

model.summary()

3. 可视化中间层和卷积层

3.1 中间层可视化

在我们的模型中,我们可以使用keras的Model类创建一个新的Model,其输入输出是相同的,但中间层输出也被设置为输出,从而方便我们对中间层进行可视化。

下面的代码使用x_train作为输入,创建一个新的Model,并输出第1个和第2个卷积层的中间输出(features1和features2)。

# 输入张量

inputs = model.input

# 输出第1个和第2个卷积层的中间输出(features1和features2)

features1_layer = model.get_layer("conv2d")

features2_layer = model.get_layer("conv2d_1")

features1 = features1_layer(inputs)

features2 = features2_layer(features1)

new_model = keras.Model(inputs=inputs, outputs=[features1, features2])

# 对x_train的前16个样本进行中间层可视化

features1, features2 = new_model.predict(x_train[:16])

# 可视化

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))

for i in range(16):

plt.subplot(4, 8, 2*i+1)

plt.imshow(x_train[i], cmap='gray')

plt.axis('off')

plt.subplot(4, 8, 2*i+2)

plt.imshow(features1[i, :, :, 0], cmap='gray')

plt.axis('off')

plt.show()

运行后可以看到,左边的图像是原始图像,右边的图像是第一个卷积层的中间输出。可以看到,第一个卷积层的中间层提取了图像的一些边缘细节和特征。

3.2 卷积层可视化

在卷积层中,我们可以通过获取卷积核的权重(w)和卷积层的中间输出(x)计算出卷积层的输出(y=w*x)。然后可以反卷积来可视化卷积层输出。

下面的代码演示了如何使用keras-vis库中的反卷积器(Deconvolution2D)来可视化卷积层的输出。

!pip install keras-vis

# 可视化第1个卷积层的输出

from vis.visualization import visualize_activation

from vis.input_modifiers import Jitter

# 获取第1个卷积层的权重

conv_weights = model.layers[1].get_weights()[0]

# 定义slice_num为可视化输出的切片数,这里定义为8

slice_num = 8

# 反卷积可视化

plt.figure(figsize=(20, 4*slice_num))

for i in range(slice_num):

# 计算卷积层输出

activation = visualize_activation(model, layer_idx=1, filter_indices=i, input_modifiers=[Jitter(16)])

# 手动计算卷积层输出

input_index = int(np.where(model.layers[1] == inputs)[0])

output_index = int(np.where(model.layers[2] == features1)[0])

y = np.array([features1[0,:,:,i]])

for i in range(y.shape[-1]):

y[:,:,i]=(conv_weights[:,:,i,:]*y).sum(axis=(-3))

# 显示原始图像和卷积层输出

plt.subplot(slice_num, 2, 2*i+1)

plt.imshow(x_train[0], cmap='gray')

plt.axis('off')

plt.subplot(slice_num, 2, 2*i+2)

plt.imshow(y[0], cmap='gray')

plt.axis('off')

plt.show()

上述可视化输出了第一个卷积层8个卷积核的输出。可以看到,卷积层的输出对原始图像进行了边缘和形状的加强。

4. 结论

本文介绍了使用Tensorflow实现可视化中间层和卷积层的方法,并使用MNIST数据集和一个简单的神经网络模型进行了演示。中间层可视化可以帮助我们更好地理解神经网络的结构和特征提取过程,卷积层可视化可以让我们看到卷积层对图像的激活模式,这些对于理解和优化模型都有帮助。读者可以根据自己的需求对代码进行优化和修改。

后端开发标签