深入解析:Inception V3--J9

news/2025/10/29 21:38:08/文章来源:https://www.cnblogs.com/gccbuaa/p/19175461

网络结构1--InceptionA

InceptionA中网络结构主要分为四块,分别是1*1的卷积块,5*5的卷积块以及双3*3的卷积块和池化层。首先,特征经过1*1的卷积块进行1*1的特征提取,保证小尺度的特征能够被提取,然后进入5*5的卷积块,在5*5的卷积块中先进行1*1的卷积降维,使得通道数缩减,降低计算量,然后进行5*5的大尺度特征提取,之后进入双3*3的卷积块,在该卷积块中,首先会进入1*1的卷积块进行降维,然后通过第一层3*3的卷积块,在提取特征的同时,进行维度提升,之后进入第二层的3*3模块,进行特征提取,实现中尺度的特征提取,最后进入池化块,进行特征增强,这便是整体的InceptionA模块。

统筹来看,InceotionA模块实现的整体功能便是进行1*1,3*3,5*5和池化层的特征提取, 然后将提取的特征合并,作为最后的总特征。

# V3版本
class InceptionA(nn.Module):def __init__(self,in_channels,pool_features):# 输入特征图的通道数  池化分支的输出通道数super(InceptionA,self).__init__()#小特征卷积,转换通道self.branch1x1=BasicConv2d(in_channels,64,kernel_size=1)#中尺度特征提取,先1*1降维,然后5*5卷积,self.branch5x5_1=BasicConv2d(in_channels,48,kernel_size=1)self.branch5x5_2=BasicConv2d(48,64,kernel_size=5,padding=2)#双3*3卷积self.branch3x3dbl_1=BasicConv2d(in_channels,64,kernel_size=1)self.branch3x3dbl_2=BasicConv2d(64,96,kernel_size=3,padding=1)self.branch3x3dbl_3=BasicConv2d(96,96,kernel_size=3,padding=1)# 平均池化self.branch_pool=BasicConv2d(in_channels,pool_features,kernel_size=1)def forward(self,x):# 先1*1的卷积branch1x1=self.branch1x1(x)# 在大尺度特征提取,降维然后卷积branch5x5=self.branch5x5_1(x)branchx5x5=self.branch5x5_2(branchx5x5)# 双3*3的卷积网络branch3x3dbl=self.branch3x3dbl_1(x)branch3x3dbl=self.branch3x3dbl_2(branch3x3dbl)branch3x3dbl=self.branch3x3dbl_3(branch3x3dbl)#池化层branch_pool=F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)branch_pool=self.branch_pool(branch_pool)# 最后特征合并outputs=[branch1x1,branch5x5,branch3x3dbl,branch_pool]return torch.cat(outputs,1)

网络结构2--InceptionB

InceptionB的网络结构与InceptionA类似,不过不同的是InceptionB采用的四层是1*1的卷积层,两个分别是1*7和7*1的卷积层,四个7*7分解的卷积层,还有最后一层池化层。其中这六层7*7卷积层不同点在于,分别采用的是1*7和7*1的卷积核,与普通7*7的卷积核不同,这样的改变不仅能够实现7*7的提取效果,同时还能够实现计算量的降低,提升计算速度。而为什么不将全部的卷积核都修改为这种拆分的情况呢,原因在于,这种1*7和7*1的卷积核提取的特征是由方向性的,而7*7提取的效果是全局性的,在某些应用场景下1*7和7*1的效果确实会优于7*7的卷积核同时也能大大提高计算速度,但显示他的使用场景是存在限制的,故而不能全部使用。

class InceptionB(nn.Module):def __init__(self,in_channels,channels_7x7):super(InceptionB,self).__init__()# 使用1*1的卷积self.branch1x1=BasicConv2d(in_channels,192,kernel_size=1)# 中等尺度卷积 --使用1*7和7*1的卷积核代替7*7的卷积核,降低计算量c7=channels_7x7self.branch7x7_1=BasicConv2d(in_channels,c7,kernel_size=1)self.branch7x7_2=BasicConv2d(c7,c7,kernel_size=(1,7),padding=(0,3))self.branch7x7_3=BasicConv2d(c7,192,kernel_size=(7,1),padding=(3,0))# 多次7*7的分解卷积分支self.branch7x7dbl_1=BasicConv2d(in_channels,c7,kernel_size=1)self.branch7x7dbl_2=BasicConv2d(c7,c7,kernel_size=(7,1),padding=(3,0))self.branch7x7dbl_3=BasicConv2d(c7,c7,kernel_size=(1,7),padding=(0,3))self.branch7x7dbl_4=BasicConv2d(c7,c7,kernel_size=(7,1),padding=(3,0))self.branch7x7dbl_5=BasicConv2d(c7,192,kernel_size=(1,7),padding=(0,3))# 平均池化,输入-192self.branch_pool=BasicConv2d(in_channels,192,kernel_size=1)def forward(self,x):branch1x1=self.branch1x1(x)branch7x7=self.branch7x7_1(x)branch7x7=self.branch7x7_2(branch7x7)branch7x7=self.branch7x7_3(branch7x7)branch7x7dbl=self.branch7x7dbl_1(x)branch7x7dbl=self.branch7x7dbl_2(branch7x7dbl)branch7x7dbl=self.branch7x7dbl_3(branch7x7dbl)branch7x7dbl=self.branch7x7dbl_4(branch7x7dbl)branch7x7dbl=self.branch7x7dbl_5(branch7x7dbl)branch_pool=F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)branch_pool=self.branch_pool(branch_pool)# 将卷积后的特征进行合并 1*1卷积 ,7*7卷积 多次7*7卷积 池化层 四层的卷积特征合并outputs=[branch1x1,branch7x7,branch7x7dbl,branch_pool]return torch.cat(outputs,1)

网络结构3--InceptionC

InceptionC与A,B类似,同样有四个模块,分别是第一层1*1卷积块,第二层3*3分解卷积块,第三层双3*3卷积块,以及第四层池化层。其中第二层3*3分解块是通过1*3和3*1共同实现的。在第三层中既有3*3的全局卷积池化层,又有分解的3*3卷积层,整体网络侧重点在于对于3*3模块的中尺度卷积。

class InceptionC(nn.Module):def __init__(self,in_channels):super(InceptionC,self).__init__()# 1*1的卷积分支self.branch1x1=BasicConv2d(in_channels,320,kernel_size=1)#3*3的卷积分支self.branch3x3_1=BasicConv2d(in_channels,384,kernel_size=1)self.branch3x3_2a=BasicConv2d(384,384,kernel_size=(1,3),padding=(0,1))self.branch3x3_2b=BasicConv2d(384,384,kernel_size=(3,1),padding=(1,0))# 双3*3的分支,第一个3*3,第二个1*3+3*1self.branch3x3dbl_1=BasicConv2d(in_channels,448,kernel_size=1)self.branch3x3dbl_2=BasicConv2d(448,384,kernel_size=3,padding=1)self.branch3x3dbl_3a=BasicConv2d(384,384,kernel_size=(1,3),padding=(0,1))self.branch3x3dbl_3b=BasicConv2d(384,384,kernel_size=(3,1),padding=(1,0))# 平均池化层self.branch_pool=BasicConv2d(in_channels,192,kernel_size=1)def forward(self,x):branch1x1=self.branch1x1(x)branch3x3=self.branch3x3_1(x)branch3x3=[self.branch3x3_2a(branch3x3),self.branch3x3_2b(branch3x3)]branch3x3=torch.cat(branch3x3,1)branch3x3dbl=torch.cat(branch3x3dbl,1)branch_pool=F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)branch_pool=self.branch_pool(branch_pool)# 合并特征outputs=[branch1x1,branch3x3,branch3x3dbl,branch_pool]return torch.cat(outputs,1)

网络结构4-ReductionA

在ReductionA网络结构中,采用三层网络结构,分别是3*3的卷积层,双3*3的卷积层以及池化层,该网络结构的作用是在增强特征的同时降低参数量,主要目的是降低参数量,从而加快训练速度。

# 降维模块
class ReductionA(nn.Module):def __init__(self,in_channels):# (-1,288,35,35)super(ReductionA,self).__init__()# 直接3*3的卷积下采样, 将通道转换为384通道# (-1,288,35,35)->(-1,384,17,17)self.branch3x3=BasicConv2d(in_channels,384,kernel_size=3,stride=2)#分支2 1*1+3*3+3*3的串联卷积通道# (-1,288,35,35)->(-1,64,35,35)self.branch3x3dbl_1=BasicConv2d(in_channels,64,kernel_size=1) #先换通道# (-1,64,35,35)->(-1,96,35,35)self.branch3x3dbl_2=BasicConv2d(64,96,kernel_size=3,padding=1) #在升维卷积# (-1,96,35,35)->(-1,96,17,17)self.branch3x3dbl_3=BasicConv2d(96,96,kernel_size=3,stride=2)#卷积def forward(self,x):branch3x3=self.branch3x3(x)branch3x3dbl=self.branch3x3dbl_1(x)branch3x3dbl=self.branch3x3dbl_2(branch3x3dbl)branch3x3dbl=self.branch3x3dbl_3(branch3x3dbl)# (-1,288,35,35)->(-1,288,17,17)branch_pool=F.max_pool2d(x,kernel_size=3,stride=2) #最后再最大池化下采样# 合并特征   (-1,384,17,17) (-1,96,17,17) (-1,288,17,17)->(-1,768,17,17)outputs=[branch3x3,branch3x3dbl,branch_pool]return torch.cat(outputs,1)

网络结构5-ReductionB

ReductionB的结构与A类似,不同的是ReductionB中采用的3层网络结构是3*3的卷积,7*7分解和3*3的卷积,最后一层池化层。作用与A类似,同样是在强化特征的的情况下尽可能减少参数量。

class ReductionB(nn.Module):def __init__(self,in_channels):super(ReductionB,self).__init__()# 输入模块 1*1的卷积核+3*3的卷积核下采样self.branch3x3_1=BasicConv2d(in_channels,192,kernel_size=1)self.branch3x3_2=BasicConv2d(192,320,kernel_size=3,stride=2)# 1*1+1*7+7*1+3*3串联下采样self.branch7x7x3_1=BasicConv2d(in_channels,192,kernel_size=1)self.branch7x7x3_2=BasicConv2d(192,192,kernel_size=(1,7),padding=(0,3))self.branch7x7x3_3=BasicConv2d(192,192,kernel_size=(7,1),padding=(3,0))self.branch7x7x3_4=BasicConv2d(192,192,kernel_size=3,stride=2)def forward(self,x):branch3x3=self.branch3x3_1(x)branch3x3=self.branch3x3_2(branch3x3)branch7x7x3=self.branch7x7x3_1(x)branch7x7x3=self.branch7x7x3_2(branch7x7x3)branch7x7x3=self.branch7x7x3_3(branch7x7x3)branch7x7x3=self.branch7x7x3_4(branch7x7x3)branch_pool=F.max_pool2d(x,kernel_size=3,stride=2)# 将三次卷积后的特征合并outputs=[branch3x3,branch7x7x3,branch_pool]return torch.cat(outputs,1)

网络结构6-InceptionAux

InceptionAux为Inception网络的辅助分支,首先利用5*5的池化层进行特征缩减,然后再利用1*1的卷积层使得通道数压缩到128层,之后利用5*5的卷积层进行升维,然后全连接接回去。之所以使用如此通道的变化,是为了避免在网络层数很深的时候出现的梯度爆炸现象。为什么这样会避免梯度爆炸,要解释这一点首先要明确梯度爆炸是怎么来的,梯度爆炸是由于网络层数过大时,参数会被逐渐放大至无穷大产生的梯度爆炸,而该辅助结构改变的是整体网络的路径,使得网络相当于从头再来,自然就会一定程度上避免梯度爆炸现象。

# 辅助分支
class InceptionAux(nn.Module):def __init__(self,in_channels,num_classes):super(InceptionAux,self).__init__()# 将主网络的中间层压缩到128层self.conv0=BasicConv2d(in_channels,128,kernel_size=1)# 5*5的卷积核进行提取self.conv1=BasicConv2d(128,768,kernel_size=5)self.conv1.stddev=0.01 #自定义权重初始化参数标记self.fc=nn.Linear(768,num_classes) #全连接层最终分类self.fc.stddev=0.001  #全连接层的权重使用标准差def forward(self,x):x=F.avg_pool2d(x,kernel_size=5,stride=3)x=self.conv0(x)x=self.conv1(x)x=x.view(x.size(0),-1)x=self.fc(x)return x

整体网络结构:

在网络结构中,首先先利用几层卷积层实现下采样,提取一些基础的特征基础,随着通道数目的加深不断提取特征细节,同时通过这几层降低参数量并且增加网络的非线性拟合能力。然后进入InceptionA,B,C模块,进行细致的特征提取,最后利用全连接层将网络结构映射到类别上,实现分类。

# 整体网络结构
import torch.nn.functional as F
class BasicConv2d(nn.Module):def __init__(self,in_channels,out_channels,kernel_size,stride=1,padding=0):super(BasicConv2d,self).__init__()self.conv=nn.Conv2d(in_channels=in_channels,out_channels=out_channels,kernel_size=kernel_size,stride=stride,padding=padding,dilation=dilation,groups=groups,bias=bias)self.bn=nn.BatchNorm2d(num_features=out_channels)def forward(self,x):x=self.conv(x)x=self.bn(x)x=F.relu(x,inplace=True)return x
class InceptionV3(nn.Module):def __init__(self,num_classes=1000,aux_logits=False,transform_input=False):# 分类类别数目,也就是最后的输出数目 ,是否启用辅助分支,是否对图像预处理super(InceptionV3,self).__init__()self.aux_logits=aux_logitsself.transform_input=transform_input# 浅层卷积,下采样 3->192self.conv2d_1a_33=BasicConv2d(3,32,kernel_size=3,stride=2)self.conv2d_2a_33=BasicConv2d(32,32,kernel_size=3)self.conv2d_2b_33=BasicConv2d(32,64,kernel_size=3,padding=1)self.conv2d_3b_11=BasicConv2d(64,80,kernel_size=1)# (-1,80,147,147)->(-1,192,144,144)self.conv2d_4a_33=BasicConv2d(80,192,kernel_size=3)# InceptionA块,多尺度特征提取,+降维 (-1,192,35,35)->(-1,256,35,35)self.Mixed_5b=InceptionA(192,pool_features=32)# (-1,256,35,35)->(-1,288,35,35)self.Mixed_5c=InceptionA(256,pool_features=64)# (-1,288,35,35)->(-1,288,35,35)self.Mixed_5d=InceptionA(288,pool_features=64)# (-1,288,35,35) 352800 ->(-1,768,17,17)  221952self.Mixed_6a=ReductionA(288)# InceptionB块,实现7*7的卷积提取self.Mixed_6b=InceptionB(768,channels_7x7=128)self.Mixed_6c=InceptionB(768,channels_7x7=160)self.Mixed_6d=InceptionB(768,channels_7x7=160)self.Mixed_6e=InceptionB(768,channels_7x7=192)if  aux_logits:self.AuxLogits=InceptionAux(768,num_classes)#分解加InceptionC块的卷积实现self.Mixed_7a=ReductionB(768)self.Mixed_7b=ReductionC(1280)self.Mixed_7c=ReductionC(2048)self.fc=nn.Linear(2048,num_classes)def forward(self,x):if self.transform_input:x=x.clone()x[:,0]=x[:,0]*(0.229/0.5)+(0.485-0.5)/0.5x[:,1]=x[:,1]*(0.224/0.5)+(0.456-0.5)/0.5x[:,2]=x[:,2]*(0.225/0.5)+(0.406-0.5)/0.5# (-1,3,299,299) ->(-1,32,149,149)x=self.conv2d_1a_33(x)# (-1,32,149,149)->(-1,32,147,147)x=self.conv2d_2a_33(x)# (-1,32,147,147)->(-1,64,147,147)x=self.conv2d_2b_33(x)# (-1,64,147,147)->(-1,64,73,73)x=F.max_pool2d(x,kernel_size=3,stride=2)# (-1,64,73,73)->(-1,80,73,73)x=self.conv2d_3b_11(x)# (-1,80,73,73)->(-1,192,71,71)x=self.conv2d_4a_33(x)# (-1,192,71,71)->(-1,192,35,35)x=F.max_pool2d(x,kernel_size=3,stride=2)# (-1,192,35,35)->()x=self.Mixed_5b(x)x=self.Mixed_5c(x)x=self.Mixed_5d(x)x=self.Mixed_6a(x)x=self.Mixed_6b(x)x=self.Mixed_6c(x)x=self.Mixed_6d(x)x=self.Mixed_6e(x)if self.training and self.aux_logits:aux=self.AuxLogits(x)x=self.Mixed_7a(x)x=self.Mixed_7b(x)x=self.Mixed_7c(x)x=F.avg_pool2d(x,kernel_size=8)x=F.dropout(x,training=self.training)x=x.view(x.size(0),-1)x=self.fc(x)if self.training and self.aux_logits:return x,auxreturn x

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

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

相关文章

ODT 学习笔记

本文同步发表于 博客园。有问题请不吝指出。 ODT (Old Driver Tree)也叫珂朵莉树(Chtholly Tree),也被叫做是颜色段均摊,由某毒瘤巨佬在 CF896C 中引入。 ODT 是一种暴力数据结构,感觉和 dsu on tree、势能线段…

Aout Me!

一个来自广州市,华南师范大学附属中学的高二学生。 一名普通的 OIer。 主要成就:NOI2025 rk29; Codeforces LGM; 命制了一些你可能做过的题目。轻喷 qwq。

解题报告-游戏(game.*)

游戏 题目描述 Alice 和 Bob 两个人正在玩一个游戏,游戏有很多种任务,难度为 \(p\) 的任务( \(p \in N_{+}\) ),有 \(2^{-p}\) 的概率完成并得到 \(2^{p-1}\) 分,如果完成不了,得 \(0\) 分。 一开始每人都是 \(0\…

gccgo如何实现golang运行时向特定interface的动态conversion(及和C++虚函数表的对比)

gccgo如何实现golang运行时向特定interface的动态conversion(及和C++虚函数表的对比)intro 在阅读k8s的源代码时,发现代码中有一个(一组)很简单粗暴的interface转换:将一个interface(storage对象)尝试向各种类型转换。…

技术人的公关利器:专业新闻稿撰写AI指令深度解析

以前我也是这样,每次写新闻稿都像在写一个没有需求文档的项目,各种要素和结构都要自己摸索。直到我尝试用AI提示词工程的思路来解决这个问题。作为程序员,我们习惯用代码解决技术问题,但面对企业公关、产品发布时却…

2025年最新考勤门禁系统推荐与选型攻略

本文将深度对比8款考勤门禁系统:i人事、 北森、柠檬智联、HID Global、真地(Realand)、Honeywell、TimeClock Plus、ACTi。在企业数字化管理的浪潮中,「考勤门禁系统」已成为人力资源与行政管理的关键基础设施。无…

2026 NOI 做题记录(八)

推荐阅读:A、E、J、K、O、R、S、U、W、ADContest Link \(\text{By DaiRuiChen007}\)*A. [AGC071D] Level K Terms (8) Problem Link 我们声称序列合法当且仅当如下两个条件均满足:定义 \(z_i=\begin{cases}i&i&l…

代码审查API

from fastapi import FastAPI, HTTPException, Depends from pydantic import BaseModel, Field from sqlmodel import SQLModel, Field as SQLField, Session, create_engine, select from typing import List, Optio…

elk架构安装部署

一、elk架构概述概述 ELK是一套开源免费且功能强大的日志分析管理系统,由Elasticsearch、Logstash、Kibana三部分组成,简称ELK ELK可以将系统日志、网站日志、应用系统日志等各种日志进行收集、过滤、清洗,然后进行…

冒泡排序 试做版 2025/10/29 21:13

include <stdio.h> int main() { int n,i,k,p; while(scanf("%d",&n)==1) //读入数组个数n { int arr[n]; //创建数组 该数组刚好能容纳n组数据 for(i=0;i<n;i++) //从数组0开始 数组0 数组…

CSP 45^2复赛游记

DAY -300+ 好激动好激动好激动这是肝硬化学了半年的 \(OI\) ,终于迎来了此生以来第一次考吃薯片-J,去的燕大,然后就是成功翘掉一天课好高兴好高兴!带了 \(inf\) 个零食,包括但不限于:蒟蒻果冻(绿色的,好像是青…

工厂用什么考勤系统好?2025最新8款推荐

本文将深度对比8款工厂考勤系统:i人事、 北森、盖雅实时考勤云、TimeClock Plus、全易通考勤系统、ADP Time & Attendance、同鑫考勤系统、When I Work。在制造业与工业企业中,工厂考勤系统早已成为提升管理效率…

深度技术解析低功耗蓝牙厂商nordic的nRF Connect SDK裸机选项方案

自2018年以来,Nordic Semiconductor一直致力于开发基于Zephyr实时操作系统( RTOS)的nRF Connect SDK,并不断发展,提供最佳的工具与软件,助力开发者在Nordic广泛的无线产品组合上构建高度可扩展的物联网应用。然而,…

MPK(Mirage Persistent Kernel)源码笔记(3)--- 系统接口

MPK(Mirage Persistent Kernel)源码笔记(3)--- 系统接口 目录MPK(Mirage Persistent Kernel)源码笔记(3)--- 系统接口0x00 概述0x01 流程0x02 初始化0x03 定义计算图0x04 编译0x05 执行0xFF 参考 0x00 概述 因…

硬件基础知识和典型应用-在休眠项目中RS485电路休眠设计

硬件基础知识和典型应用-在休眠项目中RS485电路休眠设计<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnHardware" frameborder="0" scrolling="a…

20232317 2025-2026-1 《网络与系统攻防技术》实验三实验报告

一、实验内容 (1)正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧。 1.正确使用msf编码器,使用msfvenom生成如jar之类的其他文件 2.veil,加壳工具 3.使用C + shellcode编程 (2)通过组合应用…

用 Gemini + VS Code 打造属于你的 AI 编程神器(完胜 Cursor!)

大家好! 最近很多朋友问我,Cursor + Claude 是不是最强 AI 编程组合? 确实,现在主流的 AI 编程软件中,Cursor 加 Claude Cloud 可以说是“王者中的王炸”。 但问题也很现实——太贵了! 对于刚入门的开发者、小白…

《程序员修炼之道:从小工到专家》观后感第三篇

笔记三:《应对变化——正交性与模块化的灵活设计思维》 核心观点:“正交性”设计能最大化降低代码耦合度,模块化是应对需求变化的“缓冲带”。在业务需求频繁迭代的场景中,正交且模块化的系统能实现“局部修改、全…

profile 与 profile.d 在 Linux 发行版本中的作用 - ENGINEER

profile 与 profile.d 在 Linux 发行版本中的作用​ ​核心概念与作用​​​/etc/profile​:系统范围的登录 Shell 初始化脚本,登录时由 Shell 自动执行,负责设置全局环境变量(如 ​PATH、USER、LOGNAME、HOME、MA…

思维day1

思维day1P6005 [USACO20JAN] Time is Mooney G Bessie 正在安排前往牛尼亚的一次出差,那里有 N(2≤N≤1000)个编号为 1…N 的城市,由 M(1≤M≤2000)条单向的道路连接。Bessie 每次访问城市 i 都可以赚到\(m_{i}\…