13 从 MLP 到 LeNet:卷积核到底在提取什么?特征图怎么看?用真实图片一篇看明白

张开发
2026/4/3 21:46:34 15 分钟阅读
13 从 MLP 到 LeNet:卷积核到底在提取什么?特征图怎么看?用真实图片一篇看明白
卷积核到底在提取什么特征图怎么看用真实图片一篇看明白上一篇已经把卷积层最核心的动作讲清楚了卷积层可以先理解成用卷积核在图像上滑动每个位置得到一个响应值最后这些响应值组成一张特征图 。但很多人到这里还会继续卡住卷积核到底在提取什么特征图到底表示什么一张特征图是不是“处理后的图片”为什么同一张图换不同卷积核结果会差这么多卷积核的运算方式是不是都一样这篇文章就不再重复解释卷积层怎么滑动而是直接聚焦这几个问题。一、卷积核本质上是在提取“局部模式”如果只用一句话来概括卷积核可以这样理解卷积核不是在看整张图而是在局部区域里寻找某种模式。这些模式可能是横向边缘竖向边缘亮暗变化局部纹理某种小结构所以卷积核可以先理解成一个局部模式检测器。它的任务不是“认出这是什么物体”而是回答更基础的问题这里像不像一条边这里有没有明显的亮暗变化这里有没有某种局部结构这也是为什么卷积层通常会放在网络前面因为它负责先把原始像素变成更有用的局部特征表示 。二、卷积核的运算是不是都一样很多人第一次看卷积时都会冒出一个很自然的问题不同卷积核虽然长得不一样但它们的计算方法是不是都一样答案是基本的局部计算形式是一样的。也就是说不管这个卷积核是拿来提边缘、做模糊、做锐化还是在 CNN 里通过训练学出来的参数它在某个位置上的基础计算都可以先理解成下面这几步从输入图像中取一个局部区域让这个局部区域和卷积核按位置一一对应每个位置分别做乘法再把所有乘积加起来得到当前位置的一个输出值如果把这句话再压缩一下其实就是每个点先乘再把结果加起来。所以卷积核之间真正不同的地方往往不是“怎么算”而是卷积核里的数值不同它关注的模式不同最后得到的响应分布不同三、用一个 3×3 的小例子把“乘完再加”看清楚假设输入图像里某个 3×3 局部区域是importnumpyasnp patchnp.array([[0,1,1],[1,1,1],[1,1,1]])现在卷积核是kernelnp.array([[1,1,1],[1,1,1],[1,1,1]])那当前位置的计算过程就是[[0*1,1*1,1*1],[1*1,1*1,1*1],[1*1,1*1,1*1]]也就是[[0,1,1],[1,1,1],[1,1,1]]再把它们全部加起来0111111118这个 8就是这个位置的输出值。所以卷积最基本的局部运算确实可以先理解成局部区域和卷积核按位置做乘法然后把乘积求和。从直觉上看它其实是在计算当前这个局部区域和卷积核想找的模式到底有多像。越像响应越强越不像响应越弱。四、先看几个典型卷积核它们大概在提什么信息为了把这件事讲得更直观可以先看几个常见卷积核。1. 竖向边缘检测核kernel_verticalnp.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtypefloat)这个卷积核通常更容易对左右亮暗变化明显的区域有响应也就是更容易突出竖向边缘。2. 横向边缘检测核kernel_horizontalnp.array([[-1,-1,-1],[0,0,0],[1,1,1]],dtypefloat)这个卷积核通常更容易对上下亮暗变化明显的区域有响应也就是更容易突出横向边缘。3. 模糊 / 平滑核kernel_blurnp.array([[1,1,1],[1,1,1],[1,1,1]],dtypefloat)/9.0这个卷积核会对局部做平均让图像更平滑。4. 锐化核kernel_sharpennp.array([[0,-1,0],[-1,5,-1],[0,-1,0]],dtypefloat)这个卷积核会强化图像中变化明显的部分让边缘和细节更突出。五、为什么这些卷积核会有这种效果看到这里很多人会继续追问为什么偏偏是这种数字排列就会得到边缘、模糊、锐化这些效果这个问题问得很好。因为卷积核之所以会表现出不同效果本质上和它里面正数、负数、零的分布方式有关。前面已经说过卷积在每个位置上的基础计算形式都是局部区域和卷积核按位置相乘再把结果加起来。所以卷积核里的数字排布决定了它到底在“放大什么差异”。1. 为什么竖向边缘核能提取竖向边缘这个核是[-1,0,1][-1,0,1][-1,0,1]它的特点很明显左边一列是负数中间一列是 0右边一列是正数这意味着它本质上在比较局部区域左边和右边的亮度差异。如果一个区域是“左边暗、右边亮”那乘完再加之后就容易得到比较大的正响应。如果是“左边亮、右边暗”就可能得到比较大的负响应。如果左右差不多那最后加起来就会接近 0。所以它会对左右亮暗变化明显的区域特别敏感也就是对竖向边缘敏感。2. 为什么横向边缘核能提取横向边缘这个核是[-1,-1,-1][0,0,0][1,1,1]它的结构对应的是上面一行是负数中间一行是 0下面一行是正数这意味着它本质上在比较局部区域上半部分和下半部分的亮度差异。如果上面暗、下面亮响应就会很明显。如果上面亮、下面暗也会有明显响应只是方向可能相反。如果上下差不多那响应就不会强。所以它会对上下亮暗变化明显的区域更敏感也就是横向边缘。3. 为什么模糊核会让图像变平滑模糊核通常长这样[1,1,1][1,1,1][1,1,1]/9它的特点是每个位置权重都差不多最后还要除以 9相当于求平均所以它本质上是在做用周围像素的平均值替代当前位置。这样一来很亮的点会被周围稍微拉低很暗的点会被周围稍微拉高局部变化会被抹平所以图像就会变得更平滑也更模糊。4. 为什么锐化核会让边缘更突出锐化核通常长这样[0,-1,0][-1,5,-1][0,-1,0]它的特点是中间位置给了一个比较大的正权重5周围邻居给的是负权重-1它本质上是在做保留中心像素同时减去周围邻居的一部分影响。如果中心像素和周围差不多那相减之后变化不会特别大。但如果中心像素和周围差异明显比如正好处在边缘、细节、亮暗过渡处这种差异就会被放大。所以锐化核会让图像中的边缘和细节更明显。六、只看卷积核定义还不够直接看真实图片更直观如果只看卷积核本身还是容易停留在“知道这个矩阵长什么样”。真正有说服力的是把它直接作用到真实图片上看看结果图到底发生了什么。这里用skimage自带的一张灰度图来演示这样不需要你自己准备图片文件。代码读取真实图片importmatplotlib.pyplotaspltfromskimageimportdata imgdata.camera().astype(float)plt.figure(figsize(6,6))plt.imshow(img,cmapgray)plt.title(原图)plt.axis(off)plt.show()这一步的意义很简单卷积核不是只能处理示意图它可以直接作用在真实图像上。七、把不同卷积核作用到同一张真实图片上这里用scipy.signal.convolve2d来做卷积代码会更简洁一些。fromscipy.signalimportconvolve2d feature_verticalconvolve2d(img,kernel_vertical,modesame,boundarysymm)feature_horizontalconvolve2d(img,kernel_horizontal,modesame,boundarysymm)feature_blurconvolve2d(img,kernel_blur,modesame,boundarysymm)feature_sharpenconvolve2d(img,kernel_sharpen,modesame,boundarysymm)然后把原图和卷积后的结果图放在一起看plt.figure(figsize(14,10))plt.subplot(2,3,1)plt.imshow(img,cmapgray)plt.title(原图)plt.axis(off)plt.subplot(2,3,2)plt.imshow(feature_vertical,cmapgray)plt.title(竖向边缘响应)plt.axis(off)plt.subplot(2,3,3)plt.imshow(feature_horizontal,cmapgray)plt.title(横向边缘响应)plt.axis(off)plt.subplot(2,3,4)plt.imshow(feature_blur,cmapgray)plt.title(模糊 / 平滑)plt.axis(off)plt.subplot(2,3,5)plt.imshow(feature_sharpen,cmapgray)plt.title(锐化)plt.axis(off)plt.tight_layout()plt.show()这组图一出来很多概念就会立刻变具体竖向边缘核会突出左右变化明显的地方横向边缘核会突出上下变化明显的地方模糊核会让图像整体变柔和锐化核会让细节和边缘更明显这也说明不同卷积核确实会提取不同类型的局部信息。八、特征图到底表示什么看到这里就可以更准确地理解“特征图”了。特征图不是“处理后的原图”更不是原图的简单复制。它本质上表示的是某个卷积核在整张图不同位置上的响应分布。比如如果卷积核关心竖向边缘那么特征图里响应高的地方就说明那些位置更像竖向边缘如果卷积核关心横向边缘那么特征图里响应高的地方就说明那些位置更像横向边缘所以特征图更像是一张模式响应图而不是“另一张普通图片”。九、特征图上的一个点不再是单个像素这个点特别重要。卷积之后特征图上的一个位置不再等于原图中的一个孤立像素。它对应的是输入图像中的一个局部区域。也就是说特征图上的一个点代表的是某个局部区域对当前卷积核的响应结果。所以即使卷积后的图在尺寸上没有一下缩小很多它做的事情依然非常重要。因为变化最大的不一定是“尺寸”而是每个位置的含义原来是像素值现在是局部模式响应这也是卷积真正厉害的地方。它不是简单地“把图缩一下”而是在把原始像素重新表达成更有意义的中间表示。十、传统卷积核和 CNN 里的卷积核不完全是一回事这里一定要补一句不然容易误解。上面这些边缘核、模糊核、锐化核更像是传统图像处理里的人工设计卷积核。也就是说人提前写好这些核让程序去做指定的处理。但在 CNN 里卷积核通常不是人工指定的而是通过训练学出来的。也就是说一开始参数是随机的然后模型在训练过程中不断调整最后学出对当前任务更有用的局部模式检测器所以更准确地说传统图像处理里的卷积核很多是人为设计的而 CNN 里的卷积核通常是训练得到的。但它们在直觉上的共同点是一样的都在局部区域里提取某种信息。十一、为什么一个卷积核显然不够一旦理解了卷积核是在找某种局部模式就会自然想到一个问题如果一个卷积核只能关注一种模式那怎么可能够当然不够。因为真实图像里可能同时有横向边缘竖向边缘纹理角点局部形状更复杂的组合模式所以真正的卷积层通常不会只有一个卷积核而是会有很多个。于是就会得到很多张特征图。你可以把它理解成同一张输入图被很多不同的局部模式检测器分别扫了一遍。这也是为什么卷积层输出的通常不是一张图而是一组特征图。十二、卷积层为什么通常放在网络前面这个问题放在这里讲就很好理解了。卷积层通常放在网络前面是因为它最适合做“前端特征提取”。原始输入图像刚进入网络时本质上只是像素矩阵。这时候如果直接让后面的分类器去面对原始像素并不是最自然的方式。更合理的流程是先用卷积层提取局部模式再把这些局部模式继续组合最后再交给分类层去判断所以卷积层更像是在做一件基础但很重要的事先把原始像素变成更有意义的中间表示。卷积层和全连接层的差别不只是公式不同更重要的是它们看待输入的方式不同全连接层更像把输入看成一组统一特征而卷积层更强调从局部开始提取模式 。十三、完整代码真实图片 多种卷积核 卷积结果图下面把前面用到的完整代码整理到一起方便你直接运行。importnumpyasnpimportmatplotlib.pyplotaspltfromscipy.signalimportconvolve2dfromskimageimportdata# # 1. 定义几种卷积核# kernel_verticalnp.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtypefloat)kernel_horizontalnp.array([[-1,-1,-1],[0,0,0],[1,1,1]],dtypefloat)kernel_blurnp.array([[1,1,1],[1,1,1],[1,1,1]],dtypefloat)/9.0kernel_sharpennp.array([[0,-1,0],[-1,5,-1],[0,-1,0]],dtypefloat)# # 2. 读取真实灰度图# imgdata.camera().astype(float)# # 3. 做卷积# feature_verticalconvolve2d(img,kernel_vertical,modesame,boundarysymm)feature_horizontalconvolve2d(img,kernel_horizontal,modesame,boundarysymm)feature_blurconvolve2d(img,kernel_blur,modesame,boundarysymm)feature_sharpenconvolve2d(img,kernel_sharpen,modesame,boundarysymm)# # 4. 可视化# plt.figure(figsize(14,10))plt.subplot(2,3,1)plt.imshow(img,cmapgray)plt.title(原图)plt.axis(off)plt.subplot(2,3,2)plt.imshow(feature_vertical,cmapgray)plt.title(竖向边缘响应)plt.axis(off)plt.subplot(2,3,3)plt.imshow(feature_horizontal,cmapgray)plt.title(横向边缘响应)plt.axis(off)plt.subplot(2,3,4)plt.imshow(feature_blur,cmapgray)plt.title(模糊 / 平滑)plt.axis(off)plt.subplot(2,3,5)plt.imshow(feature_sharpen,cmapgray)plt.title(锐化)plt.axis(off)plt.tight_layout()plt.show()十四、小结如果把这篇文章压缩成最核心的几句话可以记住下面这些卷积核本质上是在局部区域中寻找某种模式。不同卷积核的基础计算形式可以先统一理解成对应位置相乘再把结果相加。卷积核之所以会有不同效果本质上和它内部正数、负数、零的分布方式有关。特征图不是原图复制版而是某种模式在整张图不同位置上的响应分布。特征图上的一个点不再是单个像素而是一个局部区域的信息。卷积层通常放在网络前面因为它负责先把原始像素变成更有用的中间表示。

更多文章