# coding: utf-8 import sys, os sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定 import numpy as np import matplotlib.pyplot as plt from simple_convnet import SimpleConvNet # 导入自定义的简单卷积神经网络 from matplotlib.image import imread # 用于读取图片 from common.layers import Convolution # 导入卷积层类 def filter_show(filters, nx=4, show_num=16): """ 显示卷积层学习到的滤波器权重(即可视化卷积核)。 参数: filters: 卷积层的权重 (形状: [滤波器数, 通道数, 高, 宽]) nx: 每行显示多少个滤波器 show_num: 要显示的滤波器数量 """ FN, C, FH, FW = filters.shape # 获取滤波器的数量、通道数、高度和宽度 ny = int(np.ceil(show_num / nx)) # 计算需要显示多少行滤波器 fig = plt.figure() # 创建画布 fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05) # 调整子图间距 for i in range(show_num): # 遍历每一个要显示的滤波器 ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[]) # 创建 4x4 子图布局 ax.imshow(filters[i, 0], cmap=plt.cm.gray_r, interpolation='nearest') # 显示滤波器(取第1通道) # 创建一个简单卷积神经网络 network = SimpleConvNet(input_dim=(1,28,28), # 输入维度为 (通道数=1, 高=28, 宽=28) conv_param = {'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1}, # 卷积层参数 hidden_size=100, # 隐藏层神经元数量 output_size=10, # 输出层神经元数量(10分类) weight_init_std=0.01) # 权重初始化标准差 # 载入训练好的参数 network.load_params("params.pkl") # 可视化卷积层权重 filter_show(network.params['W1'], 16) # 读取灰度图片 img = imread('../dataset/lena_gray.png') img = img.reshape(1, 1, *img.shape) # 调整图片形状为 (批次, 通道, 高, 宽) fig = plt.figure() w_idx = 1 # 要可视化的卷积核索引 # 遍历前16个卷积核,对图像进行卷积并显示输出特征图 for i in range(16): w = network.params['W1'][i] # 获取第 i 个卷积核权重 b = 0 # 设置偏置为0(忽略原始偏置) w = w.reshape(1, *w.shape) # 调整卷积核形状为 (输出通道数, 输入通道数, 高, 宽) conv_layer = Convolution(w, b) # 创建卷积层对象 out = conv_layer.forward(img) # 对图像进行卷积 out = out.reshape(out.shape[2], out.shape[3]) # 去掉通道维度,调整输出形状 ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[]) # 创建 4x4 子图布局 ax.imshow(out, cmap=plt.cm.gray_r, interpolation='nearest') # 显示卷积结果 plt.show() # 显示所有图像
✅ 1. 导入库与路径设置
import sys, os sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定 import numpy as np import matplotlib.pyplot as plt from simple_convnet import SimpleConvNet from matplotlib.image import imread from common.layers import Convolution
-
这里设置了
sys.path.append(os.pardir)
,把父目录加入 Python 路径,目的是为了能够导入父目录下的模块simple_convnet
和common.layers
。 -
SimpleConvNet
是一个简单卷积神经网络的封装类。 -
Convolution
是定义卷积层的类。 -
用
imread
读取灰度图像。
✅ 2. 显示卷积核
def filter_show(filters, nx=4, show_num=16): """ filters: 卷积核权重 nx: 横向排列多少个 show_num: 总共显示多少个卷积核 """ FN, C, FH, FW = filters.shape # FN=卷积核个数, C=输入通道数, FH/FW=卷积核尺寸 ny = int(np.ceil(show_num / nx)) # 计算纵向排列的数量 fig = plt.figure() fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05) for i in range(show_num): ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[]) ax.imshow(filters[i, 0], cmap=plt.cm.gray_r, interpolation='nearest')
-
作用:
-
将卷积核
filters
可视化。 -
这里只显示每个卷积核第一个通道(因为输入是灰度图,C=1)。
-
-
使用
plt.cm.gray_r
是为了反转灰度,使得卷积核特征更清晰。
✅ 3. 创建神经网络 & 加载权重
network = SimpleConvNet(input_dim=(1,28,28), conv_param = {'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1}, hidden_size=100, output_size=10, weight_init_std=0.01) network.load_params("params.pkl")
-
SimpleConvNet
初始化一个简单卷积网络:-
输入尺寸:
1x28x28
-
卷积层:
-
30个
5x5
的卷积核 -
不做 padding (
pad=0
),步长stride=1
-
-
后面接一个全连接层:100 个隐藏单元,最后输出 10 类。
-
-
用
load_params()
从文件params.pkl
加载训练好的权重。
✅ 4. 显示卷积层的权重
filter_show(network.params['W1'], 16)
-
network.params['W1']
是卷积层第 1 层的权重,形状是(FN, C, FH, FW)
。 -
这里显示前 16 个卷积核。
✅ 5. 读取图片
img = imread('../dataset/lena_gray.png') img = img.reshape(1, 1, *img.shape)
-
读取一张灰度 Lena 图片。
-
reshape 成
NCHW
格式:-
N=1
(batch size) -
C=1
(通道数) -
H, W=图像高宽
-
✅ 6. 用卷积核做卷积并显示结果
fig = plt.figure() for i in range(16): w = network.params['W1'][i] # 取第i个卷积核 b = 0 # 不使用偏置 w = w.reshape(1, *w.shape) # reshape成卷积层需要的格式 conv_layer = Convolution(w, b) # 创建一个卷积层 out = conv_layer.forward(img) # 对 Lena 图做卷积 out = out.reshape(out.shape[2], out.shape[3]) # 取出卷积结果 ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[]) ax.imshow(out, cmap=plt.cm.gray_r, interpolation='nearest')
-
循环作用:
-
取出第 i 个卷积核,构建一个只有这个卷积核的卷积层。
-
对输入图片做卷积运算。
-
将卷积输出结果可视化。
-
-
b=0
表示偏置项忽略。
✅ 7. 显示卷积效果
plt.show()
-
弹出一个窗口,展示 16 个卷积核作用在图片上的效果。
🔥 整体流程总结
-
初始化 CNN 网络并加载训练好的参数。
-
可视化卷积核权重。
-
将这些卷积核作用在 Lena 图片上,显示卷积输出结果。
⚠ 重点知识点
-
network.params['W1']
-
shape:
(filter_num, input_channels, filter_height, filter_width)
-
-
Convolution
是用来单独测试卷积效果的类。 -
代码中 偏置 b=0,只是为了单纯展示卷积核效果。