经典的卷积神经网络模型 - VGGNet

经典的卷积神经网络模型 - VGGNet

flyfish

VGG网络的名称来源于其开发团队——牛津大学的视觉几何组(Visual Geometry Group)
在2014年,牛津大学的视觉几何组和Google DeepMind公司的研究人员也不例外,研发了一个名为VGG的网络, VGG网络的一个主要贡献是展示了网络的深度(即层数)在提高图像识别性能方面的重要性。他们证明了,通过增加网络的层数,可以显著提高模型的性能。
他们使用了一种非常简单却有效的设计方式,所有的卷积层都使用相同的小卷积核(3x3),这使得网络结构更为一致和简单。
VGG网络由多个卷积层和池化层堆叠而成,卷积层负责提取图像的特征,池化层则用于缩小特征图的尺寸。
这些层之后,网络还有几个全连接层,用于对提取的特征进行分类。
具体来说,VGG16模型有16个权重层,其中包含13个卷积层和3个全连接层。
VGG网络有多个变体,例如VGG11、VGG13、VGG16、VGG19等,这些变体的数字表示网络中权重层(卷积层和全连接层)的总数。例如,VGG16有16个权重层,VGG19有19个权重层。

import torchvision.models as models
vgg16 = models.vgg16()
print(vgg16)
VGG((features): Sequential((0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(3): ReLU(inplace=True)(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(6): ReLU(inplace=True)(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(8): ReLU(inplace=True)(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(11): ReLU(inplace=True)(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(13): ReLU(inplace=True)(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(15): ReLU(inplace=True)(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(18): ReLU(inplace=True)(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(20): ReLU(inplace=True)(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(22): ReLU(inplace=True)(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(25): ReLU(inplace=True)(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(27): ReLU(inplace=True)(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(29): ReLU(inplace=True)(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False))(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))(classifier): Sequential((0): Linear(in_features=25088, out_features=4096, bias=True)(1): ReLU(inplace=True)(2): Dropout(p=0.5, inplace=False)(3): Linear(in_features=4096, out_features=4096, bias=True)(4): ReLU(inplace=True)(5): Dropout(p=0.5, inplace=False)(6): Linear(in_features=4096, out_features=1000, bias=True))
)

手工用函数实现VGGNet

import torch
import torch.nn as nnclass VGG(nn.Module):def __init__(self):super(VGG, self).__init__()self.features = nn.Sequential(nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),)self.avgpool = nn.AdaptiveAvgPool2d((7, 7))self.classifier = nn.Sequential(nn.Linear(512 * 7 * 7, 4096),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(4096, 4096),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(4096, 1000),)def forward(self, x):x = self.features(x)x = self.avgpool(x)x = torch.flatten(x, 1)x = self.classifier(x)return xvgg16 = VGG()
print(vgg16)

特点

特征图尺寸单调递减:是的,从输入的224x224开始,经过每一个MaxPooling层,特征图的尺寸都在减小:224 -> 112 -> 56 -> 28 -> 14 -> 7。
特征图数量单调递增:是的,从输入的3个通道开始,特征图的数量随着网络的加深不断增加:3 -> 64 -> 128 -> 256 -> 512。

假设输入图像的大小为 224 × 224 224 \times 224 224×224(RGB图像,3个通道)。

第一段卷积层和池化层

  1. 输入: 224 × 224 × 3 224 \times 224 \times 3 224×224×3
    Conv2d(3, 64, kernel_size=3, stride=1, padding=1) -> 输出: 224 × 224 × 64 224 \times 224 \times 64 224×224×64
    ReLU(inplace=True)

  2. 输入: 224 × 224 × 64 224 \times 224 \times 64 224×224×64
    Conv2d(64, 64, kernel_size=3, stride=1, padding=1) -> 输出: 224 × 224 × 64 224 \times 224 \times 64 224×224×64
    ReLU(inplace=True)

  3. 输入: 224 × 224 × 64 224 \times 224 \times 64 224×224×64
    MaxPool2d(kernel_size=2, stride=2) -> 输出: 112 × 112 × 64 112 \times 112 \times 64 112×112×64

第二段卷积层和池化层

  1. 输入: 112 × 112 × 64 112 \times 112 \times 64 112×112×64
    Conv2d(64, 128, kernel_size=3, stride=1, padding=1) -> 输出: 112 × 112 × 128 112 \times 112 \times 128 112×112×128
    ReLU(inplace=True)

  2. 输入: 112 × 112 × 128 112 \times 112 \times 128 112×112×128
    Conv2d(128, 128, kernel_size=3, stride=1, padding=1) -> 输出: 112 × 112 × 128 112 \times 112 \times 128 112×112×128
    ReLU(inplace=True)

  3. 输入: 112 × 112 × 128 112 \times 112 \times 128 112×112×128
    MaxPool2d(kernel_size=2, stride=2) -> 输出: 56 × 56 × 128 56 \times 56 \times 128 56×56×128

第三段卷积层和池化层

  1. 输入: 56 × 56 × 128 56 \times 56 \times 128 56×56×128
    Conv2d(128, 256, kernel_size=3, stride=1, padding=1) -> 输出: 56 × 56 × 256 56 \times 56 \times 256 56×56×256
    ReLU(inplace=True)

  2. 输入: 56 × 56 × 256 56 \times 56 \times 256 56×56×256
    Conv2d(256, 256, kernel_size=3, stride=1, padding=1) -> 输出: 56 × 56 × 256 56 \times 56 \times 256 56×56×256
    ReLU(inplace=True)

  3. 输入: 56 × 56 × 256 56 \times 56 \times 256 56×56×256
    Conv2d(256, 256, kernel_size=3, stride=1, padding=1) -> 输出: 56 × 56 × 256 56 \times 56 \times 256 56×56×256
    ReLU(inplace=True)

  4. 输入: 56 × 56 × 256 56 \times 56 \times 256 56×56×256
    MaxPool2d(kernel_size=2, stride=2) -> 输出: 28 × 28 × 256 28 \times 28 \times 256 28×28×256

第四段卷积层和池化层

  1. 输入: 28 × 28 × 256 28 \times 28 \times 256 28×28×256
    Conv2d(256, 512, kernel_size=3, stride=1, padding=1) -> 输出: 28 × 28 × 512 28 \times 28 \times 512 28×28×512
    ReLU(inplace=True)

  2. 输入: 28 × 28 × 512 28 \times 28 \times 512 28×28×512
    Conv2d(512, 512, kernel_size=3, stride=1, padding=1) -> 输出: 28 × 28 × 512 28 \times 28 \times 512 28×28×512
    ReLU(inplace=True)

  3. 输入: 28 × 28 × 512 28 \times 28 \times 512 28×28×512
    Conv2d(512, 512, kernel_size=3, stride=1, padding=1) -> 输出: 28 × 28 × 512 28 \times 28 \times 512 28×28×512
    ReLU(inplace=True)

  4. 输入: 28 × 28 × 512 28 \times 28 \times 512 28×28×512
    MaxPool2d(kernel_size=2, stride=2) -> 输出: 14 × 14 × 512 14 \times 14 \times 512 14×14×512

第五段卷积层和池化层

  1. 输入: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    Conv2d(512, 512, kernel_size=3, stride=1, padding=1) -> 输出: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    ReLU(inplace=True)

  2. 输入: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    Conv2d(512, 512, kernel_size=3, stride=1, padding=1) -> 输出: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    ReLU(inplace=True)

  3. 输入: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    Conv2d(512, 512, kernel_size=3, stride=1, padding=1) -> 输出: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    ReLU(inplace=True)

  4. 输入: 14 × 14 × 512 14 \times 14 \times 512 14×14×512
    MaxPool2d(kernel_size=2, stride=2) -> 输出: 7 × 7 × 512 7 \times 7 \times 512 7×7×512

平均池化层

  1. 输入: 7 × 7 × 512 7 \times 7 \times 512 7×7×512
    AdaptiveAvgPool2d(output_size=(7, 7)) -> 输出: 7 × 7 × 512 7 \times 7 \times 512 7×7×512

全连接层

  1. 输入: 7 × 7 × 512 = 25088 7 \times 7 \times 512 = 25088 7×7×512=25088 (展平)
    Linear(25088, 4096) -> 输出: 4096
    ReLU(inplace=True)
    Dropout(p=0.5)

  2. 输入: 4096
    Linear(4096, 4096) -> 输出: 4096
    ReLU(inplace=True)
    Dropout(p=0.5)

  3. 输入: 4096
    Linear(4096, 1000) -> 输出: 1000

特征图的尺寸都在减小:224 -> 112 -> 56 -> 28 -> 14 -> 7。
特征图数量单调递增:3 -> 64 -> 128 -> 256 -> 512。

如何数层数(数权重层)

卷积层 (Convolutional Layers)

1. Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
2. Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
3. Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
4. Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
5. Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
6. Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
7. Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
8. Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
9. Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
10. Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
11. Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
12. Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
13. Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

全连接层 (Fully Connected Layers)

1. Linear(in_features=25088, out_features=4096, bias=True)
2. Linear(in_features=4096, out_features=4096, bias=True)
3. Linear(in_features=4096, out_features=1000, bias=True)

统计权重层

卷积层和全连接层总共13+3=16层,因此命名为VGG16。

注意:ReLU和MaxPooling层不算作权重层,因为它们不包含可训练的参数。
在计算神经网络的层数时,ReLU和MaxPooling层不计入可训练层。可训练层指的是那些在训练过程中具有可调节权重的层,如卷积层(Conv2d)和全连接层(Linear)。

  • ReLU 只对输入进行非线性变换
  • MaxPooling 只对输入进行下采样数

ReLU层

ReLU(Rectified Linear Unit)是一种激活函数,定义为 f ( x ) = max ⁡ ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x)
它对输入值进行逐元素的非线性变换,将所有负值设为0,正值保持不变。
ReLU层本质上只是一个数学操作,不涉及任何参数。因此,在训练过程中,没有任何权重需要更新。

MaxPooling层

MaxPooling是一种池化操作,用于减小特征图的尺寸,同时保留最重要的特征。常见的最大池化操作是2x2窗口,每个窗口选取其中的最大值。 MaxPooling层通过固定的规则(选择每个窗口中的最大值)来操作输入特征图,没有任何需要学习的参数。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

正则表达式数字匹配技巧与应用场景分析

正则表达式数字匹配技巧与应用场景分析 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 正则表达式的基本概念 正则表达式(Regular Expression…

Redis基础教程(六):redis 哈希(Hash)

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝&#x1f49…

3D开发工具HOOPS助力3D制造业仿真应用实现工厂环境规划和模拟!

HOOPS SDK是全球领先的3D领域开发工具提供商Tech Soft 3D 打造的控件产品,HOOPS SDK包括4款3D软件开发工具,其中HOOPS Exchange是一款CAD数据转换工具,可读取和导入30多种CAD文件格式;HOOPS Communicator是一款专注于Web端工程图形…

昇思25天学习打卡营第13天|基于MobileNetV2的垃圾分类

MobileNetv2模型原理介绍 相比于传统的卷积神经网络,MobileNet网络使用深度可分离卷积(Depthwise Separable Convolution)的思想在准确率小幅度降低的前提下,大大减小了模型参数与运算量。并引入宽度系数α和分辨率系数β使模型满…

根据后端返回的省市区重新封装树结构(省市区通过children表示)

对比图(截取部分): 注:先看分步,最后会附上完整代码(如果有用,可以给小编点个赞吗?十分感谢) 1.首先将前端返回相同的省份只展示一次 const obj {}; let keyList []r…

SpringBoot创建一个初始化项目

提示:这一篇文章,主要是为了之后可以快速的去搭建项目,当然这篇博客,作者也会根据以后学习到的东西,慢慢去整理 文章目录 前言 搭建一个SpringBoot项目,目的是为了快速开发项目 项目列表 响应枚举类 /***…

面向优秀SCI论文写作的语言大模型提示词设计

模板1:Abstract 润色 I want you to act as an SCI reviewer and evaluate the abstract of a research paper. You may check if the abstract is well-written and serves as an informative and descriptive overview of the research. You may also check if it…

Docker 部署 Nacos v2.3.2 版本

文章目录 Github官网文档Nacos 生态图Nacos Dockerdocker-compose.ymlapplication.propertiesNacos 官方示例 Github https://github.com/alibaba/nacos 官网 https://nacos.io/ 文档 https://nacos.io/docs/latest/what-is-nacos/ Nacos 生态图 Nacos Docker 镜像&…

ARM功耗管理软件之DVFSAVS

安全之安全(security)博客目录导读 思考:功耗管理软件栈及示例?WFI&WFE?时钟&电源树?DVFS&AVS? 目录 一、ARM功耗管理软件之DVFS 二、ARM功耗管理软件之AVS 一、ARM功耗管理软件之DVFS 有一个实现特定…

我的技术十年

前言 十年一瞬,2014 年毕业至今,刚好十年。《异类》一书曾提到“一万小时定律”,要成为某个领域的专家,需要 10000 小时,按比例计算就是:如果你每天工作八小时,一天工作五天,那么成…

2024-07-01_外语学习

文章目录 前言1、Los Angeles至于单个los 是什么意思?我们可以逐词翻译这个西班牙语句子 2. Extraneous non-props attributes (style) were passed to component but could not be automatically inherited because component renders fragment or text root nodes…

python全局解释器锁(GIL)

文章目录 1.cpu工作方式2.python全局解释器锁与多线程3.其他语言的多线程4.如何解决假的多线程 1.cpu工作方式 先来先服务(First Come, First Served,FCFS): 最简单的调度算法,按照作业或进程到达的顺序依次执行。没有…

ONLYOFFICE8.1版本桌面编辑器的测评(您的私人办公室)

ONLYOFFICE官网链接:ONLYOFFICE - 企业在线办公应用软件 | ONLYOFFICE 在线PDF查看器和转换器 | ONLYOFFICE​​​​​​在线办公套件 | ONLYOFFICE 一,引言 在数字化浪潮中,高效、便捷、安全的办公工具对现代职场至关重要。今天,…

SOC模块LoRa-STM32WLE5有哪些值得关注

SoC 是片上系统的缩写,是一种集成芯片,集成了计算机或其他电子系统的所有或大部分组件。这些组件通常包括中央处理器 (CPU)、内存、输入/输出接口和辅助存储接口。包含数字、模拟、混合信号和通常的 RF 信号处理功能,具体取决于应用。片上系统…

守护矿山安全生产:AI视频分析技术在煤矿领域的应用

随着人工智能(AI)技术的快速发展,其在煤矿行业的应用也日益广泛。AI视频智能分析技术作为其中的重要分支,为煤矿的安全生产、过程监测、效率提升和监管决策等提供了有力支持。 一、煤矿AI视频智能分析技术的概述 视频智慧煤矿AI…

6 矩阵相关案例

矩阵计算在CUDA中的应用是并行计算领域的典型场景 ; 矩阵算法题通常涉及线性代数的基础知识,以及对数据结构和算法的深入理解。解决这类问题时,掌握一些核心思想和技巧会非常有帮助。以下是一些常见的矩阵算法题解题思想: 动态规划…

二叉树遍历学习

前序遍历: 遍历顺序是根节点,左子树,右子树 中序遍历的顺序是左子树、根节点、右子树 后序遍历的顺序是左子树、右子树、根节点。 /*** Description: 递归 实现 二叉树的 先中后序* Author: wule* Date: 2024/7/1 13:44*/ public class Erchashu {/*** 定…

pytorch nn.Embedding 用法和原理

nn.Embedding 是 PyTorch 中的一个模块,用于将离散的输入(通常是词或子词的索引)映射到连续的向量空间。它在自然语言处理和其他需要处理离散输入的任务中非常常用。以下是 nn.Embedding 的用法和原理。 用法 初始化 nn.Embedding nn.Embed…

LeetCode 1321, 209, 102

目录 1321. 餐馆营业额变化增长题目链接表要求知识点思路代码 209. 长度最小的子数组题目链接标签暴力法思路代码 滑动窗口思路代码 102. 二叉树的层序遍历题目链接标签思路代码 1321. 餐馆营业额变化增长 题目链接 1321. 餐馆营业额变化增长 表 表Customer的字段为custome…

使用Python实现学生管理系统

文章目录 1. 系统概述2. 系统功能3. 实现细节3.1 初始化学生列表3.2 添加学生3.3 显示所有学生3.4 查找学生3.5 删除学生3.6 主菜单 4. 运行系统 在本文中,我们将使用Python编程语言来开发一个简单的学生管理系统。该系统将允许用户执行基本的学生信息管理操作&…