TensorFlow神经网络中间层的可视化

TensorFlow神经网络中间层的可视化

TensorFlow神经网络中间层的可视化

1. 训练网络并保存为.h5文件

我们使用AlexNet为例,任务是手写数字识别,训练集使用手写数字集(mnist)。

网络的结构(我们使用的是28x28的黑白图):

网络搭建和训练的代码

python 复制代码
# 最终版
import os.path
import tensorflow as tf
import matplotlib.pyplot as plt
import cv2


# 画出训练过程的准确率和损失值的图像
def plotTrainHistory(history, train, val):
	plt.plot(history[train])
	plt.plot(history[val])
	plt.title('Train History')
	plt.xlabel('Epoch')
	plt.ylabel(train)
	plt.legend(['train', 'validation'], loc = 'upper left')
	plt.show()


(xTrain, yTrain), (xTest, yTest) = tf.keras.datasets.mnist.load_data()

xTrain = tf.expand_dims(xTrain, axis = 3)
xTest = tf.expand_dims(xTest, axis = 3)
print(f"训练集数据大小:{xTrain.shape}")
print(f"训练集标签大小:{yTrain.shape}")
print(f"测试集数据大小:{xTest.shape}")
print(f"测试集标签大小:{yTest.shape}")

# 归一化
xTrainNormalize = tf.cast(xTrain, tf.float32) / 255
xTestNormalize = tf.cast(xTest, tf.float32) / 255
# 数据独热编码
yTrainOneHot = tf.keras.utils.to_categorical(yTrain)
yTestOneHot = tf.keras.utils.to_categorical(yTest)

model = tf.keras.models.Sequential([
	tf.keras.layers.Conv2D(
		filters = 96, kernel_size = 11, strides = 4, input_shape = (28, 28, 1),
		padding = 'SAME', activation = tf.keras.activations.relu
	),
	tf.keras.layers.BatchNormalization(),
	tf.keras.layers.MaxPool2D(pool_size = 3, strides = 2, padding = 'SAME'),
	tf.keras.layers.Conv2D(
		filters = 256, kernel_size = 5, strides = 1,
		padding = 'SAME', activation = tf.keras.activations.relu
	),
	tf.keras.layers.BatchNormalization(),
	tf.keras.layers.MaxPool2D(pool_size = 3, strides = 2, padding = 'SAME'),
	tf.keras.layers.Conv2D(
		filters = 384, kernel_size = 3, strides = 1,
		padding = 'SAME', activation = tf.keras.activations.relu
	),
	tf.keras.layers.Conv2D(
		filters = 384, kernel_size = 3, strides = 1,
		padding = 'SAME', activation = tf.keras.activations.relu
	),
	tf.keras.layers.Conv2D(
		filters = 256, kernel_size = 3, strides = 1,
		padding = 'SAME', activation = tf.keras.activations.relu
	),
	tf.keras.layers.MaxPool2D(pool_size = 3, strides = 2, padding = 'SAME'),
	tf.keras.layers.Flatten(),
	tf.keras.layers.Dense(4096, activation = tf.keras.activations.relu),
	tf.keras.layers.Dropout(0.5),
	tf.keras.layers.Dense(4096, activation = tf.keras.activations.relu),
	tf.keras.layers.Dropout(0.5),
	tf.keras.layers.Dense(10, activation = tf.keras.activations.softmax)
])


weightsPath = './AlexNetModel/'

callback = tf.keras.callbacks.ModelCheckpoint(
	filepath = weightsPath,
	save_best_only = True,
	save_weights_only = True,
	verbose = 1
)

model.compile(
	loss = tf.keras.losses.CategoricalCrossentropy(),
	optimizer = tf.keras.optimizers.Adam(),
	metrics = ['accuracy']
)

model.summary()

# 不存在就训练模型
print('参数文件不存在,即将训练模型')
modelTrain = model.fit(
	xTrainNormalize, yTrainOneHot, validation_split = 0.2,
	epochs = 20, batch_size = 300, verbose = 1, callbacks = [callback]
)
model.save("./model.h5")
plotTrainHistory(modelTrain.history, 'loss', 'val_loss')
plotTrainHistory(modelTrain.history, 'accuracy', 'val_accuracy')

2. 通过.h5文件导入网络

把刚才训练得到的模型重新读取,并且重新加载数据集

python 复制代码
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np


def plot_images(images, number, path, title, gray = False):
    plt.figure()
    plt.title(title)
    order = 1
    for i in range(0, number):

        plt.subplot(3, 3, order)
        if gray:
            plt.imshow(images[:, :, 0, i], cmap = 'gray')
        else:
            plt.imshow(images[:, :, 0, i])
        plt.colorbar()
        order = order + 1

    plt.savefig("./{}.png".format(path))
    plt.show()


if __name__ == '__main__':
    weightsPath = './AlexNetModel/'
    (xTrain, yTrain), (xTest, yTest) = tf.keras.datasets.mnist.load_data()

    xTrain = tf.expand_dims(xTrain, axis = 3)
    xTest = tf.expand_dims(xTest, axis = 3)
    # print(f"训练集数据大小:{xTrain.shape}")
    # print(f"训练集标签大小:{yTrain.shape}")
    # print(f"测试集数据大小:{xTest.shape}")
    # print(f"测试集标签大小:{yTest.shape}")

    # 归一化
    xTrainNormalize = tf.cast(xTrain, tf.float32) / 255
    xTestNormalize = tf.cast(xTest, tf.float32) / 255
    # 数据独热编码
    yTrainOneHot = tf.keras.utils.to_categorical(yTrain)
    yTestOneHot = tf.keras.utils.to_categorical(yTest)

    model = tf.keras.models.load_model("model.h5")
    model.summary()
    print('Layer Number', len(model.layers))

    sample = xTrainNormalize[0]
    plt.imshow(sample)
    plt.colorbar()
    plt.savefig('./train.png')

3. 可视化网络中间层结果

测试的数字,5

(1)索引取层可视化

model.layers 中存放着这个神经网络的全部层,它是一个list类型变量

AlexNet一共16层(卷积层、全连接层、池化层等都算入),全部存储在里面

python 复制代码
model = tf.keras.models.load_model("model.h5")
print('Layer Number', len(model.layers))

可视化的时候我们取出一部分层,然后来预测,预测结果就是取出来这部分层的结果,因此就看到了中间层的结果

python 复制代码
output = tf.keras.models.Sequential([
    tf.keras.layers.InputLayer(input_shape = (28, 28, 1)),
    model.layers[0],
    model.layers[1],
    model.layers[2],
]).predict(sample)
print('output.shape', output.shape)
plot_images(output, 9, '5_Conv2D_BN_MP_1', str(output.shape))

查看三层的结果,即Conv2D+BN+MaxPool,结果是 (28, 4, 1, 96),这里画出前9个

把这96个叠加在一起的结果

python 复制代码
t = output[:, :, 0, 0]
for i in range(1, output.shape[3]):
    t = t + output[:, :, 0, i]
plt.imshow(t)
plt.colorbar()
plt.savefig('./5_Conv2D_BN_MP_1_All.png')

下面的代码是画出神经网络三个中间层的结果

python 复制代码
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np


def plot_images(images, number, path, title, gray = False):
    plt.figure()
    plt.title(title)
    order = 1
    for i in range(0, number):

        plt.subplot(3, 3, order)
        if gray:
            plt.imshow(images[:, :, 0, i], cmap = 'gray')
        else:
            plt.imshow(images[:, :, 0, i])
        plt.colorbar()
        order = order + 1

    plt.savefig("./{}.png".format(path))
    plt.show()


if __name__ == '__main__':
    weightsPath = './AlexNetModel/'
    (xTrain, yTrain), (xTest, yTest) = tf.keras.datasets.mnist.load_data()

    xTrain = tf.expand_dims(xTrain, axis = 3)
    xTest = tf.expand_dims(xTest, axis = 3)
    # print(f"训练集数据大小:{xTrain.shape}")
    # print(f"训练集标签大小:{yTrain.shape}")
    # print(f"测试集数据大小:{xTest.shape}")
    # print(f"测试集标签大小:{yTest.shape}")

    # 归一化
    xTrainNormalize = tf.cast(xTrain, tf.float32) / 255
    xTestNormalize = tf.cast(xTest, tf.float32) / 255
    # 数据独热编码
    yTrainOneHot = tf.keras.utils.to_categorical(yTrain)
    yTestOneHot = tf.keras.utils.to_categorical(yTest)

    model = tf.keras.models.load_model("model.h5")
    model.summary()
    print('Layer Number', len(model.layers))

    sample = xTrainNormalize[0]
    plt.imshow(sample)
    plt.colorbar()
    plt.savefig('./train.png')

    output = tf.keras.models.Sequential([
        tf.keras.layers.InputLayer(input_shape = (28, 28, 1)),
        model.layers[0],
        model.layers[1],
        model.layers[2],
    ]).predict(sample)
    print('output.shape', output.shape)
    plot_images(output, 9, '5_Conv2D_BN_MP_1', str(output.shape))

    t = output[:, :, 0, 0]
    for i in range(1, output.shape[3]):
        t = t + output[:, :, 0, i]
    plt.imshow(t)
    plt.colorbar()
    plt.savefig('./5_Conv2D_BN_MP_1_All.png')

    output = tf.keras.models.Sequential([
        tf.keras.layers.InputLayer(input_shape=(28, 28, 1)),
        model.layers[0],
        model.layers[1],
        model.layers[2],
        model.layers[3],
        model.layers[4],
        model.layers[5],
    ]).predict(sample)
    print('output.shape', output.shape)
    plot_images(output, 9, '5_Conv2D_BN_MP_2', str(output.shape))

    t = output[:, :, 0, 0]
    for i in range(1, output.shape[3]):
        t = t + output[:, :, 0, i]
    plt.imshow(t)
    plt.colorbar()
    plt.savefig('./5_Conv2D_BN_MP_2_All.png')

    output = tf.keras.models.Sequential([
        tf.keras.layers.InputLayer(input_shape=(28, 28, 1)),
        model.layers[0],
        model.layers[1],
        model.layers[2],
        model.layers[3],
        model.layers[4],
        model.layers[5],
        model.layers[6],
        model.layers[7],
        model.layers[8],
        model.layers[9],
    ]).predict(sample)
    print('output.shape', output.shape)
    plot_images(output, 9, '5_Conv2D_3_MP', str(output.shape))

    t = output[:, :, 0, 0]
    for i in range(1, output.shape[3]):
        t = t + output[:, :, 0, i]
    plt.imshow(t)
    plt.colorbar()
    plt.savefig('./5_Conv2D_3_MP_All.png')

0和5的结果

(2)通过名字取层可视化

模型的**summary()**成员函数可以查看网络每一层名字和参数情况

python 复制代码
model.summary()

博客中使用的AlexNet每一层名字和参数情况

通过名字来取中间层,并且预测得到中间层可视化结果

如果我们要看这个池化层的结果,这样写代码

python 复制代码
model = tf.keras.models.load_model("../model.h5")
model.summary()

sample = xTrainNormalize[0]
plt.imshow(sample)
plt.colorbar()
plt.savefig('./train.png')

output = tf.keras.models.Model(
    inputs=model.get_layer('conv2d').input,
    outputs=model.get_layer('max_pooling2d').output
).predict(sample)

通过get_layer获取指定名字的层

inputs指定输入层,outputs指定输出层

每一层的名字可以在创建的时候使用name参数指定

python 复制代码
...
tf.keras.layers.Conv2D(
		filters = 96, kernel_size = 11, strides = 4, input_shape = (28, 28, 1),
		padding = 'SAME', activation = tf.keras.activations.relu, name = 'Conv2D_1'
	),
...

每一层的名字红色框框出

下面是例子:

python 复制代码
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np


def plot_images(images, number, path, title, gray = False):
    plt.figure()
    plt.title(title)
    order = 1
    for i in range(0, number):

        plt.subplot(3, 3, order)
        if gray:
            plt.imshow(images[:, :, 0, i], cmap = 'gray')
        else:
            plt.imshow(images[:, :, 0, i])
        plt.colorbar()
        order = order + 1

    plt.savefig("./{}.png".format(path))
    plt.show()


if __name__ == '__main__':
    (xTrain, yTrain), (xTest, yTest) = tf.keras.datasets.mnist.load_data()

    xTrain = tf.expand_dims(xTrain, axis = 3)
    xTest = tf.expand_dims(xTest, axis = 3)

    # 归一化
    xTrainNormalize = tf.cast(xTrain, tf.float32) / 255
    xTestNormalize = tf.cast(xTest, tf.float32) / 255
    # 数据独热编码
    yTrainOneHot = tf.keras.utils.to_categorical(yTrain)
    yTestOneHot = tf.keras.utils.to_categorical(yTest)

    model = tf.keras.models.load_model("../model.h5")
    model.summary()

    sample = xTrainNormalize[0]
    plt.imshow(sample)
    plt.colorbar()
    plt.savefig('./train.png')

    output = tf.keras.models.Model(
        inputs=model.get_layer('conv2d').input,
        outputs=model.get_layer('max_pooling2d').output
    ).predict(sample)

    # output = tf.keras.models.Sequential([
    #     tf.keras.layers.InputLayer(input_shape = (28, 28, 1)),
    #     model.layers[0],
    #     model.layers[1],
    #     model.layers[2],
    # ]).predict(sample)
    print('output.shape', output.shape)
    # plot_images(output, 9, '5_Conv2D_BN_MP_1', str(output.shape))
相关推荐
AWS官方合作商26 分钟前
Amazon Lex:AI对话引擎重构企业服务新范式
人工智能·ai·机器人·aws
workflower30 分钟前
Prompt Engineering的重要性
大数据·人工智能·设计模式·prompt·软件工程·需求分析·ai编程
curemoon1 小时前
理解都远正态分布中指数项的精度矩阵(协方差逆矩阵)
人工智能·算法·矩阵
胡桃不是夹子2 小时前
CPU安装pytorch(别点进来)
人工智能·pytorch·python
Fansv5872 小时前
深度学习-6.用于计算机视觉的深度学习
人工智能·深度学习·计算机视觉
xjxijd2 小时前
AI 为金融领域带来了什么突破?
人工智能·其他
SKYDROID云卓小助手2 小时前
无人设备遥控器之如何分享数传篇
网络·人工智能·算法·计算机视觉·电脑
deephub2 小时前
LLM高效推理:KV缓存与分页注意力机制深度解析
人工智能·深度学习·语言模型
奋斗的袍子0073 小时前
Spring AI + Ollama 实现调用DeepSeek-R1模型API
人工智能·spring boot·深度学习·spring·springai·deepseek
青衫弦语3 小时前
【论文精读】VLM-AD:通过视觉-语言模型监督实现端到端自动驾驶
人工智能·深度学习·语言模型·自然语言处理·自动驾驶