【深度学习】(2+1)D模型框架结构笔记

2023-05-16

(2+1)D 模型框架结构笔记

    • SpatioTemporalConv模块结构
    • SpatioTemporalResBlock模块结构
    • SpatioTemporalResLayer模块结构
    • 2Plus1DNet

SpatioTemporalConv模块结构

SpatioTemporalConv的输入参数:(in_channels,out_channels,kernel_size,stride=1,padding=0, bias=False,first_conv=False)

Args:
in_channels (int): Number of channels in the input tensor,输入张量中的通道数

out_channels (int): Number of channels produced by the convolution,卷积提供的通道数

kernel_size (int or tuple): Size of the convolving kernel,卷积核大小

stride (int or tuple, optional): Stride of the convolution. Default: 1,卷积的步长。 默认值:1

padding (int or tuple, optional): Zero-padding added to the sides of the input during their respective convolutions. Default: 0,在它们各自的卷积期间将零填充添加到输入的边。 默认值:0

bias (bool, optional): If True, adds a learnable bias to the output. Default: True,

Created with Raphaël 2.2.0 inputs Spatial_conv:Conv3d(in_channels,intermed_channels, spatial_kernel_size,spatial_stride,sptial_padding,bias) BatchNorm3d Relu Temporal_conv:Conv3d(intermed_channels,out_channels, temporal_kernel_size,temporal_stride,temporal_padding,bias) BatchNorm3d Relu outputs

在代码中,当first_conv=True时intermed_channels=45,否则intermed_channels=(kernel_size[0] * kernel_size[1] * kernel_size[2] * in_channels * out_channels)/(kernel_size[1] * kernel_size[2] * in_channels+kernel_size[0] * out_channels)。

其中intermed_channels出自论文中的计算
在这里插入图片描述
也就是(3D卷积核x输入通道数x输出通道数)/(空间卷积核x输入通道数 + 时间卷积核x输出通道数)。

temporal_kernel_size=(3,1,1),spatial_padding=(1,0,0)在3D中的Conv3d卷积核尺寸为txtxt,而(2+1)D将其变为先进行卷积核为1xtxt的Spatial_conv,然后再进行tx1x1的Temporal_conv。

spatial_kernel_size=(1,kernel_size[1],kernel_size[2])
spatial_stride=(1,stride[1],stride[2])
spatial_padding=(0,padding[1],padding[2])

temporal_kernel_size=(kernel_size[0],1,1)
temporal_stride=(stride[0],1,1)
temporal_padding=(padding[0],0,0)

实现代码如下:

class SpatioTemporalConv(nn.Module):
    r"""通过在空间轴和时间轴上执行2D卷积到中间子空间,然后在时间轴上执行1D卷积以产生最终输出
    Args:
        in_channels (int): Number of channels in the input tensor,输入张量中的通道数
        out_channels (int): Number of channels produced by the convolution,卷积提供的通道数
        kernel_size (int or tuple): Size of the convolving kernel
        stride (int or tuple, optional): Stride of the convolution. Default: 1,卷积的步伐。 默认值:1
        padding (int or tuple, optional): Zero-padding added to the sides of the input during their respective convolutions. Default: 0,
        在它们各自的卷积期间将零填充添加到输入的边。 默认值:0
        bias (bool, optional): If ``True``, adds a learnable bias to the output. Default: ``True``,
        偏见(布尔型,可选):如果为``True'',则向输出添加可学习的偏见。 默认值:``True``
    """

    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, bias=False, first_conv=False):
        super(SpatioTemporalConv, self).__init__()

        # if ints are entered, convert them to iterables, 1 -> [1, 1, 1]
        kernel_size = _triple(kernel_size)
        stride = _triple(stride)
        padding = _triple(padding)

        if first_conv: # 首层设置
            
            spatial_kernel_size = kernel_size #(1,7,7)
            spatial_stride = (1, stride[1], stride[2]) #(1,2,2)
            spatial_padding = padding #(0,3,3)

            temporal_kernel_size = (3, 1, 1)
            temporal_stride = (stride[0], 1, 1) #(1,1,1)
            temporal_padding = (1, 0, 0)

            # from the official code, first conv's intermed_channels = 45
            intermed_channels = 45

            # 空间卷积等价于2D卷积, followed by batch_norm and ReLU
            self.spatial_conv = nn.Conv3d(in_channels, intermed_channels, spatial_kernel_size,
                                          stride=spatial_stride, padding=spatial_padding, bias=bias)
            self.bn1 = nn.BatchNorm3d(intermed_channels)
			# 时间卷积等效于1D卷积,
            
            self.temporal_conv = nn.Conv3d(intermed_channels, out_channels, temporal_kernel_size,
                                           stride=temporal_stride, padding=temporal_padding, bias=bias)
            self.bn2 = nn.BatchNorm3d(out_channels)
            self.relu = nn.ReLU()
        else:
            # decomposing the parameters into spatial and temporal components by
            # masking out the values with the defaults on the axis that
            # won't be convolved over. This is necessary to avoid unintentional
            # behavior such as padding being added twice
            spatial_kernel_size =  (1, kernel_size[1], kernel_size[2]) # 一般为(1,3,3)
            spatial_stride =  (1, stride[1], stride[2]) # stride = 2时下采样
            spatial_padding =  (0, padding[1], padding[2]) # 

            temporal_kernel_size = (kernel_size[0], 1, 1)
            temporal_stride = (stride[0], 1, 1)
            temporal_padding = (padding[0], 0, 0)

            # 公式计算中间通道数
            # from the paper section 3.5
            intermed_channels = int(math.floor((kernel_size[0] * kernel_size[1] * kernel_size[2] * in_channels * out_channels)/ \
                                (kernel_size[1] * kernel_size[2] * in_channels + kernel_size[0] * out_channels)))

            # the spatial conv is effectively a 2D conv due to the
            # spatial_kernel_size, followed by batch_norm and ReLU
            self.spatial_conv = nn.Conv3d(in_channels, intermed_channels, spatial_kernel_size,
                                        stride=spatial_stride, padding=spatial_padding, bias=bias)
            self.bn1 = nn.BatchNorm3d(intermed_channels)

            # the temporal conv is effectively a 1D conv, but has batch norm
            # and ReLU added inside the model constructor, not here. This is an
            # intentional design choice, to allow this module to externally act
            # identical to a standard Conv3D, so it can be reused easily in any
            # other codebase
            self.temporal_conv = nn.Conv3d(intermed_channels, out_channels, temporal_kernel_size,
                                        stride=temporal_stride, padding=temporal_padding, bias=bias)
            self.bn2 = nn.BatchNorm3d(out_channels)
            self.relu = nn.ReLU()



    def forward(self, x):
        x = self.relu(self.bn1(self.spatial_conv(x)))
        x = self.relu(self.bn2(self.temporal_conv(x)))
        return x

SpatioTemporalResBlock模块结构

该模型为残差网络结构
SpatioTemporalResBlock的输入参数:(in_channels,out_channels,kernel_size,stride=1,downsample=False)

padding=kernel_size//2

downsample=True时,将对输入的Tensor进行下采样,输入的Tensor为(N,C,D,X,Y),输出的Tensor为(N,out_channels,D/2,X/2,Y/2),此时的模型结构图如下:
在这里插入图片描述
downsample=False时,对输入的Tensor不进行下采样,输入和输出的Tensor的shape一样,此时的模型结构图如下:
在这里插入图片描述
在这里插入图片描述
实现代码如下:

class SpatioTemporalResBlock(nn.Module):
    r"""Single block for the ResNet network. Uses SpatioTemporalConv in
        the standard ResNet block layout (conv->batchnorm->ReLU->conv->batchnorm->sum->ReLU)
        ResNet网络的单个块。 在标准ResNet块布局中使用SpatioTemporalConv

        Args:
            in_channels (int): Number of channels in the input tensor.
            out_channels (int): Number of channels in the output produced by the block.
            kernel_size (int or tuple): Size of the convolving kernels.
            downsample (bool, optional): If ``True``, the output size is to be smaller than the input. Default: ``False``
        """

    def __init__(self, in_channels, out_channels, kernel_size, downsample=False):
        super(SpatioTemporalResBlock, self).__init__()

        # If downsample == True, the first conv of the layer has stride = 2
        # to halve the residual output size, and the input x is passed
        # through a seperate 1x1x1 conv with stride = 2 to also halve it.

        # no pooling layers are used inside ResNet
        self.downsample = downsample

        # to allow for SAME padding
        padding = kernel_size // 2

        if self.downsample:# 下采样为true,对输入层也得进行图片的长宽压缩
		
            # 下采样输入x,残差的右侧分支部分
            self.downsampleconv = SpatioTemporalConv(in_channels, out_channels, 1, stride=2) #卷积核1x1x1,直接对输入进行下采样
            self.downsamplebn = nn.BatchNorm3d(out_channels) #  接bn3d

            # 下采样的主线部分,一次conv包括 空间卷积加时间卷积
            self.conv1 = SpatioTemporalConv(in_channels, out_channels, kernel_size, padding=padding, stride=2)
        
		else:# 不进行下采样的话 ,右侧分支直接相加就行了
            self.conv1 = SpatioTemporalConv(in_channels, out_channels, kernel_size, padding=padding)

        self.bn1 = nn.BatchNorm3d(out_channels)
        self.relu = nn.ReLU()

        # 再进行一次标准的卷积 + bn3d + relu
        self.conv2 = SpatioTemporalConv(out_channels, out_channels, kernel_size, padding=padding)
        self.bn2 = nn.BatchNorm3d(out_channels)

    def forward(self, x):
        res = self.relu(self.bn1(self.conv1(x)))
        res = self.bn2(self.conv2(res))

        if self.downsample:
            x = self.downsamplebn(self.downsampleconv(x))

        return self.relu(x + res)

SpatioTemporalResLayer模块结构

SpatioTemporalResLayer的输入参数:(in_channels,out_channels,kernel_size,layer_size,
block_type=SpatioTemporalResBlock,downsample=False)
在这里插入图片描述
代码为:

class SpatioTemporalResLayer(nn.Module):
    """
    形成ResNet网络的单层,并重复多次输出大小相同的块彼此堆叠

        Args:
            in_channels (int): Number of channels in the input tensor.
            out_channels (int): Number of channels in the output produced by the layer.
            kernel_size (int or tuple): Size of the convolving kernels.
            layer_size (int): Number of blocks to be stacked to form the layer
            block_type (Module, optional): Type of block that is to be used to form the layer. Default: SpatioTemporalResBlock.
            downsample (bool, optional): If ``True``, the first block in layer will implement downsampling. Default: ``False``
        """

    def __init__(self, in_channels, out_channels, kernel_size, layer_size, block_type=SpatioTemporalResBlock,
                 downsample=False):

        super(SpatioTemporalResLayer, self).__init__()

        # 首层,采用SpatioTemporalResBlock的 有下采样的结构。
        self.block1 = block_type(in_channels, out_channels, kernel_size, downsample)

        # 接下来重复进行layer_size - 1次不进行下采样的结构,依次堆叠;
		# layer_size为2时,即再进行1次不进行下采样的SpatioTemporalResBlock结构
        self.blocks = nn.ModuleList([])
        for i in range(layer_size - 1):
            # 所有这些块都是相同的,并且默认情况下downsample = False
            self.blocks += [block_type(out_channels, out_channels, kernel_size)]

    def forward(self, x):
        x = self.block1(x)
        for block in self.blocks:
            x = block(x)

        return x

2Plus1DNet

class R2Plus1DNet(nn.Module):
    r"""Forms the overall ResNet feature extractor by initializng 5 layers, with the number of blocks in
    each layer set by layer_sizes, and by performing a global average pool at the end producing a
    512-dimensional vector for each element in the batch.
    通过初始化5层,并通过layer_sizes设置每层中的块数,并最后通过执行全局平均池来为批次中的每个元素生成512维向量,来形成整个ResNet特征提取器。

        Args:
            layer_sizes (tuple): An iterable containing the number of blocks in each layer
            block_type (Module, optional): Type of block that is to be used to form the layers. Default: SpatioTemporalResBlock.
    """

    def __init__(self, layer_sizes, block_type=SpatioTemporalResBlock):
        super(R2Plus1DNet, self).__init__()

        
		# 第一层,输入通道为3,卷积核大小(177), stride=(1,2,2)在三维方向上步长是1,在宽和高上步长是2进行下采样,
		# padding为(0, 3, 3),宽高padding为 7/2=3
        self.conv1 = SpatioTemporalConv(3, 64, (1, 7, 7), stride=(1, 2, 2), padding=(0, 3, 3), first_conv=True)
		
        
		# 第二层输出和第一层输出大小相同,不进行下采样通道数也不变,卷积核大小为3x3x3
        self.conv2 = SpatioTemporalResLayer(64, 64, 3, layer_sizes[0], block_type=block_type)
       
		# 最后三层的输出通道数二倍于输入通道数,而且进行下采样,在每一层的第一个block进行下采样
        self.conv3 = SpatioTemporalResLayer(64, 128, 3, layer_sizes[1], block_type=block_type, downsample=True)
        self.conv4 = SpatioTemporalResLayer(128, 256, 3, layer_sizes[2], block_type=block_type, downsample=True)
        self.conv5 = SpatioTemporalResLayer(256, 512, 3, layer_sizes[3], block_type=block_type, downsample=True)

        # global average pooling of the output
        self.pool = nn.AdaptiveAvgPool3d(1)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = self.conv5(x)

        x = self.pool(x)

        return x.view(-1, 512)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【深度学习】(2+1)D模型框架结构笔记 的相关文章

  • MySql - 重置root密码(版本5.7.21)

    Mysql 版本 xff1a 5 7 21 网上能搜到的文章还挺多的 xff0c 最常见的是这个 xff1a 1 修改 my ini xff0c 在 mysqld 下增加一行 xff1a skip grant tables 2 重启 mys
  • Linux - 文件复制后大小不一致的问题

    问题 xff1a 通过cp或者rsync传输文件后 xff0c 通过du s查看到的体积 xff0c 前后不一致 原因 xff1a https stackoverflow com questions 10364999 file size c
  • 基于nand flash的文件系统的整理

    一 Nandflash简介 基本概念 xff1a flash芯片 block page 附加页 1 1结构 Flash芯片的擦除以块为单位 xff0c 写以页为单位 在每个flash芯片中包括非常多的块 xff0c 同款芯片上每个块的大小相
  • 卡普的21个NP完全问题-问题描述

    以下部分为卡普21个问题的名称 xff08 来自于维基百科https zh wikipedia org wiki E5 8D A1 E6 99 AE E7 9A 84 E4 BA 8C E5 8D 81 E4 B8 80 E5 80 8BN
  • 在终端使用命令卸载交叉编译工具

    ubuntu中可以使用命令行 sudo apt install gcc arm linux gnueabi 自动安装交叉编译工具 xff0c 但是往往软件版本太过超前了 xff0c 交叉编译时候使用的命令是 arm linux gnueab
  • ubuntu系统下降低风扇转速的方式

    我的本自从装了ubuntu之后风扇就呼呼的响个不停 xff0c 看了很多教程都是说强制降低风扇转速的方式 偶然看到了转速过快的原因是因为显卡与系统自带的驱动不兼容的问题 我的显卡是nvidia xff0c 安装显卡驱动步骤如下 xff1a

随机推荐

  • 怎样向visual studio加入vim的强大编辑能力,让装逼防不胜防!

    经常使用vim的小伙伴知道它的强大 私认为它最大的优势就是解放了你的右手 让鼠标成为了累赘 但是其学习曲线是相当陡峭的 虽然经常使用linux系统 但是偶尔还是会迫于形势缓缓胃口的 在使用VS的时候经常不自觉的就来一串ESC shift 冒
  • JGROUPS

    package com example jgroupsdemo import jakarta annotation PostConstruct import lombok extern slf4j Slf4j import org jgro
  • android studio仿真时遇到VT-x is disabled in BIOS解决办法

    在使用android studio run app时候遇到了 xff1a Intel HAXM is required to run this AVD VT x is disabled in BIOS 的错误提示 xff0c 导致无法进行仿
  • linux系统中resolv.conf文件详解

    etc resolv conf 它是DNS客户机配置文件 xff0c 用于设置DNS服务器的IP地址及DNS域名 xff0c 还包含了主机的域名搜索顺序 该文件是由域名解析器 xff08 resolver xff0c 一个根据主机名解析IP
  • yii2.0 basic版使用CRUD生成器的时候提示错误及页面显示错误

    在使用model生成器的时候不用加命名空间 xff0c 写好表名就可以直接生成了 但是在用CRUD的时候填写完controllers和model class之后点击生成会弹出错误提示 xff1a Class 39 TelBook 39 sp
  • linux日志对应内容

    var log messages 包括整体系统信息 xff0c 其中也包含系统启动期间的日志 此外 xff0c mail xff0c cron xff0c daemon xff0c kern和auth等内容也记录在var log messa
  • 常用证书操作函数

    现有的证书大都采用X 509规范 xff0c 主要同以下信息组成 xff1a 版本号 证书序列号 有效期 拥有者信息 颁发者信息 其他扩展信息 拥有者的公钥 CA对以上信息的签名 OpenSSL实现了对X 509数字证书的所有操作 包括签发
  • MongoDB 匹配查询和比较操作符

    一 匹配查询 1 查询所有 span class token operator gt span db accounts find span class token punctuation span span class token punc
  • 我的2014——典型程序员的一年,不想再重来

    兴冲冲地拿起 xff0c 信誓旦旦的搁在一边 xff0c 以为很快就会回来 xff0c 却一晃而过 xff0c 不再回来 xff1b 我不想再重复过去 xff0c 决定去做 xff0c 写下来 题记 已经记不起我2014的年初是否有过规划
  • 我的2016——程序员年到三十,工作第四年

    看到CSDN 我的2016 主题征文活动 已经是1月6号 xff0c 而截止时间是1月8号 xff0c 对比去年的总结是在闲等活动开始 xff0c 今年在时间上真的是天差地别 但是 xff0c 一年到头 xff0c 还是需要花些时间来回顾这
  • mac下 ndk_build: command not found

    参考 http blog csdn net greenbird811 article details 7543305 在mac下调用ndk build c代码文件提示错误 fix 1 启动终端Terminal 2 进入当前用户的home目录
  • 公司分配IP地址,求主机号码的最小值和最大值。

    问题描述如下 xff1a 姐 xff1a 注意减去2的实际意义 xff1a 网络地址后的第一个主机地址是本网段的网络地址192 168 0 0 xff0c 最 后一个主机地址是本网段的广播地址192 168 255 255
  • Erlang入门

    64 author sunxu 64 copyright C 2023 lt COMPANY gt 64 doc 64 end Created 16 2月 2023 22 16 module test author 34 sunxu 34
  • IPv4地址、IPv6地址和Mac地址的位数

    xff08 1 xff09 IPv4的地址是32位 xff0c 用点分十进制表示 xff0c 每八位划分 xff0c 也就是四个0 255的十进制数 xff0c 这是很常见的 xff08 2 xff09 IPv6的地址是128位 xff0c
  • 用C#连接数据库的方法

    连接SQL Server数据库的方法 xff1a 1 在程序中引用System Data SqlClient命名空间 2 编写连接字符串 xff0c 格式为 xff1a Data Source 61 服务器名称 Initial Catalo
  • gcc 不支持 //注释的解决

    这段时间用slickedit写代码 xff08 windows平台下 xff0c 装了Cygwin xff09 xff0c 编译器用的gcc xff0c 但是有个问题就是用 34 34 写注释的时候 xff0c 编译的时候有错 xff1a
  • python实现按照文件名称进行文件分类

    问题 xff1a 大量名称中带有数字的图片 视频 xff0c 根据名称中数字按照一定的等差数列来排序 xff0c 并且放入指定对应的文件夹中 span class token keyword import span os span clas
  • 【深度学习】Yolov3详解笔记及Pytorch代码

    Yolov3详解笔记及Pytorch代码 预测部分网络结构backbone xff1a Darknet 53output预测结果的解码 训练部分计算loss所需参数pred是什么target是什么loss的计算过程 预测部分 网络结构 DB
  • 【深度学习】各种卷积的理解笔记(2D,3D,1x1,可分离卷积)

    卷积 1 2D卷积单通道版本多通道版本 2 3D卷积3 1x1卷积作用应用 4 卷积算法5 可分离卷积空间可分离卷积深度可分离卷积 1 2D卷积 卷积的目的是从输入中提取有用的特征 在图像处理中 xff0c 卷积可以选择多种不同的滤波器 每
  • 【深度学习】(2+1)D模型框架结构笔记

    xff08 2 43 1 xff09 D 模型框架结构笔记 SpatioTemporalConv模块结构SpatioTemporalResBlock模块结构SpatioTemporalResLayer模块结构2Plus1DNet Spati