赞
踩
由于接下来的课程内容将围绕计算机视觉展开,其中接触最多的内容是卷积、卷积神经网络等…因此,本篇内容将从卷积入手,梳理理解:卷积的意义、卷积在图像处理中的作用以及卷积神经网络的概念,最后利用pytorch搭建一个神经网络。
在第一次接触到"卷积"的概念时,我与大多数人的想法类似,首先想的问题是,“卷积"到底是怎样的一个"卷”?
在网上搜索卷积的概念之后,我初步了解到卷积本质上是一个数学问题,它的表示如下:
( f ∗ g ) ( t ) = ∫ − ∞ ∞ f ( τ ) g ( t − τ ) d τ (f * g)(t) = \int_{-\infty}^{\infty} f(\tau)g(t-\tau) d\tau (f∗g)(t)=∫−∞∞f(τ)g(t−τ)dτ
以上的表示过于抽象,所以通过搜索B站的视频,找到了介绍卷积较为形象的示例。
示例:如果用图示来表示一个人的吃饭情况,那么他进食的过程和消化的过程可以用如下图来分别表示
进食过程:用f函数来表示进食,横坐标是时间,纵坐标是进食(也就是吃东西)了多少。
消化过程:消化的过程与进食是独立,吃的东西进入胃里面会进行消化,这个过程可以用g函数来表示。横坐标是时间,纵坐标是剩余食物的比例。
此时,如果我们想知道这个人在下午2点时,胃里还剩多少食物。这个问题如果直接求解是不好求解的,但是如果借助上面的两个函数,就比较容易可以求得,具体如下:
由此,推导得到这个人在t时刻,胃里剩余食物的比例可以用如下的公式表示:
上面的公式因为是求吃饭问题场景下的食物剩余比例,所以积分上下限是0~t;如果是将此问题场景换成其他场景,只需要把公式中做微调如下,即可求更加广泛的问题:
( f ∗ g ) ( t ) = ∫ − ∞ ∞ f ( τ ) g ( t − τ ) d τ (f * g)(t) = \int_{-\infty}^{\infty} f(\tau)g(t-\tau) d\tau (f∗g)(t)=∫−∞∞f(τ)g(t−τ)dτ
卷积:在一个系统中,输入不稳定、输出稳定的情况下,可以用卷积求系统的存量。
例如:
在一个热力系统中,可以利用卷积计算:燃料持续添加 f ( τ ) f(\tau) f(τ)和燃料持续燃烧 g ( t − τ ) g(t-\tau) g(t−τ)下,燃烧过程中产生的总热量。
在一个信号系统中,信号持续输入 f ( τ ) f(\tau) f(τ)和系统的响应 g ( t − τ ) g(t-\tau) g(t−τ)下,信号对系统产生影响的累积效果。
上述对卷积的理解,还可以换一种角度(例如:蝴蝶效应)来理解:
在t时刻发生了一件事,t时刻之前很多事情都会产生影响,而其中x时刻对t时刻的影响(g函数)是随着时间逐步减弱的。
对于上述的f函数和g函数在t时刻的对应关系,可以用如下图表示:
在t时刻进食的食物f(t),此时在消化过程g(t)时刚开始,所以对应g(t)函数图的最左侧;
在t时刻之前时刻进食的食物f(t),则对应对应消化过程g(t)的第二个点(从左向右)。
备注:此处对于上图其他点的理解,得用逆转的思想来理解。
将上图的g函数做翻转,上下两图的对应关系就更加清晰。因为这个翻转,所以称之为"卷积"。
在《【课程总结】Day8(下):计算机视觉基础入门》中,我们学习了解过:
在上图这个计算过程中,其与卷积有着相同之处:
上图计算过程,本质上是计算周围像素点对中间像素点的影响,因此套用吃饭问题可以如下图来理解:
上图中左下角的点对中心点的影响,可以换做是x时刻的事件对t时刻的影响,以此来理解图像中卷积的意义。
至此,在图像处理中:
卷积神经网络一般是用来做图像识别的,通过卷积神经网络可以将下面的图片中的X分别识别出来。
虽然上述图片的整体像素不同,但是仔细看,可以看到局部是相同的:
所以,如果利用之前学习的机器学习思想:
由此,我们得到一个与人体神经系统类似的网络,卷积神经网络。
Batch Normalization是一种用于神经网络的技术,通过在神经网络的每一层对输入进行归一化处理,即将每个特征维度的数据归一化为均值为0、方差为1的分布,以减少内部协变量转移(Internal Covariate Shift)。
对于输入 (x),Batch Normalization的计算公式如下:
x
^
=
x
−
μ
σ
2
+
ϵ
\hat{x} = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}}
x^=σ2+ϵ
x−μ
y = γ x ^ + β y = \gamma \hat{x} + \beta y=γx^+β
其中:
ReLU是一种简单而有效的激活函数,其数学表达式为 f ( x ) = max ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x),即当输入 (x) 大于零时输出为 (x),否则输出为零。
线性层是神经网络中的基本层之一,其输出是输入特征的线性组合。在线性层中,每个输入特征与对应的权重相乘,然后将所有结果相加得到输出。
线性层的计算公式为:output = input * weight + bias,其中weight是权重矩阵,bias是偏置项。线性层的作用是对输入进行线性变换。
Dropout是一种在神经网络训练过程中随机丢弃一部分神经元的技术。在每次训练迭代中,随机选择一部分神经元不参与前向传播和反向传播,从而减少神经网络的复杂度和提高泛化能力。
其思想非常类似于集成学习,在训练(正向传播)的时候,随机进行失活(让一部分参数置为0),相当于训练了多个弱分类器;在预测的时候,dropout层失效(由于数学期望是一样的)
import torch
from torch import nn
dropout = nn.Dropout(p=0.5)
X = torch.randn(10)
运行结果:
右上可以看到,dropout会50%概率将X中的值置为0。
LeNet5诞生于1994年,是最早的卷积神经网络之一,其作用主要用来进行手写字符的识别与分类。由于LeNet网络结构比较简单,但是刚好适合神经网络的入门学习。
如图所示,LeNet共分为7层,分别是:
定义:LeNet的输入层接受原始图像数据,并将每个像素的灰度值作为输入信号传递给下一层的卷积层。输入层的作用是将原始数据转换为神经网络可以理解和处理的格式,为后续的特征提取和分类任务奠定基础。
参数:输入层为尺寸32 × 32的图片。
一般来说不将输入层视为网络层次结构之一,上面讲的"7层"也不包括输入层。
定义:卷积层C1是LeNet模型中的第一个卷积层,用于提取输入图像的特征。
功能:卷积层C1的主要特点和功能如下:
主要参数:
输入: 32 × 32的图像
卷积核种类: 6
卷积核大小: 5 × 5
输出特征图数量: 6
每个卷积核分别与输入图像进行卷积运算,共得到6份输出
输出特征图大小: 28 × 28
输出图大小的计算方法:原图片的大小 - 卷积核大小 + 1 = 输出图片大小
如图所示:5(原图) - 3(卷积核) + 1 = 3(输出图)
定义:池化层(Pooling Layer)是深度学习神经网络中常用的一种层类型,用于减少特征图的空间维度,从而降低模型复杂度、减少参数数量,并且有助于防止过拟合。
作用:
常见池化操作有两种:最大池化(Max Pooling)和 平均池化(Average Pooling)
以最大池化为例:采用2 × 2的滤波器(filter),最大池化的结果如上,即对每个2 × 2的区域取最大值。
28 × 28的特征图(6张)
2 × 2
14 × 14
6
定义:卷积层C3是LeNet模型中的第三个卷积层,用于进一步提取输入特征图的更高级别特征。其输出将作为下一层的输入,经过池化层等操作逐步提取更加抽象和高级的特征。
主要功能和作用:
主要参数:
输入: 14 × 14的特征图(6张)
卷积核种类: 16
因此卷积层C3能够提取出更多细微的特征
卷积核大小: 5 × 5
输出特征图数量: 16
输出特征图大小: 10 × 10
输出特征图的边长为14 - 5 + 1 = 10
输入: 10 × 10的特征图(16张)
采样区域: 2 × 2
在这里,采样方式为4个输入相加,乘以一个可训练参数,再加上一个可训练偏置,并将结果通过sigmoid函数。
输出特征图大小: 5 × 5
输出特征图数量: 16
定义:卷积层C5是LeNet模型中的第五个卷积层,也是整个网络中的最后一个卷积层。卷积层C5的主要作用是进一步提取输入特征图的高级别特征,并将这些特征用于后续的分类任务。
主要作用:通过卷积层C5的特征提取操作,网络可以学习和理解输入数据的更加抽象和复杂的特征,从而提高模型对不同类别的区分能力。
主要参数:
5 × 5的特征图(16张)
120
5 × 5
120维向量
算法:
每个卷积核与16张特征图做卷积,得到的结果求和,再加上一个偏置,结果通过sigmoid函数输出。
定义:全连接层F6是LeNet模型中的最后一个层,用于将卷积层提取的特征进行分类和预测。
主要功能:
主要参数:
120维向量
84维向量
算法: 计算输入向量和权重向量之间的点积,再加上一个偏置,结果通过sigmoid函数输出。
F6层有84个结点,本质上对应一张7×12的比特图。实际上,ASCII码就可以用一张7×12的比特图来表示,每个像素若为-1则表示白色,1表示黑色。该全连接层的设计也是利用了这一思想。
84维向量
本质上是一张7×12的比特图,表示经过我们多层处理最终得到的一张"数字图像"。
10维向量
import torch from torch import nn class ConvBlock(nn.Module): """ 一层卷积块: - 卷积层 - 批规范化层 - 激活层 """ def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1): super().__init__() self.conv = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding) self.bn = nn.BatchNorm2d(num_features=out_channels) # 批规范化层 self.relu = nn.ReLU() # ReLU激活函数 def forward(self, x): x = self.conv(x) # 卷积操作 x = self.bn(x) # 批规范化操作 x = self.relu(x) # 激活操作 class LeNet(nn.Module): def __init__(self): super().__init__() # 特征提取部分 self.feature_extractor = nn.Sequential( # 第一层卷积块 ConvBlock(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=0), nn.MaxPool2d(kernel_size=2, stride=2, padding=0), # 最大池化层 # 第二层卷积块 ConvBlock(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=0), nn.MaxPool2d(kernel_size=2, stride=2, padding=0) # 最大池化层 ) # 分类部分 self.classifier = nn.Sequential( nn.Flatten(), # 展平操作 nn.Linear(in_features=400, out_features=120), # 第一个全连接层 nn.ReLU(), # ReLU激活函数 nn.Linear(in_features=120, out_features=84), # 第二个全连接层 nn.ReLU(), # ReLU激活函数 nn.Linear(in_features=84, out_features=10) # 输出层 ) def forward(self, x): # 1. 特征提取 x = self.feature_extractor(x) # 2. 分类 x = self.classifier(x) return x model = LeNet() model
卷积神经网络
卷积网络组件
LeNet
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。