游乐游手机版
首页/AI热点日报/热点详情

PyTorch实战:卷积神经网络深度解析

类型:热点整理2026-07-17
在当今时代,机器在理解和识别图像中的特征与目标方面,已经实现了99%的精度。看看我们身边:智能手机可以识别相机中的面部,用Google图片搜索能立刻找到特定照片,甚至从条形码或书籍中扫描文本。这些能力背后,卷积神经网络(CNN)功不可没——它是一种特定类型的神经网络,也叫卷积网络。 如果你是深度学习

在当今时代,机器在理解和识别图像中的特征与目标方面,已经实现了99%的精度。看看我们身边:智能手机可以识别相机中的面部,用Google图片搜索能立刻找到特定照片,甚至从条形码或书籍中扫描文本。这些能力背后,卷积神经网络(CNN)功不可没——它是一种特定类型的神经网络,也叫卷积网络。

如果你是深度学习爱好者,大概率早就听说过CNN,甚至自己动手写过几个图像分类器。像TensorFlow和PyTorch这样的现代框架,让机器学习图像变得相当容易。不过,有个问题始终绕不开:数据究竟是怎么通过神经网络的人工层传递的?计算机又是如何从中学习的?要解答这些疑问,最好的办法就是用PyTorch来可视化每个图层的图像,咱们今天就来深入拆解一下。

卷积神经网络全解析

什么是卷积神经网络?

卷积神经网络(CNN)是一种在图像处理上表现特别出色的神经网络。它由Yan LeCun在1998年提出,最初是为了识别输入图像中存在的数字。在了解CNN之前,得先弄明白神经网络的工作原理——它模仿了人脑解决复杂问题并在数据集中寻找模式的方式。过去几年,神经网络已经席卷了许多机器学习和计算机视觉算法。

神经网络的基本模型由组织在不同层中的神经元组成。每个网络都有输入层和输出层,中间根据问题复杂度增加若干隐藏层。数据通过这些层时,神经元会学习并识别模式,这种表示就称为模型。训练完成后,网络会根据测试数据做出预测。如果对神经网络还不熟悉,可以先看看那篇关于用Python做深度学习的文章,能帮你快速入门。

而CNN是一种特殊变体,极其擅长处理图像。除了数字识别,它的应用还包括语音识别、图像分割和文本处理。在CNN流行之前,人们常用多层感知器(MLP)来构建图像分类器。图像分类就是从多波段光栅图像中提取信息类别的任务。但MLP有明显短板:需要更多时间和空间来查找信息,因为每个输入特征都要连接到下一层的每个神经元。CNN通过引入“局部连接”的概念取代了MLP——每个神经元只连接到输入体积的本地区域。这样一来,网络不同部分可以专门处理高级特征(如纹理或重复图案),大大减少了参数数量。听起来有点复杂?别担心,咱们把图像分别通过MLP和CNN过一遍,就明白了。

比较MLP与CNN

以MNIST数据集为例,输入图像大小为28×28=784,如果使用MLP,输入层的神经元总数就是784。网络要预测图中数字,输出类别可能是0到9中的任意一个(1、2、3、4、5、6、7、8、9)。在输出层,每个类别都有一个分数——比如输入是数字“3”,那么对应“3”的那个神经元得分就比其他神经元高。中间要放多少隐藏层、每层放多少神经元?下面是一个用Keras实现的MLP代码示例:

这段代码表明,第一个隐藏层有512个神经元,连接到一个形状为784的输入层。随后加了一个随机失活层(dropout,0.2表示每20%的神经元随机不参与),用来防止过拟合。第二个隐藏层同样512个神经元,再接一次随机失活。最后用一个10类的输出层收尾——得分最高的那个类就是模型的预测结果。

这是定义所有层之后网络的多层外观。这种MLP的缺点是全连接网络学习起来太费时费空间,而且它只能接受向量作为输入。

卷积层则不同,它不使用全连接,而是采用稀疏连接——接收矩阵作为输入,这比MLP有天然优势。输入特征连接到本地的编码节点。在MLP中,每个节点要负责理解整幅画面;而在CNN中,我们把图像拆成区域(像素的局部区域),每个隐藏节点只需向输出层报告,输出层再把这些数据组合起来寻找模式。下面的图展示了各层如何本地连接:

在弄懂CNN如何从图片中提取信息之前,先得理解特征提取的过程。CNN利用不同的层来保存图像中的特征。比如一张狗的照片,网络要对狗进行分类,就得识别所有特征:眼睛、耳朵、舌头、腿等等。这些特征通过滤波器和核被分解,然后在网络的局部层中被识别出来。

计算机如何看图像?

人类靠眼睛理解图像,计算机则靠一组0到255之间的像素值。它只识别像素值——这就是图像对计算机的全部意义。分析完像素值后,计算机慢慢判断图像是灰度还是彩色。灰度图像只有一个通道(每个像素代表一种颜色的强度,0黑、255白,中间是不同灰度);彩色图像有三个通道(红、绿、蓝,构成3D矩阵),当这三个值同时变化时,就能产生海量的颜色。确定颜色属性后,计算机再识别图像中物体的曲线和轮廓。

用PyTorch可以很直观地探索这个过程——加载数据集并将滤波器应用到图像上。下面是代码片段:

现在来看看如何将单个图像输入神经网络:

img = np.squeeze(images[7])  
fig = plt.figure(figsize = (12,12))   
ax = fig.add_subplot(111)  
ax.imshow(img, cmap='gray')  
width, height = img.shape  
thresh = img.max()/2.5  
for x in range(width):  
    for y in range(height):  
        val = round(img[x][y],2) if img[x][y] !=0 else 0  
        ax.annotate(str(val), xy=(y,x),   
           color='white' if img[x][y]

这就是数字“3”被分解成像素的样子。从一组手写数字中随机挑出一个“3”,显示其像素值。这里用到了ToTensor(),它会把实际像素值(0–255)归一化到0~1之间——为什么这么做?因为简化后续计算,不管是在解释图像还是寻找通用模式时都更省事。

建立自己的滤波器

在CNN中,图像像素信息会经过滤波。为什么需要滤波器?就像小孩子学习一样,计算机也得经历一个“了解图像”的学习过程。好在它不需要几年时间!计算机从零开始、逐步推进,先知道所有原始部分——边缘、轮廓等低层特征,然后处理更复杂的功能。简单说,必须先提取低级特征,再提取中级特征,最后提取高级特征。滤波器就是提取信息的一种手段。

低级特征可以用特定滤波器来提取,滤波器本身也是一组像素值(可以理解为连接CNN各层的权重)。把这些权重或滤波器与输入相乘,就会得到中间图像——它代表了计算机对图像的部分理解。这些中间结果再与更多的滤波器相乘,逐步扩展视野。这个过程会一直持续,直到计算机彻底认清图像。

滤波器种类很多,取决于你的需求:模糊、锐化、加深、边缘检测……应有尽有。来看看代码片段,了解一下滤波器的具体作用:

这是应用Sobel滤波器后图像的样子。

完整的卷积神经网络(CNN)

我们已经知道滤波器如何提取特征,但要构建一个完整的CNN,还需要理解它的各层结构。CNN中的基本层包括:

  • 卷积层
  • 池化层
  • 全连接层

利用这三层,可以构造出类似下图的图像分类器:

CNN各层的作用

卷积层——卷积层(CONV)使用滤波器执行卷积操作,同时扫描输入图像的尺寸。超参数包括滤波器尺寸(通常设为2×2、3×3、4×4、5×5等,不仅限于此)和步长(S)。输出结果(O)被称为特征图或激活图,包含了输入层和滤波器计算出的所有特性。下图展示了卷积操作产生的特征图:

卷积操作示意

池化层——池化层(POOL)用于特征的降采样,通常在卷积层之后应用。常见两种操作:最大池化和平均池化,分别取特征的最大值和平均值。下图是池化的基本原理:

最大池化示例

平均池化示例

全连接层——全连接层(FC)作用于扁平化后的输入,每个输入都连接到所有神经元。它通常位于网络末端,把隐藏层连接到输出层,用来优化类分数。

全连接层结构

在PyTorch中可视化CNN

了解了CNN的各个部件后,现在用Facebook的PyTorch框架来实现一下。

步骤1:加载输入图像

使用NumPy和OpenCV加载图像。

步骤2:可视化滤波器

先了解我们即将使用的滤波器长什么样。

步骤3:定义卷积神经网络

这个CNN包含卷积层和最大池化层,权重用上述滤波器进行初始化:

步骤4:可视化滤波器

快速看一下正在使用的滤波器:

def viz_layer(layer, n_filters=4):  
    fig = plt.figure(figsize=(20,20))  
    for i in range(n_filters):  
        ax = fig.add_subplot(1, n_filters, i+1)  
        ax.imshow(np.squeeze(layer[0,i].data.numpy()), cmap='gray')  
        ax.set_title('Output %s' % str(i+1))  

fig = plt.figure(figsize=(12,6))  
fig.subplots_adjust(left=0, right=1.5, bottom=0.8, top=1, hspace=0.05, wspace=0.05)  
for i in range(4):  
    ax = fig.add_subplot(1,4,i+1, xticks=[], yticks=[])  
    ax.imshow(filters[i], cmap='gray')  
    ax.set_title('Filter %s' % str(i+1))  

gray_img_tensor = torch.from_numpy(gray_img).unsqueeze(0).unsqueeze(1)

滤波器可视化结果:

步骤5:跨层滤波器输出

在CONV和POOL层中输出的图像如下:

viz_layer(activated_layer)  
viz_layer(pooled_layer)

卷积层输出:

池化层输出:

来源:https://m.elecfans.com/article/1896408.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。