热门搜索:和平精英 原神 街篮2 

您的位置:首页 > > 教程攻略 > ai资讯 >可视化CNN和特征图

可视化CNN和特征图

来源:互联网 更新时间:2026-05-29 11:58

在计算机视觉领域,卷积神经网络(CNN)早已不是什么新鲜概念。无论是图像分类、目标检测,还是更复杂的视觉任务,CNN都扮演着核心角色。而理解CNN的关键,绕不开一个基本概念——特征图。简单来说,特征图就是卷积滤波器对输入图像“扫描”后生成的中间表示,它承载了从原始像素中提取出来的模式信息。

理解卷积层

1、卷积操作

卷积本质上是一种数学运算,它将两个函数结合生成第三个函数。在CNN的语境下,这两个函数分别是输入图像和滤波器(也叫卷积核),结果就是特征图。可以这样理解:滤波器像一个小窗口,在图像上滑动,每次滑动都计算一次点积,最终得到一张新的“地图”——特征图。

2、卷积层

具体来说,卷积层的工作流程就是:在输入图像上滑动滤波器,每一步计算滤波器与图像局部区域之间的点积,并将结果存入特征图的对应位置。如果用了多个滤波器,每个滤波器负责检测不同的特征(比如边缘、纹理、形状),那么就能生成多个特征图。特征图的数量,就等于该层使用的滤波器数量。

3、重要参数

Stride(步长)

:控制滤波器每次移动多少个像素。步长越大,特征图尺寸越小,计算量也越小。

Padding(填充)

:在输入图像或特征图的边界外添加额外像素(通常是0)。填充的目的是控制输出特征图的大小,同时确保滤波器能覆盖边缘区域。如果不做填充,边缘像素只能被滤波器覆盖一次,容易丢失信息。填充有两种常见模式:"valid"(不填充)和"same"(填充后输出尺寸与输入相同)。

Kernel/Filter(滤波器)

:滤波器是一个可学习的小矩阵,其权重会在训练过程中不断调整。下图展示了一个典型场景:输入图像大小为5×5,滤波器大小为3×3(黄色区域),步长为1,填充为valid(即无填充)。滤波器在图像上滑动,每次计算点积,最终生成特征图。

4、特征图

特征图是卷积层的输出,本质上是一个二维数组,包含了卷积滤波器从输入中提取的特征。特征图的大小(尺寸)取决于输入尺寸、滤波器尺寸、填充和步长。随着网络层数加深,特征图尺寸通常会逐渐缩小,但深度(通道数)会增加——这意味着网络在“用更小的空间表达更丰富的信息”。

特征图尺寸的计算公式如下:

Output_Size = (Input_Size - Filter_Size + 2 * Padding) / Stride + 1

这个公式非常实用,在实际搭建网络时经常需要用到,建议记住。每一层输出的特征图,会作为下一层的输入。随着层数增加,网络能够学习到越来越抽象的特征——从边缘、纹理,到物体部件,再到完整的对象。正是通过多层特征的组合,CNN才能识别出复杂模式并做出准确的预测。

特征图可视化

理论讲完,咱们来点实际的——用代码把特征图画出来。这里以TensorFlow/Keras作为演示框架。

首先导入必要的库:

# 图像处理库
import cv2
# Keras
import keras
from keras import layers
# 绘图
import matplotlib.pyplot as plt
import numpy as np

使用OpenCV读取一张图片,并缩放到224×224像素:

img_size = (224, 224)
file_name = "./data/archive/flowers/iris/10802001213_7687db7f0c_c.jpg"
img = cv2.imread(file_name)
img = cv2.resize(img, img_size)

搭建一个包含两个卷积层的简单模型:

model = keras.Sequential()
filters = 16
model.add(layers.Conv2D(input_shape=(224, 224, 3), filters=filters, kernel_size=3))
model.add(layers.Conv2D(filters=filters, kernel_size=3))

从第一层中提取训练好的滤波器权重,并做归一化以便显示:

filters, bias = model.layers[0].get_weights()
min_filter = filters.min()
max_filter = filters.max()
filters = (filters - min_filter) / (max_filter - min_filter)

接下来可视化这些滤波器:

figure = plt.figure(figsize=(10, 20))
filters_count = filters.shape[-1]
channels = filters.shape[0]
index = 1
for channel in range(channels):
    for filter in range(filters_count):
        plt.subplot(filters_count, channels, index)
        plt.imshow(filters[channel, :, :, filter])
        plt.xticks([])
        plt.yticks([])
        index += 1
plt.show()

将图像输入模型,得到第一层的特征图:

normalized_img = (img - img.min()) / (img.max() - img.min())
normalized_img = normalized_img.reshape(-1, 224, 224, 3)
feature_map = model.predict(normalized_img)

特征图也需要归一化才能用matplotlib显示:

feature_map = (feature_map - feature_map.min()) / (feature_map.max() - feature_map.min())

提取并显示所有16个滤波器对应的特征图:

total_imgs = feature_map.shape[0]
no_features = feature_map.shape[-1]
fig = plt.figure(figsize=(10, 50))
index = 1
for image_no in range(total_imgs):
    for feature in range(no_features):
        plt.subplot(no_features, 3, index)
        plt.imshow(feature_map[image_no, :, :, feature], cmap="gray")
        plt.xticks([])
        plt.yticks([])
        index += 1
plt.show()

总结

通过可视化CNN不同层的特征图,我们可以直观地看到网络在处理图像时到底“看”到了什么。第一层往往关注边缘、角落这类简单特征;越往后的层,特征越抽象——可能对应物体的某个部件,甚至整类物体的存在。与此同时,特征图还能帮助我们定位图像中对网络决策最重要的区域。这些可视化手段,对于理解模型的内部机制、诊断模型行为,都非常有价值。

热门手游

手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc