AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


你了解了这些背景知识,CNN卷积神经网络就好理解了!
发布日期:2024-04-12 21:41:51 浏览次数: 2572 来源:牛爷儿



引言

CNN,即卷积神经网络(Convolutional Neural Network),是一种特别为处理具有类似网格结构(比如,图片)的数据而设计的深度学习算法,最典型的应用是图像识别和处理,其中数据可以被视为2D网格。CNN通过卷积层、池化层和全连接层的组合来自动并有效地提取图像中的特征,用于分类、检测等任务。


这是CNN的标准定义,卷积神经网络,这个翻译至少给理解它加深了一个难度。Convolutional 解释为盘旋,缠绕,估计就好很多。配合下面这张git图,就彻底搞明白了。本质上,是使用了一个卷积核(过滤器,或者叫matrix),类似盘旋的方式,依次从左到右,从上到下,跟输入数据做`加减乘除`运算。‍‍‍

CNN的由来

CNN的基础理念可以追溯到Hubel和Wiesel在1960年代对猫的视觉皮层的研究,他们发现视觉皮层包含专门对光斑、边缘等简单模式敏感的神经元。

基于这一发现,Fukushima在1980年提出了一个层次化的、无监督学习的神经网络模型,称为“Neocognitron”,可以看作是现代CNN的雏形。CNN在1998年由Yann LeCun及其合作者提出,提出CNN最初的目的是为了解决全连接神经网络在处理数据时的局限性

图像数据具有一种固有的空间结构 - 相邻的像素点在空间上是相连的,并携带着相似的局部模式和特征。例如一个像素及其周围的像素很可能属于同一个边缘或物体的一部分。

传统的全连接神经网络,(可以参考上一篇文章,pytorch实现神经网络原来这么简单!)将图像数据直接展平作为输入,把图像转化为1维向量,这意味着图像中相邻像素之间的空间邻近性信息丢失,破坏了图像的局部连续性特征,也不能有效地利用图像中的平移不变性。

网络在处理这个向量时,等同对待所有特征(像素值),无法识别哪些特征是相邻并可能具有相关性的比如,识别图片中是否有一只猫,我们希望的是,猫在图片的左边,或者右边(相当于做了图像的平移),都能够识别出来,全连接神经网络并不能很好地解决

CNN网络结构如下,接下来,我们来讲讲理解CNN网络结构,必须要了解的知识点。

什么是卷积核

卷积核(或过滤器)在卷积神经网络(CNN)中是用于提取特征的关键组件。每个卷积核由一系列可学习的权重组成,以帮助模型识别输入数据中的特定模式或特征,这些核通过在输入数据上滑动(`盘旋`操作)来应用,从而产生特征图(feature map),这个过程能够捕获输入数据中的空间和模式信息。


每个卷积核仅与输入图像的一个小区域(即局部感知域)进行运算,这意味着网络的每个神经元不需要一次性处理整个图像,而是只处理一小块区域。这种机制使得卷积核能够捕捉到局部的特征,如边缘、角点、纹理等。


卷积操作的另一个关键特性是权重共享,即网络中的卷积核在整个输入图像上滑动时使用相同的权重集。这不仅显著减少了模型的参数数量,提高了训练效率,而且意味着一旦卷积核学会了在图像的某一部分识别特定特征,它就可以在图像的任何其他部分识别同样的特征。这种平移不变性(即特征不论位于图像何处都能被相同方式识别的能力)是卷积神经网络特别适合图像处理任务的关键原因之一。


核的大小会影响模型捕捉输入数据特征的能力:


  • 小核尺寸(如1x1,3x3):能够捕捉到细粒度特征,对于捕获局部信息非常有效。3x3尺寸的核特别流行,因为它们在提取特征时提供了良好的平衡,既能捕获重要信息,又能保持计算效率。多个3x3的卷积层堆叠在一起,可以有效地增加网络的深度,而不会显著增加参数数量和计算复杂度。

  • 大核尺寸(如5x5,7x7):可以捕捉更广泛的空间信息,对于提取更大范围的特征很有帮助。但是,大核尺寸会增加模型的参数数量,从而增加计算负担和过拟合的风险。


实际应用中,核大小的选择取决于具体任务和输入数据的特性。一般来说,3x3的核被广泛认为是效率和效果之间的一个好平衡,并且是很多现代CNN架构的首选。

卷积核是如何跟输入做计算的,为什么要做padding?

卷积运算的基本过程是:卷积核(也叫滤波器kernel)在输入数据(如图像)上滑动,对与卷积核覆盖的局部数据区域进行元素级别的加权求和运算(就是小学学的`加减乘除`四则运算),得到一个卷积后的特征映射。


如下面这个例子,假设输入数据是个二维矩阵,卷积核也是一个二维矩阵(当然也可以是三维的用于彩色图像),卷积核在输入数据上按stride(步长)大小滑动,在每个位置,将卷积核与输入数据的对应区域进行元素级别乘法、求和运算,得到一个新的像素值,最终就得到了一个新的特征映射层。

或者这样理解,卷积核3x3的矩阵,覆盖在原来输入的数据上,也就得到两个重叠在一起的九宫格,九宫格中重叠位置的元素做乘法运算,运算的结果做加法,然后输出到对应的位置。


那为什么还要做padding呢?核心原因有三个:


1. 提升数据边缘特征信号的有效性,如果观察卷积操作的过程,我们可以发现,边缘数据参与卷积的次数要小于中间区域,在处理图像等空间数据时,边缘区域包含有用的信息,尤其是对于图像识别、边缘检测等任务。不使用padding可能会导致边缘信息在每次卷积操作后逐渐减少,特别是在深层网络中,这可能会损害模型的性能。


2. 支持深层次的网络结构,在设计深层网络时,可能需要多个卷积层叠加。如果每次卷积都减小特征图的尺寸,会限制网络深度,因为特征图的尺寸不能无限缩小。通过使用padding保持尺寸不变,可以构建更深的网络结构,而不必担心输入尺寸的快速减少。


3. 便于后续做特征融合,这点本篇文章不做展开,后续写AI文生图,降到Unet时,再会过来看,想了解unet的话,可以在文章底部留言,超过10人留言,优先写unet,?


那么,如何做Padding呢?通用做法是给原来的输入扩展出`边缘`,使得卷积核能从边缘处开始计算。padding和计算过程可以看下面这个gif图。

什么是下采样,池化(pooling)又是什么意思?

本文下采样(Subsampling)和池化(Pooling)是卷积神经网络(CNN)中常用的操作,用于减小特征图的尺寸,从而减少计算量和模型参数的数量。这两种操作有助于提高模型的泛化能力,通过减少过拟合的风险来提升模型性能。


下采样和池化还是有一些区别,接下来分别讲解。


1. subsampling(下采样)

下采样是一种减少数据维度和复杂度的过程,旨在降低后续层的计算需求并提高模型的效率。在图像处理和深度学习中,下采样通常意味着减小图像或特征图的尺寸,同时尽量保留重要信息。下采样的方法包括但不限于:
  • 调整卷积核的stride:卷积核默认是一次挪一步,可以改成2步,减少采样

  • 池化操作,也就是下面要讲的pooling


2. 池化(pooling)

池化是下采样的一种特殊形式,专门用于深度学习中。它通过对特征图的邻近像素进行聚合操作来减小尺寸,最常见的池化操作是最大池化(Max Pooling,取区域内的最大值)和平均池化(Average Pooling,取区域内的平均值)。

池化层的引入是基于这样一个观察:在图像中,一旦一个特征被检测到,其确切的位置相对于周围的像素来说就不那么重要。通过池化,CNN能够检测到特征的存在,并对图像中的小变化(如平移)保持不变性。此外,池化层通过减少特征图的尺寸,帮助减少计算量和模型的过拟合风险。

maxpooling

pooling翻译成池化,也是有故意提升难度的嫌疑。pooling,本质是提取某一个区域内,最显著的特征,比如做max pooling,我们就可以理解为,在做指定的区域内(pool,想象成泳池的形状,框住一片数据),图像如果出现平移,我们提取的特征都是一样的,因为不管最大值在上下左右的哪个位置,那片区域的最大值都是一样的。

什么是dropout,它有什么作用?

Dropout是一种在训练深度神经网络时广泛使用的正则化技术,由Srivastava等人在2014年提出。它的核心思想非常直观:在网络的训练过程中,随机丢弃(以一定的概率,不计算某些神经元)网络中的一部分神经元(以及它们的连接),从而防止模型对训练数据的过拟合。

这意味着在每次训练迭代中,每个神经元都有一定概率不被包含在前向和后向传播过程中,这个概率由dropout率控制,通常设置为0.5(即50%的概率被丢弃)。

在实践中,应用dropout非常简单。只有在神经网络的训练过程中,在全连接层或卷积层之后加入dropout层。在测试或评估模型时,关闭dropout(即保留所有的神经元),确保所有的特征都被用于决策。

如何用pytorch实现CNN?

最后,来用pytorch实现一个简单的CNN网络吧。

网络架构:

1. 第一个卷积层:使用32个3x3的卷积核,步长为1,激活函数为ReLU。

2. 第一个池化层:使用2x2的最大池化。

3. 第二个卷积层:使用64个3x3的卷积核,步长为1,激活函数为ReLU。

4. 第二个池化层:使用2x2的最大池化。

5. 一个全连接层:将前一层的输出平坦化后,连接到一个具有128个神经元的全连接层,激活函数为ReLU。

6. 输出层:一个具有10个神经元的全连接层,对应于10个类别的输出,使用Softmax函数作为激活函数。


import torchimport torch.nn as nnimport torch.nn.functional as F
class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)self.pool = nn.MaxPool2d(kernel_size=2, stride=2)self.fc1 = nn.Linear(7*7*64, 128)self.fc2 = nn.Linear(128, 10)
def forward(self, x):x = self.pool(F.relu(self.conv1(x)))x = self.pool(F.relu(self.conv2(x)))x = x.view(-1, 7*7*64)x = F.relu(self.fc1(x))x = self.fc2(x)return F.log_softmax(x, dim=1)
# 实例化模型model = SimpleCNN()print(model)



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询