You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何可视化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

火山引擎 最新活动