【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解

文章目录

  • 【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解
  • 前言
  • AlexNet讲解
    • 卷积层的作用
    • 卷积过程
    • 特征图的大小计算公式
    • Dropout的作用
    • AlexNet模型结构
  • AlexNet Pytorch代码
  • 完整代码
  • 总结


前言

AlexNet是由多伦多大学的Krizhevsky, Alex等人在《ImageNet Classification with Deep Convolutional Neural Networks【NIPS-2012】》【论文地址】一文中提出的模型,核心思想是使用用一个深度卷积神经网络来进行图片分类,并用dropout这个正则化方法来减少过拟合。
AlexNet的出现标志着神经网络的复苏和深度学习的崛起,成功证明了深度神经网络在大规模图像分类任务中的有效性,为后续的深度学习研究提供了强有力的动力。


AlexNet讲解

卷积层的作用

在卷积神经网络里,卷积层的主要功能是通过卷积操作对输入数据进行特征提取。它使用一组可学习的卷积核(也称为滤波器或卷积矩阵),将卷积核与输入数据进行卷积运算,生成输出特征图。卷积对于提高模型的性能和提取更高层次的抽象特征非常关键。

以下是卷积层在深度学习中的几个重要含义:

  1. 特征提取:卷积层可以学习提取输入数据的局部特征。通过卷积核与输入数据进行卷积运算,卷积层能够识别图像中的边缘、纹理、形状等特征。
  2. 参数共享:卷积层具有参数共享的特性。在卷积层中,每个卷积核的参数被共享给整个输入数据的不同位置,大大减少网络的参数数量,提高模型的效率,并使模型更具鲁棒性和泛化能力。
  3. 空间局部性:卷积层通过局部感受野(receptive field)的方式处理输入数据。每个神经元只连接输入数据中一个小的局部区域,而不是全局连接,能够更好地捕捉输入数据的空间局部性特征。
  4. 下采样:卷积层通常结合池化层来进行下采样操作。池化层可以减小特征图的尺寸,并提取更加抽象的特征。
    通过堆叠多个卷积层,可以构建出深度卷积神经网络(Convolutional Neural Network,CNN),用于解决各种计算机视觉任务(图像分类、目标检测和图像分割)。

卷积过程

在卷积神经网络中,卷积层的实现方式实际上是数学中定义的互相关(cross-correlation)运算,是卷积层中的基本操作,具体的计算过程如图所示:

左边浅紫色的图表示7×7的输入图片(或特征图)矩阵;中间粉红色的图表示3×3卷积核矩阵,后边淡青色的图表示卷积层输出的特征图矩阵。

卷积操作的步骤如下:

  1. 将卷积核与输入矩阵的一个局部区域进行逐元素乘积;
  2. 对乘积结果进行求和,得到输出矩阵的一个元素;
  3. 将卷积核在输入矩阵上移动一个步幅,并重复上述操作,直到覆盖整个输入矩阵;
  4. 重复上述过程,每个卷积核生成一个输出矩阵;

卷积过程描述了卷积操作在深度学习中的数学运算,以下是卷积过程中涉及到的重要概念。

概念描述
卷积核(kernel)卷积核中数值为对图像中与卷积核同样大小的子块像素点进行卷积计算时所采用的权重
卷积计算(convolution)图像中像素点具有强烈的空间依赖性,卷积(convolution)就是针对像素点的空间依赖性来对图像进行处理
特征图(feature map)卷积核的输出结果
填充(Padding)输入矩阵的边缘周围添加额外的边缘元素(通常是0),以控制输出矩阵的尺寸
步幅(Stride)决定了在输入矩阵上卷积核每次移动的距离

特征图的大小计算公式

卷积层输出特征图(矩阵)的大小由以下几个因素决定:

  • 输入矩阵的大小: F h × F w {F_{\rm{h}}} \times {F_{{\rm{w}}}} Fh×Fw
  • 卷积核的大小: k h × k w {k_{\rm{h}}} \times {k_{{\rm{w}}}} kh×kw
  • 步幅的大小: s s s
  • 填充的大小: p a d pad pad

其基本公式为:
输出特征图的高: F h = F h _ p r e v − k h + 2 × p a d s + 1 {F_{\rm{h}}} = \frac{{{F_{{\rm{h\_prev}}}} - {k_{\rm{h}}} + 2 \times pad}}{s} + 1 Fh=sFh_prevkh+2×pad+1,输出特征图的宽: F w = F w _ p r e v − k w + 2 × p a d s + 1 {F_{\rm{w}}} = \frac{{{F_{{\rm{w\_prev}}}} - {k_{\rm{w}}} + 2 \times pad}}{s} + 1 Fw=sFw_prevkw+2×pad+1
以下是padding为1的输入8×8的输入特征特征矩阵,经过步长为2,大小为3×3的卷积核后生成3×3大小的输出特征矩阵:

同理,池化层输出特征图(矩阵)的大小由以下几个因素决定:

  • 输入矩阵的大小: F h × F w {F_{\rm{h}}} \times {F_{{\rm{w}}}} Fh×Fw
  • 卷积核的大小: k h × k w {k_{\rm{h}}} \times {k_{{\rm{w}}}} kh×kw
  • 步幅的大小: s s s

池化层不再对输出特征图进行填充,其基本公式为:
输出特征图的高: F h = F h _ p r e v − k h s + 1 {F_{\rm{h}}} = \frac{{{F_{{\rm{h\_prev}}}} - {k_{\rm{h}}}}}{s} + 1 Fh=sFh_prevkh+1,输出特征图的宽: F w = F w _ p r e v − k w s + 1 {F_{\rm{w}}} = \frac{{{F_{{\rm{w\_prev}}}} - {k_{\rm{w}}}}}{s} + 1 Fw=sFw_prevkw+1
以下是输入4×4的输入特征特征矩阵,经过步长为1,大小为3×3的池化核后生成2×2大小的输出特征矩阵:

卷积神经网络中池化核的大小通常的为2×2

Dropout的作用

Dropout是一种用于深度神经网络的正则化技术,其核心思想是在训练过程中随机地丢弃(置零)网络中的神经元,即随机地关闭一些神经元(或节点)它们以及与下一层神经元之间的连接,以减少神经元之间的共适应性,从而提高模型的泛化能力。

Dropout的特点:

  • 随机关闭神经元:在每个神经元被关闭的概率是相同的,概率是一个给定超参数。
  • 前向传播时的关闭:前向传播过程中,失活的神经元的输出值被设为零。
  • 反向传播时的开启:反向传播过程中,失活的神经元的权重不会被调整,只有真正激活的神经元参与权重更新。
  • 集成学习效果:一种可以集成学习(Ensemble Learning)的方法,因为每次迭代都会随机创建一个不同的子模型,该子模型由丢弃部分神经元后的网络组成,通过平均或投票来集成多个子网络的预测,降低模型的仰角,提高泛化性能。
  • 减少共适应性:神经网络中的神经元往往会相互适应,通过彼此的激活模式来共同处理输入数据。这种共适应性可能导致过拟合,即在训练数据上表现良好,但在测试数据上泛化能力较差,特别是在训练数据稀疏或较小的情况下。Dropout通过随机丢弃神经元,迫使网络在不同子集的神经元中学习并适应数据,从而减少神经元之间的共适应性,有助于提高模型的泛化能力。

AlexNet模型结构

下图是博主根据原论文给出的关于VGGnet模型结构绘制的详细示意图:

layer_namekernel sizekernel numpaddingstrideinput_size
Conv11196243×224×224
Maxpool13-0296×55×55
Conv252562196×27×27
Maxpool23-02256×27×27
Conv3338411256×13×13
Conv4338411384×13×13
Conv5325611384×13×13
Maxpool33-02256×13× 13
FC1-2048--256×1×1
FC2-2048--2048×1×1
FC3-1000--2048×1×1

AlexNet可以分为两部分:第⼀部分 (backbone) 主要由卷积层和池化层(汇聚层)组成,第⼆部分由全连接层 (分类器) 组成。

AlexNet的亮点说明
ReLU激活函数解决了SIgmoid在网络较深时的梯度消失问题,训练时比tanh收敛更快,并且有效防止了过拟合现象的出现。
层叠池化操作池化的步长小于核尺寸,使得输出之间会有重叠和覆盖,可以使相邻像素间产生信息交互和保留必要的联系,提升了特征的丰富性,并且避免平均池化的模糊化效果。
Dropout操作Dropout操作会将概率小于0.5的每个隐层神经元的输出设为0,选择性地将一些神经节点去掉,减少了复杂的神经元之间的相互影响,达到防止过拟合。

AlexNet Pytorch代码

backbone部分

# backbone部分
# 卷积层组:conv2d+ReLU
self.features = nn.Sequential(
            # input[3, 224, 224]  output[96, 55, 55]
            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            # input[96, 55, 55] output[96, 27, 27]
            nn.MaxPool2d(kernel_size=3, stride=2),
            # input[96, 27, 27] output[256, 27, 27]
            nn.Conv2d(96, 256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            # input[256, 27, 27] output[256, 13, 13]
            nn.MaxPool2d(kernel_size=3, stride=2),
            # input[256, 13, 13] output[384, 13, 13]
            nn.Conv2d(256, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            # input[384, 13, 13] output[384, 13, 13]
            nn.Conv2d(384, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            # input[384, 13, 13] output[256, 13, 13]
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            # input[384, 13, 13] output[256, 6, 6]
            nn.MaxPool2d(kernel_size=3, stride=2),
        )

分类器部分

# 分类器部分:Dropout+FC+ReLU
self.classifier = nn.Sequential(
	# 以0.5的概率选择性地将隐藏层神经元的输出设置为零
    nn.Dropout(p=0.5),
    nn.Linear(256 * 6 * 6, 2048),
    nn.ReLU(inplace=True),
    nn.Dropout(p=0.5),
    nn.Linear(2048, 2048),
    nn.ReLU(inplace=True),
    nn.Linear(2048, num_classes),
)

完整代码

import torch.nn as nn
import torch
from torchsummary import summary

class AlexNet(nn.Module):
    def __init__(self, num_classes=1000, init_weights=False):
        super(AlexNet, self).__init__()
        # backbone部分
        # 卷积层组:conv2d+ReLU
        self.features = nn.Sequential(
            # input[3, 224, 224]  output[96, 55, 55]
            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            # input[96, 55, 55] output[96, 27, 27]
            nn.MaxPool2d(kernel_size=3, stride=2),
            # input[96, 27, 27] output[256, 27, 27]
            nn.Conv2d(96, 256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            # input[256, 27, 27] output[256, 13, 13]
            nn.MaxPool2d(kernel_size=3, stride=2),
            # input[256, 13, 13] output[384, 13, 13]
            nn.Conv2d(256, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            # input[384, 13, 13] output[384, 13, 13]
            nn.Conv2d(384, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            # input[384, 13, 13] output[256, 13, 13]
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            # input[384, 13, 13] output[256, 6, 6]
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        # 分类器部分:Dropout+FC+ReLU
        self.classifier = nn.Sequential(
            # 以0.5的概率选择性地将隐藏层神经元的输出设置为零
            nn.Dropout(p=0.5),
            nn.Linear(256 * 6 * 6, 2048),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(2048, 2048),
            nn.ReLU(inplace=True),
            nn.Linear(2048, num_classes),
        )
        # 对模型的权重进行初始化操作
        if init_weights:
            self._initialize_weights()

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, start_dim=1)
        x = self.classifier(x)
        return x

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                # Conv2d的权重初始化为服从均值为0,标准差为sqrt(2 / fan_in)的正态分布
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    # Conv2d的偏置置0
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                # FC的权重初始化服从指定均值和标准差的正态分布
                nn.init.normal_(m.weight, 0, 0.01)
                # FC的偏置置0
                nn.init.constant_(m.bias, 0)
if __name__ == '__main__':
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    model = AlexNet().to(device)
    summary(model, input_size=(3, 224, 224))              

summary可以打印网络结构和参数,方便查看搭建好的网络结构。


总结

尽可能简单、详细的介绍了深度可分卷积的原理和卷积过程,讲解了AlexNet模型的结构和pytorch代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/118533.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读——What Can Human Sketches Do for Object Detection?(cvpr2023)

论文:https://openaccess.thecvf.com/content/CVPR2023/papers/Chowdhury_What_Can_Human_Sketches_Do_for_Object_Detection_CVPR_2023_paper.pdf 代码:What Can Human Sketches Do for Object Detection? (pinakinathc.me) 一、 Baseline SBIR Fram…

Cesium:WFS请求两种方式

以本地发布的上海市浦东区行政区划WMS地图服务为例,讲述Cesium中WFS请求的两种方式及其优缺点。 服务加载地址及其参数如下, 服务加载地址:http://localhost:8089/geoserver/pudong/wms 加载参数:layerName:pudong:distractservice: "WMS",request: "GetMa…

8-2、T型加减速计算简化【51单片机控制步进电机-TB6600系列】

摘要:本节介绍简化T型加减速计算过程,使其适用于单片机数据处理。简化内容包括浮点数转整型数计算、加减速对称处理、预处理计算 一、浮点数转整型数计算 1.1简化∆t_1计算 根据上一节内容已知 K0.676 step1.8/X(x为细分值,1.8对…

【Leetcode】349. 两个数组的交集

题意 给定两个数组,编写一个函数来计算它们的交集。 说明: 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。 思路 这道题目,主要要学会使用一种哈希数据结构:unordered_set,这个数据结构可以解决…

MYSQL:主从复制简述

(图片来自于马士兵教育) 从节点的I/O线程会请求主节点的Binlog,并且将得到的Binlog写入到本地relay_log(中继日志)中,SQL线程会读取realy_log中的日志文件,并且解析成SQL逐行执行。 主库会生成…

XSS漏洞利用工具BeEF

BeEF是Browser Exploitation Framework的缩写。随着人们越来越多地关注针对包括移动客户端在内的客户端的网络传播攻击,BeEF使专业的渗透测试人员可以使用客户端攻击向量来评估目标环境的实际安全状况。与其他安全框架不同,BeEF超越了硬化的网络边界和客…

win11下使用VMmare设置CentOS7里面的静态IP

1,win11上的VMware 8 设置 2,选择VMmare上的虚拟网络编辑进行设置 #3,接下来进入虚拟机设置(就是进入CentOS7 打开终端 右键 Open Terminal ) # 切换root su root #ksana #编辑网络配置文件 vi /etc/sysconfig/networ…

【LeetCode:318. 最大单词长度乘积 | 模拟 位运算】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

nn.embedding函数详解(pytorch)

提示:文章附有源码!!! 文章目录 前言一、nn.embedding函数解释二、nn.embedding函数使用方法四、模型训练与预测的权重变化探讨 前言 最近发现prompt工程(如sam模型),也有transform的detr模型等都使用了nn.Embedding函…

GB28181学习(十五)——流传输方式

前言 基于GB/T28181-2022版本,实时流的传输方式包括3种: UDPTCP被动TCP主动 UDP 流程 注意: m字段指定传输方式为RTP/AVP; 抓包 SIP服务器发送INVITE请求; INVITE sip:xxx192.168.0.111:5060 SIP/2.0 Via: SIP…

【C++】智能指针【内存泄漏|智能指针原理及使用|RAII】

目录 1、了解内存泄露 1.1 内存泄漏的定义及危害 1.2 内存泄漏分类(了解) 1.3 如何检测内存泄漏(了解) 1.4如何避免内存泄漏 2、智能指针的引出 3、智能指针的使用及原理 3.1 RAII 3.2 智能指针的原理 3.3 std::auto_pt…

skynet学习笔记01— skynet开发环境搭建(超详细)与第一个skynet程序

00、参考资料 https://blog.csdn.net/qq769651718/category_7480207.html 01、前置准备 开发所在目录 mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ pwd /home/mhzzj/work/skynetStudy前置准备 mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ sudo apt install lua5…

手动关闭PS中的TopazStudio2的登录窗口

2021 adobe photoshop Topaz Studio 2 不是使用防火墙出站规则,是手动关闭的解决方案 点击社区-切换用户,登录窗口会出现X,可以手动关闭

【flutter no devices】

1.在环境变量增加 ANDROID_HOME 值为:C:\Users\Administrator\AppData\Local\Android\Sdk (Android sdk 位置) 2 环境变量的path里面增加2个值: %ANDROID_HOME%\platform-tools %ANDROID_HOME%\tools 3 打开cmd,或者在Android st…

uniapp使用抖音微信自定义组件

tt.vue中使用video-player组件 用到的目录如下: pages.json {"path": "pages/Tabbar/tt/tt","style": {"navigationBarTitleText": "","enablePullDownRefresh": false,// 使用自定义组件"using…

使用R语言构建HTTP爬虫:IP管理与策略

目录 摘要 一、HTTP爬虫与IP管理概述 二、使用R语言进行IP管理 三、爬虫的伦理与合规性 四、注意事项 结论 摘要 本文深入探讨了使用R语言构建HTTP爬虫时如何有效管理IP地址。由于网络爬虫高频、大量的请求可能导致IP被封禁,因此合理的IP管理策略显得尤为重要…

【JAVA学习笔记】63 -坦克大战1.3-敌方发射子弹,击中坦克消失并爆炸,敌人坦克随机移动,规定范围限制移动

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter18/src/com/yinhai/tankgame1_3 〇、要求 增加功能 1.让敌人的坦克也能够发射子弹(可以有多颗子弹) 2.当我方坦克击中敌人坦克时,敌人的坦克就消失,如果能做出爆炸效果更好. …

人工智能-卷积神经网络

从全连接层到卷积 我们之前讨论的多层感知机十分适合处理表格数据,其中行对应样本,列对应特征。 对于表格数据,我们寻找的模式可能涉及特征之间的交互,但是我们不能预先假设任何与特征交互相关的先验结构。 此时,多层感…

Java锁常见面试题

图片引用自:不可不说的Java“锁”事 - 美团技术团队 1 java内存模型 java内存模型(JMM)是线程间通信的控制机制。JMM定义了主内存和线程之间抽象关系。线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该…

计算机毕业设计java+springboot+vue的旅游攻略平台

项目介绍 本系统结合计算机系统的结构、概念、模型、原理、方法,在计算机各种优势的情况下,采用JAVA语言,结合SpringBoot框架与Vue框架以及MYSQL数据库设计并实现的。员工管理系统主要包括个人中心、用户管理、攻略管理、审核信息管理、积分…