如何可视化Keras卷积神经网络(CNN)中的滤波器?附模型构建代码
如何可视化Keras卷积神经网络中的滤波器
嘿,我来给你一步步拆解怎么可视化你这个Keras CNN里的卷积滤波器,结合你提供的模型代码,咱们实操起来~
先理清楚你的模型结构
先看你写的build_model函数,第一个卷积层Conv2D(6, (5,5), ...)定义了6个5×5大小的滤波器,输入是3通道的RGB图像(input_shape=(32,32,3)),所以这个层的权重形状是(5,5,3,6)——你代码里也打印了这个形状,完全正确。第二个卷积层有16个5×5滤波器,输入是6通道(第一个卷积层的输出),所以权重形状是(5,5,6,16)。
步骤1:准备工作&构建模型
首先确保你导入了需要的库,然后构建好你的模型:
import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense def build_model(): model = Sequential() model.add(Conv2D(6, (5,5), padding='valid', activation = 'relu', kernel_initializer='he_normal', input_shape=(32,32,3))) print(np.asarray(model.get_weights())[0].shape) # 输出 (5,5,3,6) model.add(MaxPooling2D((2, 2), strides=(2, 2))) model.add(Conv2D(16, (5,5), padding='valid', activation = 'relu', kernel_initializer='he_normal')) model.add(MaxPooling2D((2, 2), strides=(2, 2))) model.add(Flatten()) model.add(Dense(120, activation = 'relu', kernel_initializer='he_normal')) # 补充你省略的输出层,比如假设是10分类任务 model.add(Dense(10, activation='softmax')) return model # 实例化模型 model = build_model()
步骤2:获取卷积层的权重
卷积层的权重存储在get_weights()方法返回的列表里,第一个元素是核权重(就是我们要可视化的滤波器),第二个是偏置(不用管它):
# 获取第一个卷积层的滤波器权重 conv1_filters = model.layers[0].get_weights()[0] print(f"第一个卷积层权重形状:{conv1_filters.shape}") # 输出 (5,5,3,6) # 获取第二个卷积层的滤波器权重 conv2_filters = model.layers[2].get_weights()[0] print(f"第二个卷积层权重形状:{conv2_filters.shape}") # 输出 (5,5,6,16)
步骤3:归一化权重(关键!)
滤波器的权重值范围可能很大(比如从-2到2),直接显示会导致图像一片黑或者一片白,所以我们要把值缩放到0-1之间:
def normalize_weights(weights): min_val = np.min(weights) max_val = np.max(weights) # 归一化到0-1区间 return (weights - min_val) / (max_val - min_val) # 对两个卷积层的权重分别归一化 norm_conv1 = normalize_weights(conv1_filters) norm_conv2 = normalize_weights(conv2_filters)
步骤4:可视化滤波器
可视化第一个卷积层(RGB滤波器)
第一个卷积层的每个滤波器是5×5×3的RGB格式,可以直接用imshow显示:
# 设置子图布局:2行3列(因为有6个滤波器) rows, cols = 2, 3 plt.figure(figsize=(10, 6)) for i in range(6): # 取出第i个滤波器 filter = norm_conv1[:, :, :, i] # 绘制子图 plt.subplot(rows, cols, i+1) plt.imshow(filter) plt.title(f"Filter {i+1}") plt.axis('off') # 关闭坐标轴,让图像更清爽 plt.tight_layout() # 自动调整子图间距 plt.show()
如果你的模型已经训练过,这些滤波器会显示出学到的特征(比如边缘、颜色块、纹理);如果是刚初始化的模型,就是随机权重,看起来比较杂乱。
可视化第二个卷积层(多通道滤波器)
第二个卷积层的每个滤波器是5×5×6的多通道(对应第一个卷积层的6个输出通道),没法直接用RGB显示,我们可以把多通道转成灰度图(比如取通道平均值):
# 设置子图布局:4行4列(16个滤波器) rows, cols = 4, 4 plt.figure(figsize=(12, 8)) for i in range(16): # 取出第i个滤波器 filter = norm_conv2[:, :, :, i] # 转成灰度图:取所有通道的平均值 filter_gray = np.mean(filter, axis=2) # 绘制灰度图 plt.subplot(rows, cols, i+1) plt.imshow(filter_gray, cmap='gray') plt.title(f"Filter {i+1}") plt.axis('off') plt.tight_layout() plt.show()
小提示
- 如果你的模型是训练好的,记得先加载训练后的权重(
model.load_weights('your_weights.h5'))再可视化,这样看到的是模型真正学到的特征。 - 对于更深的卷积层,滤波器会捕捉更抽象的特征(比如物体部件、轮廓),而浅层滤波器一般捕捉基础的边缘、颜色。
内容的提问来源于stack exchange,提问作者nirvair




