计算机视觉是人工智能的一个分支,致力于让计算机从图像或视频中获取、分析和理解信息。其目标是模拟人类视觉系统的功能,实现场景识别、物体检测、运动跟踪等任务。
对于计算机视觉入门的人来说,我觉得应该掌握卷积层,激活函数,池化层,全连接层等,下面人我们聊一聊,他们都是什么。
模型的基本结构
输入层
输入层比较简单,这一层的主要工作就是输入图像等信息,因为卷积神经网络主要处理的是图像相关的内容,但是我们人眼看到的图像和计算机处理的图像是一样的么?很明显是不一样的,对于输入图像,首先要将其转换为对应的二维矩阵,这个二维矩阵就是由图像每一个像素的像素值大小组成的。我们可以看一个例子,如下图所示的手写数字 “8” 的图像,计算机读取后是以像素值大小组成的二维矩阵存储的图像。
上图又称为灰度图像,因为其每一个像素值的范围是 0~255(由纯黑色到纯白色),表示其颜色强弱程度。另外还有黑白图像,每个像素值要么是 0(表示纯黑色),要么是 255(表示纯白色)。我们日常生活中最常见的就是 RGB 图像,有三个通道,分别是红色、绿色、蓝色。每个通道的每个像素值的范围也是 0~255,表示其每个像素的颜色强弱。但是我们日常处理的基本都是灰度图像,因为比较好操作(值范围较小,颜色较单一),有些 RGB 图像在输入给神经网络之前也被转化为灰度图像,也是为了方便计算,否则三个通道的像素一起处理计算量非常大。当然,随着计算机性能的高速发展,现在有些神经网络也可以处理三通道的 RGB 图像。
卷积层
首先我们先了解一下卷积核,卷积核就是一个小的权重矩阵,在图像上华东,用来提取图像特征的工具,下面就是一些卷积核。
这些是3 * 3 的卷积核,其实不只是3 * 3的,还有5 * 5,7 * 7and so on
卷积神经网络就是利用卷积在图片上不断滑动扫描,提取特征的神经网络,每滑到一个位置,就算一个值,最后生成一张特征图
可以看到,整个过程就是一个降维的过程,通过卷积核的不同移动计算,可以提取图像中最有用的特征。
这是一张图片经过卷积之后图区的六张特征图,可能有的人觉得卷积很神奇,经过卷积核的数学计算之后,提取出特征图,其实我也不知道,想知道的可以了解一下,顺便打在评论区
总之,在我看来,卷积就是对图片特征的提取
池化层
首先,我们先了解一下池化窗口,它和卷积核不太一样,它没有参数,不用学习,只做简单的统计,它分为最大池化和平均池化
这是一个最大池化,将其中具有代表性的特征提取出来,可以起到减小过拟合和降低维度的作用,下面更加详细的分析一下
最大池化就是每次取正方形中所有的最大值,这个最大值相当于当前位置最具有代表性的特征平均池化就是每次取正方形中所有的平均值
激活层
激活层是卷积神经网络中紧跟在卷积层 / 全连接层之后的核心层,它的核心作用是给网络引入非线性变换,让模型能够学习复杂的特征规律,而不是只能做简单的线性拟合。
简单来说:卷积 / 全连接做的是「线性计算」(矩阵相乘、加权求和),而激活层给这个线性结果套上一个非线性函数,让网络能拟合图像、语音等复杂数据的非线性分布。
如果不理解,就可以把他堪称一个开关
全连接层
全连接层一般出现在卷积神经网络的最后部分,在卷积层,池化层提取特征之后使用,简而言之,他就是把前面提取出来的图像特征,综合起来做最终判断。
这就是一个简单的全连接层,看起来很复杂,其实也不太好理解
全连接层的本质是y = w(权重)* x + b(偏置)
过程假设
第一层神经网络
神经元个数:3 个假设输出值:123
第二层神经网络
神经元个数:4 个假设权重:
- 第 1 个神经元权重:0.1,0.5,0.9
- 第 2 个神经元权重:0.2,0.6,1.0
- 第 3 个神经元权重:0.3,0.7,1.1
- 第 4 个神经元权重:0.4,0.8,1.2
假设偏置:
- 第 1 个偏置:0.1
- 第 2 个偏置:0.2
- 第 3 个偏置:0.3
- 第 4 个偏置:0.4
第三层神经网络
神经元个数:4 个假设:把第 2 个神经元的值置为 0,其余不变
第四层神经网络
神经元个数:2 个假设权重:
- 第 1 个输出神经元权重:0.2,0.4,0.6,0.8
- 第 2 个输出神经元权重:0.1,0.3,0.5,0.7
假设偏置:
- 第 1 个偏置:0.1
- 第 2 个偏置:0.2
二、开始计算
1. 第一层 → 第二层
第 1 个神经元:1×0.1 + 2×0.5 + 3×0.9 + 0.1 = 3.9第 2 个神经元:1×0.2 + 2×0.6 + 3×1.0 + 0.2 = 4.6第 3 个神经元:1×0.3 + 2×0.7 + 3×1.1 + 0.3 = 5.3第 4 个神经元:1×0.4 + 2×0.8 + 3×1.2 + 0.4 = 6.0
第二层输出:3.9,4.6,5.3,6.0
2. 第二层 → 第三层
按假设,第 2 个神经元置为 0:
第三层输出:3.9,0,5.3,6.0
3. 第三层 → 第四层
第 1 个输出:3.9×0.2 + 0×0.4 + 5.3×0.6 + 6.0×0.8 + 0.1 = 8.86
第 2 个输出:3.9×0.1 + 0×0.3 + 5.3×0.5 + 6.0×0.7 + 0.2 = 7.44
最终结果
第四层神经网络输出:8.86,7.44
输出层
卷积神经网络的输出层理解起来就比较简单了,只需要将全连接层得到的一维向量经过计算后得到识别值的一个概率,当然,这个计算可能是线性的,也可能是非线性的。在深度学习中,我们需要识别的结果一般都是多分类的,所以每个位置都会有一个概率值,代表识别为当前值的概率,取最大的概率值,就是最终的识别结果。
卷积神经网络(CNN)流程图
以上就是卷积神经网络(CNN)的基本流程,然我们通过下图在回忆一遍吧!
相信你对卷积神经网络(CNN)有了一定的了解,下面我们通过一些简单且经典的模型加固一下我们的认识吧!
经典模型
LeNet
LeNet模型背景
LeNet由Yann LeCun等人于1998年提出,是早期卷积神经网络(CNN)的代表性模型,主要用于手写数字识别任务(如MNIST数据集)。其结构奠定了现代CNN的基础。
LeNet模型结构
输入层
接收32×32像素的灰度图像(原始论文针对邮政手写数字设计)。
卷积层C1
- 使用6个5×5的卷积核,步长为1。
- 输出特征图尺寸:28×28×6(32−5+1=28)。
- 激活函数:Sigmoid或Tanh(原始论文使用Sigmoid)。
池化层S2
- 平均池化(2×2窗口,步长为2)。
- 输出特征图尺寸:14×14×6。
卷积层C3
- 使用16个5×5的卷积核,步长为1。
- 输出特征图尺寸:10×10×16。
池化层S4
- 平均池化(2×2窗口,步长为2)。
- 输出特征图尺寸:5×5×16。
全连接层C5
- 将5×5×16=400维特征展平,连接120个神经元。
- 激活函数:Sigmoid。
全连接层F6
- 84个神经元,用于进一步特征提取。
输出层
- 10个神经元(对应0~9数字分类),使用Softmax激活函数。
LeNet模型特点
- 局部感受野:通过卷积核捕捉局部特征。
- 权值共享:减少参数数量,提升效率。
- 下采样:池化层降低计算复杂度,增强平移不变性。
代码实现(PyTorch示例)
import torch.nn as nn class LeNet(nn.Module): def __init__(self): super(LeNet, self).__init__() self.conv1 = nn.Conv2d(1, 6, 5) self.pool = nn.AvgPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16*5*5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(torch.sigmoid(self.conv1(x))) x = self.pool(torch.sigmoid(self.conv2(x))) x = x.view(-1, 16*5*5) x = torch.sigmoid(self.fc1(x)) x = torch.sigmoid(self.fc2(x)) x = self.fc3(x) return x应用与局限性
- 应用场景:手写字符识别、简单图像分类。
- 局限性:参数量较小,难以处理复杂图像(如高分辨率、多类别任务)。
AlexNet
AlexNet模型背景
AlexNet是由Alex Krizhevsky、Ilya Sutskever和Geoffrey Hinton在2012年提出的深度卷积神经网络模型,在ImageNet竞赛(ILSVRC-2012)中以显著优势获胜,标志着深度学习在计算机视觉领域的突破性进展。
AlexNet核心结构
- 输入层:处理224×224像素的RGB图像(实际输入为227×227,因原始论文存在笔误)。
- 卷积层:共5层,使用ReLU激活函数替代传统Sigmoid,提升训练效率。
- 第一层:96个11×11卷积核,步长4,输出55×55特征图。
- 第二层:256个5×5卷积核,步长1,配合最大池化。
- 池化层:采用重叠最大池化(3×3窗口,步长2),减少过拟合。
- 全连接层:3层,包含4096个神经元,最后一层输出1000类ImageNet分类结果。
- Dropout:在全连接层引入0.5概率的Dropout,防止过拟合。
关键技术特点
- ReLU激活函数:解决梯度消失问题,加速收敛。
- 多GPU并行:模型在训练时分布在两块GPU上,提升计算效率。
- 局部响应归一化(LRN):增强局部特征的区分度(后续研究证明效果有限)。
影响与后续发展
AlexNet推动了深度学习在CV领域的广泛应用,其架构设计理念(如深度堆叠、ReLU、Dropout)成为后续模型(如VGG、ResNet)的基础。当前虽被更高效模型取代,但其历史地位不可忽视。
代码示例(PyTorch实现片段):
class AlexNet(nn.Module): def __init__(self, num_classes=1000, init_weights=False): super(AlexNet, self).__init__() self.features = nn.Sequential( # Sequential将一系列层结构打包 # 卷积核个数均采用原AlexNet的一半 nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # input[3, 224, 224] output[48, 55, 55] nn.ReLU(inplace=True), # inplace可理解为pytorch增加计算量、降低内存使用的一种方法 nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27, 27] nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27] nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13] nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13] nn.ReLU(inplace=True), nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13] nn.ReLU(inplace=True), nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128, 13, 13] nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6] ) self.classifier = nn.Sequential(# 全连接层 # Dropout加在两个全连接层之间 nn.Dropout(p=0.5),# 神经元随机失活的比例=0.5 # 展成一维的并且卷积核的个数为原AlexNet的一半 # 因此不是256*6*6,而是128 * 6 * 6,且FC1的卷积核大小为2048 nn.Linear(128 * 6 * 6, 2048), nn.ReLU(inplace=True), nn.Dropout(p=0.5), # 第二个全连接层 nn.Linear(2048, 2048), nn.ReLU(inplace=True), # 第三个全连接层,输出num_classes的数值是训练集类别的个数 # 对于花的数据集num_classes=5 nn.Linear(2048, num_classes), ) # 在pytorch中其实并不需要此函数 # pytorch自动使用kaiming_normal_对卷积层和全连接层进行初始化 if init_weights:# 初始化权重函数,init_weights=True时,会执行此函数 self._initialize_weights() # 正向传播 def forward(self, x): x = self.features(x) # 展平处理 pytorch的tensor排列顺序为[batch,channel,height,width] # 0维的batch不用,故start_dim=1,也可以使用view函数展平 x = torch.flatten(x, start_dim=1) # 输入到分类结构中,即后面的三个全连接层 x = self.classifier(x) return xGoogleNet
GoogleNet模型简介
GoogleNet,也称为Inception v1,是2014年由Google团队提出的一种深度卷积神经网络架构。该模型在ImageNet Large Scale Visual Recognition Challenge (ILSVRC) 2014竞赛中取得了优异成绩,其核心创新在于Inception模块的设计,显著提升了计算效率和特征提取能力。
核心特点
Inception模块
采用多分支结构并行处理不同尺度的卷积(1x1、3x3、5x5)和池化操作,通过拼接(concatenation)融合多尺度特征。1x1卷积用于降维,减少计算量。网络深度与宽度
共22层(含池化层),但参数量仅为AlexNet的1/12(约500万参数),通过稀疏连接和高效结构设计实现轻量化。辅助分类器
在中间层添加两个辅助分类器,缓解梯度消失问题,增强模型训练稳定性。
关键改进
全局平均池化
替代全连接层,减少过拟合风险。高效硬件利用
Inception模块通过并行计算优化GPU利用率,提升训练速度。
后续版本
Inception v2/v3
引入批量归一化(Batch Normalization)和卷积分解(如将5x5分解为两个3x3)。Inception v4
结合残差连接(ResNet思想),进一步优化性能。
代码示例
class GoogLeNet(nn.Module): def __init__(self, num_classes=1000, aux_logits=True, init_weights=False): super(GoogLeNet, self).__init__() self.aux_logits = aux_logits self.conv1 = BasicConv2d(3, 64, kernel_size=7, stride=2, padding=3) self.maxpool1 = nn.MaxPool2d(3, stride=2, ceil_mode=True) self.conv2 = BasicConv2d(64, 64, kernel_size=1) self.conv3 = BasicConv2d(64, 192, kernel_size=3, padding=1) self.maxpool2 = nn.MaxPool2d(3, stride=2, ceil_mode=True) self.inception3a = Inception(192, 64, 96, 128, 16, 32, 32) self.inception3b = Inception(256, 128, 128, 192, 32, 96, 64) self.maxpool3 = nn.MaxPool2d(3, stride=2, ceil_mode=True) self.inception4a = Inception(480, 192, 96, 208, 16, 48, 64) self.inception4b = Inception(512, 160, 112, 224, 24, 64, 64) self.inception4c = Inception(512, 128, 128, 256, 24, 64, 64) self.inception4d = Inception(512, 112, 144, 288, 32, 64, 64) self.inception4e = Inception(528, 256, 160, 320, 32, 128, 128) self.maxpool4 = nn.MaxPool2d(3, stride=2, ceil_mode=True) self.inception5a = Inception(832, 256, 160, 320, 32, 128, 128) self.inception5b = Inception(832, 384, 192, 384, 48, 128, 128) if self.aux_logits: self.aux1 = InceptionAux(512, num_classes) self.aux2 = InceptionAux(528, num_classes) self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.dropout = nn.Dropout(0.4) self.fc = nn.Linear(1024, num_classes) if init_weights: self._initialize_weights() def forward(self, x): # N x 3 x 224 x 224 x = self.conv1(x) # N x 64 x 112 x 112 x = self.maxpool1(x) # N x 64 x 56 x 56 x = self.conv2(x) # N x 64 x 56 x 56 x = self.conv3(x) # N x 192 x 56 x 56 x = self.maxpool2(x) # N x 192 x 28 x 28 x = self.inception3a(x) # N x 256 x 28 x 28 x = self.inception3b(x) # N x 480 x 28 x 28 x = self.maxpool3(x) # N x 480 x 14 x 14 x = self.inception4a(x) # N x 512 x 14 x 14 if self.training and self.aux_logits: # eval model lose this layer aux1 = self.aux1(x) x = self.inception4b(x) # N x 512 x 14 x 14 x = self.inception4c(x) # N x 512 x 14 x 14 x = self.inception4d(x) # N x 528 x 14 x 14 if self.training and self.aux_logits: # eval model lose this layer aux2 = self.aux2(x) x = self.inception4e(x) # N x 832 x 14 x 14 x = self.maxpool4(x) # N x 832 x 7 x 7 x = self.inception5a(x) # N x 832 x 7 x 7 x = self.inception5b(x) # N x 1024 x 7 x 7 x = self.avgpool(x) # N x 1024 x 1 x 1 x = torch.flatten(x, 1) # N x 1024 x = self.dropout(x) x = self.fc(x) # N x 1000 (num_classes) if self.training and self.aux_logits: # eval model lose this layer return x, aux2, aux1 return x以上就是我要分享的全部内容,如果对你有帮助的话请留下你的关注🎉🎉🎉和点赞💓💓💓
如果以上内容有问题的话,可发至评论区,方便大家纠正哦💕💕💕