疏老师-python训练营-Day54Inception网络及其思考

@浙大疏锦行

DAY54

一、 inception网络介绍

今天我们介绍inception,也就是GoogleNet

传统计算机视觉的发展史

从上面的链接,可以看到其实inceptionnet是在resnet之前的,那为什么我今天才说呢?因为他要引出我们后面的特征融合和特征并行处理这些思想。

Inception 网络,也被称为 GoogLeNet,是 Google 团队在 2014 年提出的经典卷积神经网络架构。它的核心设计理念是 “并行的多尺度融合”,通过在同一层网络中使用多个不同大小的卷积核(如 1x1、3x3、5x5)以及池化操作,从不同尺度提取图像特征,然后将这些特征进行融合,从而在不增加过多计算量的情况下,获得更丰富的特征表达。

Inception 模块是 Inception 网络的基本组成单元。

在同样的步长下,卷积核越小,下采样率越低,保留的图片像素越多;卷积核越大,越能捕捉像素周围的信息。

一个典型的 Inception 模块包含以下几个并行的分支:

  • 1x1 卷积分支:用于降维,减少后续卷积操作的计算量,同时提取局部特征。​(像素下采样率低,但是可以修改通道数)
  • 3x3 卷积分支:捕捉中等尺度的特征。​
  • 5x5 卷积分支:捕捉较大尺度的特征。​
  • 池化分支:通常使用最大池化或平均池化,用于保留图像的全局信息。

二、 inception网络架构

2.1 定义inception模块

import torch
import torch.nn as nnclass Inception(nn.Module):def __init__(self, in_channels):"""Inception模块初始化,实现多尺度特征并行提取与融合参数:in_channels: 输入特征图的通道数"""super(Inception, self).__init__()# 1x1卷积分支:降维并提取通道间特征关系# 减少后续卷积的计算量,同时保留局部特征信息self.branch1x1 = nn.Sequential(nn.Conv2d(in_channels, 64, kernel_size=1),  # 降维至64通道nn.ReLU()  # 引入非线性激活)# 3x3卷积分支:通过1x1卷积降维后使用3x3卷积捕捉中等尺度特征# 先降维减少计算量,再进行空间特征提取self.branch3x3 = nn.Sequential(nn.Conv2d(in_channels, 96, kernel_size=1),  # 降维至96通道nn.ReLU(),nn.Conv2d(96, 128, kernel_size=3, padding=1),  # 3x3卷积,保持空间尺寸不变nn.ReLU())# 5x5卷积分支:通过1x1卷积降维后使用5x5卷积捕捉大尺度特征# 较大的感受野用于提取更全局的结构信息self.branch5x5 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),  # 大幅降维至16通道nn.ReLU(),nn.Conv2d(16, 32, kernel_size=5, padding=2),  # 5x5卷积,保持空间尺寸不变nn.ReLU())# 池化分支:通过池化操作保留全局信息并降维# 增强特征的平移不变性self.branch_pool = nn.Sequential(nn.MaxPool2d(kernel_size=3, stride=1, padding=1),  # 3x3最大池化,保持尺寸nn.Conv2d(in_channels, 32, kernel_size=1),  # 降维至32通道nn.ReLU())def forward(self, x):"""前向传播函数,并行计算四个分支并在通道维度拼接参数:x: 输入特征图,形状为[batch_size, in_channels, height, width]返回:拼接后的特征图,形状为[batch_size, 256, height, width]"""# 注意,这里是并行计算四个分支branch1x1 = self.branch1x1(x)  # 输出形状: [batch_size, 64, height, width]branch3x3 = self.branch3x3(x)  # 输出形状: [batch_size, 128, height, width]branch5x5 = self.branch5x5(x)  # 输出形状: [batch_size, 32, height, width]branch_pool = self.branch_pool(x)  # 输出形状: [batch_size, 32, height, width]# 在通道维度(dim=1)拼接四个分支的输出# 总通道数: 64 + 128 + 32 + 32 = 256outputs = [branch1x1, branch3x3, branch5x5, branch_pool]return torch.cat(outputs, dim=1)

上述模块变化为[B, C, H, W]-->[B, 256, H, W]

model = Inception(in_channels=64)
input = torch.randn(32, 64, 28, 28)
output = model(input)
print(f"输入形状: {input.shape}")
print(f"输出形状: {output.shape}")  
输入形状: torch.Size([32, 64, 28, 28])
输出形状: torch.Size([32, 256, 28, 28])

inception模块中不同的卷积核和步长最后输出同样尺寸的特征图,这是经过精心设计的,才能在空间上对齐,才能在维度上正确拼接(concat)。

2.2 特征融合方法

这里我们注意到,它是对把不同尺度的特征融合在一起。concat这种增加通道数的方法是一种经典的特征融合方法。通道数增加,空间尺寸(H, W)保持不变,每个通道的数值保持独立,没有加法运算。相当于把不同特征图 “并排” 放在一起,形成更 “厚” 的特征矩阵。

在深度学习中,特征融合的尺度有以下方式:

  1. 逐元素相加:将相同形状的特征图对应位置的元素直接相加,比如残差连接:
    output = x + self.residual_block(x)

不改变特征图尺寸和通道数,计算高效,但需保证输入形状一致。

  1. 逐元素相乘:通过乘法对特征进行权重分配,抑制无关特征,增强关键特征。比如注意力机制、门控机制(如 LSTM 中的遗忘门、输入门),例如

    attention = self.ChannelAttention(features)  # 生成通道权重
    weighted_features = features * attention  # 逐元素相乘

其他的特征融合方法我们后面有机会介绍

2.3 InceptionNet网络定义

class InceptionNet(nn.Module):def __init__(self, num_classes=10):super(InceptionNet, self).__init__()self.conv1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))self.inception1 = Inception(64)self.inception2 = Inception(256)self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(256, num_classes)def forward(self, x):x = self.conv1(x)x = self.inception1(x)x = self.inception2(x)x = self.avgpool(x)x = torch.flatten(x, 1)x = self.fc(x)return x
# 创建网络实例
model = InceptionNet()
# 创建一个随机输入张量,模拟图像数据,这里假设输入图像是3通道,尺寸为224x224
input_tensor = torch.randn(1, 3, 224, 224)
# 前向传播
output = model(input_tensor)
print(output.shape)
torch.Size([1, 10])

inception网络有着很多变体,Inception v1版本就是 GoogLeNet,他还有v2到v4,还版本,还可以引入残差连接,如 Inception-ResNet-v2 在 ImageNet 上 top-1 准确率达 96.4%

多尺度融合等其他技巧我们将在科研班中展开了,因为单纯从讲义的形式来说,实在是不方便。将会在科研班的板块中,提到backbone-neck-head这样的范式架构设计,这将带你开启搭积木的道路。

今天的内容稍微有点单薄,我们再补充点小知识点。

三、卷积核的变体

3.1 感受野

我们发现,经常会有不同尺寸的卷积核来在特征图上滑动进一步提取信息,那么卷积核的尺寸如何选取比较合适呢?在思考这个问题前你需要理解下感受野的概念。

感受野是指在卷积神经网络(CNN)中,神经元在原始输入图像上所对应的区域大小。通俗来说,卷积层中的每个输出特征图上的一个像素点,其信息来源于输入图像中的某个特定区域,这个区域的大小就是该像素点的感受野。

假设我们有一个 3×3 的卷积核,对一张 5×5 的图像进行步长为 1 的卷积操作:

输出特征图的每个像素点,都由输入图像中 3×3 的区域计算得到,因此该层的感受野为 3×3。 如果再叠加一层 3×3 卷积(步长 1),第二层的每个像素点会融合第一层 3×3 区域的信息,而第一层的每个区域又对应原始图像的 3×3 区域,因此第二层的感受野扩展为 5×5(即 3+3-1=5)

为了方便大家理解这个5怎么来的,找了一个博主的视频方便大家理解: 感受野的理解视频解析

所以,在对应同等感受野的情况下,卷积核尺寸小有2个显著的优势:

  1. 能让参数变少,简化计算
  2. 能够引入更多的非线性(多经过几次激活函数),让拟合效果更好

这也是为什么像 VGG 网络就用多层 3×3 卷积核替代大卷积核,平衡模型性能与复杂度 。

3.2 卷积的变体

卷积也是有很多变体的,除了我们之前说过的基础的卷积,还有空洞卷积、幻影卷积等等变体。我们以空洞卷积举例:

空洞卷积(也叫扩张卷积、膨胀卷积 ),是对标准卷积的 “升级”—— 在卷积核元素间插入空洞(间隔),用 空洞率(dilation rate,记为d) 控制间隔大小。

标准卷积(d=1):卷积核元素紧密排列,直接覆盖输入特征图相邻区域。 空洞卷积(d>1):卷积核元素间插入 d-1 个空洞,等效扩大卷积核的 “感受野范围”,但不增加参数数量(仅改变计算时的采样间隔)。也就是无需增大卷积核尺寸或叠加多层卷积,仅通过调整 d,就能指数级提升感受野。

对比池化(Pooling)或下采样,空洞卷积不丢失空间信息,能在扩大感受野的同时,维持特征图尺寸,特别适合语义分割、目标检测等需要精准像素 / 目标定位的任务。

所以不同的设计,其实是为了不同的任务,比如你虽然可以捕捉不同尺度的信息,但是对于图像分类这个任务来说没用,我的核心是整个图像的类别,如果你是目标检测,对于小目标的检测中小尺度的设计就很有用。

3.3 空洞卷积示例

其实就是多了一个参数,代码上仅仅也是多了一个参数

self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=2, dilation=2)

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),  # 转为张量transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))  # 归一化
])# 加载CIFAR-10数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=True, transform=transform)
trainloader = DataLoader(trainset, batch_size=128, shuffle=True)testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)
testloader = DataLoader(testset, batch_size=128, shuffle=False)# 定义含空洞卷积的CNN模型
class SimpleCNNWithDilation(nn.Module):def __init__(self):super(SimpleCNNWithDilation, self).__init__()# 第一层:普通3×3卷积,捕捉基础特征self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)  # 第二层:空洞卷积,dilation=2,感受野扩大(等效5×5普通卷积感受野)self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=2, dilation=2)  # 第三层:普通3×3卷积,恢复特征对齐self.conv3 = nn.Conv2d(32, 64, kernel_size=3, padding=1)  self.pool = nn.MaxPool2d(2, 2)  # 池化层self.relu = nn.ReLU()# 全连接层,根据CIFAR-10尺寸计算:32×32→池化后16×16→...→最终特征维度需匹配self.fc1 = nn.Linear(64 * 8 * 8, 256)  self.fc2 = nn.Linear(256, 10)  def forward(self, x):# 输入: [batch, 3, 32, 32]x = self.conv1(x)  # [batch, 16, 32, 32]x = self.relu(x)x = self.pool(x)   # [batch, 16, 16, 16]x = self.conv2(x)  # [batch, 32, 16, 16](dilation=2 + padding=2 保持尺寸)x = self.relu(x)x = self.pool(x)   # [batch, 32, 8, 8]x = self.conv3(x)  # [batch, 64, 8, 8]x = self.relu(x)x = x.view(-1, 64 * 8 * 8)  # 展平x = self.fc1(x)x = self.relu(x)x = self.fc2(x)return x# 初始化模型、损失函数、优化器
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = SimpleCNNWithDilation().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 训练函数
def train(epoch):model.train()running_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = data[0].to(device), data[1].to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if i % 100 == 99:  # 每100个batch打印一次print(f'Epoch: {epoch + 1}, Batch: {i + 1}, Loss: {running_loss / 100:.3f}')running_loss = 0.0# 测试函数
def test():model.eval()correct = 0total = 0with torch.no_grad():for data in testloader:images, labels = data[0].to(device), data[1].to(device)outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Accuracy on test set: {100 * correct / total:.2f}%')# 训练&测试流程
for epoch in range(5):  # 简单跑5个epoch示例train(epoch)test()
Files already downloaded and verified
Files already downloaded and verified
Epoch: 1, Batch: 100, Loss: 1.816
Epoch: 1, Batch: 200, Loss: 1.501
Epoch: 1, Batch: 300, Loss: 1.385
Accuracy on test set: 55.62%
Epoch: 2, Batch: 100, Loss: 1.210
Epoch: 2, Batch: 200, Loss: 1.182
Epoch: 2, Batch: 300, Loss: 1.115
Accuracy on test set: 60.03%
Epoch: 3, Batch: 100, Loss: 1.013
Epoch: 3, Batch: 200, Loss: 0.991
Epoch: 3, Batch: 300, Loss: 0.976
Accuracy on test set: 65.74%
Epoch: 4, Batch: 100, Loss: 0.877
Epoch: 4, Batch: 200, Loss: 0.877
Epoch: 4, Batch: 300, Loss: 0.856
Accuracy on test set: 68.51%
Epoch: 5, Batch: 100, Loss: 0.765
Epoch: 5, Batch: 200, Loss: 0.767
Epoch: 5, Batch: 300, Loss: 0.754
Accuracy on test set: 69.82%

局部替换成空洞卷积,在不显著增加计算量的情况下,增强模型对长距离特征的捕捉能力,尤其适合想在小数据集(CIFAR-10)里尝试扩大感受野的场景。

可以尝试在不同层设置不同dilation(比如dilation=[1,2,1] ),让模型从多个感受野维度提取特征。

所以其实对于这些模块和类的参数本身能力的理解,才能帮助你更好的搭积木,而不是单纯的无脑的试,未来你做什么任务就积累这方面的能力即可。

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

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

相关文章

LeetCode第3304题 - 找出第 K 个字符 I

题目 解答 class Solution {public char kthCharacter(int k) {int n 0;int v 1;while (v < k) {v << 1;n;}String target kthCharacterString(n);return target.charAt(k - 1);}public String kthCharacterString(int n) {if (n 0) {return "a";}Str…

Codeforces Round 1043 (Div. 3) D-F 题解

D. From 1 to Infinity 题意 有一个无限长的序列&#xff0c;是把所有正整数按次序拼接&#xff1a;123456789101112131415...\texttt{123456789101112131415...}123456789101112131415...。求这个序列前 k(k≤1015)k(k\le 10^{15})k(k≤1015) 位的数位和。 思路 二分出第 …

【C语言16天强化训练】从基础入门到进阶:Day 7

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C基础知识知识强化补充、C/C干货分享&学习过程记录 &#x1f349;学习方向&#xff1a;C/C方向学习者…

【AI基础:神经网络】16、神经网络的生理学根基:从人脑结构到AI架构,揭秘道法自然的智能密码

“道法自然,久藏玄冥”——人工神经网络(ANN)的崛起并非偶然,而是对自然界最精妙的智能系统——人脑——的深度模仿与抽象。从单个神经元的信号处理到大脑皮层的层级组织,从突触可塑性的学习机制到全脑并行计算的高效能效,生物大脑的“玄冥”智慧为AI提供了源源不断的灵感…

容器安全实践(一):概念篇 - 从“想当然”到“真相”

在容器化技术日益普及的今天&#xff0c;许多开发者和运维人员都将应用部署在 Docker 或 Kubernetes 中。然而&#xff0c;一个普遍存在的误解是&#xff1a;“容器是完全隔离的&#xff0c;所以它是安全的。” 如果你也有同样的想法&#xff0c;那么你需要重新审视容器安全了。…

腾讯开源WeKnora:新一代文档理解与检索框架

引言&#xff1a;文档智能处理的新范式 在数字化时代&#xff0c;企业和个人每天都面临着海量文档的处理需求&#xff0c;从产品手册到学术论文&#xff0c;从合同条款到医疗报告&#xff0c;非结构化文档的高效处理一直是技术痛点。2025年8月&#xff0c;腾讯正式开源了基于大…

C++之list类的代码及其逻辑详解 (中)

接下来我会依照前面所说的一些接口以及list的结构来进行讲解。1. list_node的结构1.1 list_node结构体list由于其结构为双向循环链表&#xff0c;所以我们在这里要这么初始化_next&#xff1a;指向链表中下一个节点的指针_prev&#xff1a;指向链表中上一个节点的指针_val&…

新能源汽车热管理仿真:蒙特卡洛助力神经网络训练

研究背景在新能源汽车的热管理仿真研究中&#xff0c;神经网络训练技术常被应用于系统降阶建模。通过这一方法&#xff0c;可以构建出高效准确的代理模型&#xff0c;进而用于控制策略的优化、系统性能的预测与评估&#xff0c;以及实时仿真等任务&#xff0c;有效提升开发效率…

第十九讲:C++11第一部分

目录 1、C11简介 2、列表初始化 2.1、{}初始化 2.2、initializer_list 2.2.1、成员函数 2.2.2、应用 3、变量类型推导 3.1、auto 3.2、decltype 3.3、nullptr 4、范围for 5、智能指针 6、STL的一些变化 7、右值引用和移动语义 7.1、右值引用 7.2、右值与左值引…

书写本体论视域下的文字学理论重构

在符号学与哲学的交叉领域&#xff0c;文字学&#xff08;Grammatologie&#xff09;作为一门颠覆性学科始终处于理论风暴的中心。自德里达1967年发表《论文字学》以来&#xff0c;传统语言学中"语音中心主义"的霸权地位遭遇根本性动摇&#xff0c;文字不再被视为语言…

为什么要做架构设计?架构设计包含哪些内容?

大家好,我是IT孟德,You can call me Aman(阿瞒,阿弥陀佛的ē,Not阿门的ā),一个喜欢所有对象(热爱技术)的男人。我正在创作架构专栏,秉承ITer开源精神分享给志同道合(爱江山爱技术更爱美人)的朋友。专栏更新不求速度但求质量(曹大诗人传世作品必属精品,请脑补一下《…

Vue2封装Axios

一、介绍Axios 是一个基于 promise 的 HTTP 库&#xff0c;简单的讲就是可以发送get、post等请求。二、安装npm install axios --save二、axios不同请求方式axios(config)这是 Axios 的核心方法&#xff0c;用于发送自定义配置的 HTTP 请求。通过传入一个包含请求配置的对象&am…

DataAnalytics之Tool:Metabase的简介、安装和使用方法、案例应用之详细攻略

DataAnalytics之Tool&#xff1a;Metabase的简介、安装和使用方法、案例应用之详细攻略 目录 Metabase的简介 1、特点 Metabase的安装和使用方法 1、安装 快速设置&#xff1a;开发环境 前端快速设置 后端快速设置 2、使用方法 Metabase的案例应用 Metabase的简介 Met…

frp v0.64.0 更新:开源内网穿透工具,最简洁教程

frp是一款跨平台的内网穿透工具&#xff0c;支持 Windows、macOS 与 Linux&#xff0c;它需要你有一台拥有固定公网 IP 的电脑&#xff0c;VPS 最好&#xff0c;然后就能愉快的进行内网穿透了。还支持 https&#xff0c;甚至可以用它进行小程序开发。Appinn v0.64.0 新增token…

【数据结构】B+ 树——高度近似于菌丝网络——详细解说与其 C 代码实现

文章目录B 树的定义B 树组织数据的方法往 B 树中插入键值对数据从 B 树中删除键值对把 B 树看作是 “真菌网络”——我理解并记忆 B 树的方法B 树的 C 代码实现初始化节点、B 树B 树节点内的二分查找B 树的数据插入操作B 树的删除数据操作范围查询与全局遍历销毁 B 树测试代码&…

01、数据结构与算法--顺序表

正式进入数据结构的学习&#xff0c;先从预备知识学起&#xff0c;戒焦戒躁戒焦戒躁...一、泛型的引入1、为什么需要泛型&#xff1f;先来看一个题目&#xff1a;实现一个类&#xff0c;类中包含一个数组成员&#xff0c;使得数组中可以存放任何类型的数据&#xff0c;也可以根…

8.23打卡 DAY 50 预训练模型+CBAM模块

DAY 50: 预训练模型与 CBAM 模块的融合与微调 今天&#xff0c;我们将把之前学到的知识融会贯通&#xff0c;探讨如何将 CBAM 这样的注意力模块应用到强大的预训练模型&#xff08;如 ResNet&#xff09;中&#xff0c;并学习如何高效地对这些模型进行微调&#xff0c;以适应我…

北极圈边缘生态研究:从数据采集到分析的全流程解析

原文链接&#xff1a;https://onlinelibrary.wiley.com/doi/10.1111/1744-7917.70142?afR北极圈边缘生态研究&#xff1a;从数据采集到分析的全流程解析简介本教程基于一项在俄罗斯摩尔曼斯克州基洛夫斯克市开展的长期生态学研究&#xff0c;系统讲解如何对高纬度地区特定昆虫…

Excel处理控件Aspose.Cells教程:使用Python将 Excel 转换为 NumPy

使用 Python 处理 Excel 数据非常常见。这通常涉及将数据从 Excel 转换为可高效操作的形式。将 Excel 数据转换为可分析的格式可能非常棘手。在本篇教程中&#xff0c;您将学习借助强大Excel处理控件Aspose.Cells for Python&#xff0c;如何仅用几行代码将 Excel 转换为 NumPy…

python 字典有序性的实现和OrderedDict

文章目录 一、Python 3.7+ 字典有序性的验证 二、如何在字典头部插入键值对 方法 1:创建新字典(推荐) 方法 2:使用 `collections.OrderedDict`(适合频繁头部插入场景) 方法 3:转换为列表操作(不推荐,效率低) 底层核心结构:双数组哈希表 有序性的实现原理 与旧版本(…