网络框架学习之InversionNet

目录

一、文章简介

二、网络简单介绍

2.1 编码器

2.2 解码器 

三、代码介绍

四、疑惑


一、文章简介

  • 文章名称:《InversionNet: An Efficient and Accurate Data-Driven Full Waveform Inversion》
  • 文章出处:IEEE TRANSACTIONS ON COMPUTATIONAL IMAGING
  • 文章作者:Yue Wu and Youzuo Lin
  • 面向数据集:OpenFWI中的Vel类、Fault类、Style类(时间域与宽度的比值很高)——2019年提出的完全端到端算法(最简单的一个,采用的是最基础的CNN网络进行架构)

        输入数据的详细参数如下图所示:

二、网络简单介绍

        InversionNet(深度学习实现的反演)构建了一个具有编码器-解码器结构的卷积神经网络,用以模拟地震数据与地下速度结构之间的对应关系。

2.1 编码器

        编码器(上侧部分)主要采用卷积层(非方形卷积)构建的,从输入的地震数据中提取出高级特征,并将高级特征压缩为单一的高维向量。在最后一个卷积层中并没有实施填充零的操作,一遍特征向量可以压缩为一个单一的向量。

        这个高维向量是由1*1的图块构成的512通道张量,可以认为是一个512维的向量。

        非方形卷积——空间压缩,因为输入的地震波图像的时间维度(图像的高)相比于宽度是很高的,所以需要使用一些比较窄的卷积将时间域压缩来与宽度差不多的程度,先经历宽度不变,高度被压缩的过程。

        从上图可以直观的感受到,最初的输入有6个通道,经过第一次卷积压缩变为32个通道(图像的尺寸变小、通道数变多才能保证信息的平衡),1000的高度变成了500;第二次使用两个卷积先将500的时间维度变为250,再使用这两个卷积将250的高度变为125,相当于经历了两次压缩过程(一次压缩使用2个卷积,相比于第一次卷积的压缩更加温和),一共用了4个卷积。第三次操作通过一次压缩、四次卷积的过程将125变为32,此时非方形卷积的目的已经达到了。第四操作中时间域与空间域的操作同时进行,采用一般卷积(方形卷积)进行压缩。

        注意:压缩其实是一个特征提取的过程,每一次的压缩不一定改变通道数,但是最终的目的会在有限次压缩后将通道数改变。特征提取的过程中需要保持通道数的增加,否则会导致空间信息严重丢失。

        这篇论文读出了一个结论:上述压缩信息是合理的,因为没有必要保留地震数据中的时间和空间的相关性。(ps:这个结论我们不能完全赞同,因为后面有人写了论文评判了这个思想。这也是InversionNet的一个缺点:对空间进行了舍弃。)

2.2 解码器 

        解码器(底部部分)通过一组反卷积(转置卷积)将这些特征转换为速度模型。

        下图架构中给出的h和w方便用户在未来适配更多的速度模型环境,对于70*70的速度模型,作者给出的h=w=5,在该模型下最终输出的尺寸为80*80(16w),最后通过裁剪得到70*70。

        反卷积可以将图像的维度进行升维,同时最大程度保留图像原本的性质,可以通过在输入特征地图上填充零来实现。反卷积的效果比一般的反池化(信息丢失较多)操作拥有更好的效果。

三、代码介绍

        注意:没有使用原论文中提到的1000*32的数据,而是使用的1000*70的OpenFWI的数据,这里采用的代码参照OpenFWI论文2022年)中公开的InversionNet的修改版代码,该代码的卷积过程与2019年发布的InversionNet论文中所展示的架构存在一定程度的差异。

        OpenFWI也是InversionNet作者所在的团队新提出来的,后续对网络的架构进行了修改。

  • 网络结构中展示的每个卷积操作实质上都是由卷积层、批归一化(BN)和LeaklyReLU共同构成的。
  • 在卷积层中,卷积承担输入信号的责任,同时担任滤波器(提取有意义的特征)的作用。
  1. 卷积:是应用于DL-FWI问题的理想方法,因为地震测量在空间上是连续的,而卷积层的局部连通性和权重共享使得特征提取有效和高校。
  2. 批量归一化(Batch Normalization):如果网络的输入具有零均值、单位方差和去相关,则深层网络的收敛速度会加快。有关研究进一步表明,使中间层的输出具有这些属性也是有利的。批量归一化用于在每次迭代时,对馈送到网络中的中间层的数据子集在输出时进行归一化。
  3. LeaklyReLU:用于解决ReLu的神经元死亡现象,LeaklyReLU通过将x的非常小的线性分量给予负输入αx来调整负值的零梯度问题,此外也可以扩大函数y的范围。

        InversionNet的末端采用的标准损失函数是L1规范的损失函数。(但是平常在进行测试的时候,使用L2更多一些,效果好一些)

L1(y,z)=\frac{1}{n}\sum_{i=1}^{n}|y_{i}-z_{i}|

        其中,yi是真实速度模型,zi是预测速度模型,n是速度模型中空间像素的数量。

  • ConvBlock卷积的声明: 
class ConvBlock(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1, norm='bn', relu_shop=0.2, dropout=None):
        """
        Standard convolution operation [Affiliated with InversionNet]
        :param in_channels:    Number of channels of input 输入的通道数
        :param out_channels:   Number of channel of output 输出的通道数
        :param kernel_size:    Size of the convolution
        :param stride:         Step of the convolution
        :param padding:        Zero-fill width
        :param norm:           The means of normalization
        :param relu_shop:      Parameter of relu
        :param dropout:        Weather of apply dropout
        """
        super(ConvBlock, self).__init__()

        # 构造卷积层
        layers = [nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding)]

        # 批归一化层
        if norm in NORM_LAYERS:
            layers.append(NORM_LAYERS[norm](out_channels))

        # 激活函数层
        layers.append(nn.LeakyReLU(relu_shop, inplace=True))

        if dropout:
            layers.append(nn.Dropout2d(0.8))
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        '''
        :param x:               Input Image
        :return:
        '''
        return self.layers(x)
class ConvBlock_Tanh(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1, norm='bn'):
        '''
        Convolution operation of the output part
        [Affiliated with InversionNet]

        :param in_channels:     Number of channels of input
        :param out_channels:    Number of channels of output
        :param kernel_size:     Size of the convolution kernel
        :param stride:          Step size of the convolution
        :param padding:         Zero-fill width
        :param norm:            The means of normalization
        '''
        super(ConvBlock_Tanh, self).__init__()
        layers = [nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding)]
        if norm in NORM_LAYERS:
            layers.append(NORM_LAYERS[norm](out_channels))
        layers.append(nn.Tanh())
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        '''
        :param x:               Input Image
        :return:
        '''
        return self.layers(x)
class DeconvBlock(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=2, stride=2, padding=0, output_padding=0, norm='bn'):
        '''
        Deconvolution operation
        [Affiliated with InversionNet]

        :param in_channels:     Number of channels of input
        :param out_channels:    Number of channels of output
        :param kernel_size:     Size of the convolution kernel
        :param stride:          Step size of the convolution
        :param padding:         Zero-fill width of input
        :param output_padding:  Zero-fill width of output
        :param norm:            The means of normalization
        '''
        super(DeconvBlock, self).__init__()
        layers = [nn.ConvTranspose2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding, output_padding=output_padding)]
        if norm in NORM_LAYERS:
            layers.append(NORM_LAYERS[norm](out_channels))
        layers.append(nn.LeakyReLU(0.2, inplace=True))
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        '''
        :param x:               Input Image
        :return:
        '''
        return self.layers(x)
  •  网络搭建:

        注意:2019年论文只针对时间域压缩,但是2022年论文不再只针对时间域的压缩,因为此时长宽比已经很接近与1。 

class InversionNet(nn.Module):
    def __init__(self, dim1=32, dim2=64, dim3=128, dim4=256, dim5=512, **kwargs):
        '''
        Network architecture of InversionNet
        :param dim1:            Number of channels in the 1st layer
        :param dim2:            Number of channels in the 2nd layer
        :param dim3:            Number of channels in the 3rd layer
        :param dim4:            Number of channels in the 4th layer
        :param dim5:            Number of channels in the 5th layer
        :param sample_spatial:  Scale parameters for sampling in space
        '''
        super(InversionNet, self).__init__()

        # 时间域的第一次降维,直接通过一批(32个)卷积进行降维——T:1000->T:500
        # ConvBlock中进行了封装,包括二维的卷积操作、批归一化BN以及Relu三个操作
        self.convblock1 = ConvBlock(5, dim1, kernel_size=(7, 1), stride=(2, 1), padding=(3, 0))

        # 时间域的第二次降维,通过两批(64个)卷积进行降维——T:500->T:250
        self.convblock2_1 = ConvBlock(dim1, dim2, kernel_size=(3, 1), stride=(2, 1), padding=(1, 0))
        self.convblock2_2 = ConvBlock(dim2, dim2, kernel_size=(3, 1), padding=(1, 0))

        # 时间域的第三次降维,通过两批(64个)卷积进行降维——T:250->T:125
        self.convblock3_1 = ConvBlock(dim2, dim2, kernel_size=(3, 1), stride=(2, 1), padding=(1, 0))
        self.convblock3_2 = ConvBlock(dim2, dim2, kernel_size=(3, 1), padding=(1, 0))

        # 时间域的第四次降维,通过两批(64个)卷积进行降维——T:125->T:63
        self.convblock4_1 = ConvBlock(dim2, dim3, kernel_size=(3, 1), stride=(2, 1), padding=(1, 0))
        self.convblock4_2 = ConvBlock(dim3, dim3, kernel_size=(3, 1), padding=(1, 0))

        # 单方面降维结束,进入两个方向同时的降维——R:70->35 T:63->32
        self.convblock5_1 = ConvBlock(dim3, dim3, stride=2) # 默认构造方形卷积
        self.convblock5_2 = ConvBlock(dim3, dim3)

        # 两个方向同时的降维——R:35->18 T:32->16
        self.convblock6_1 = ConvBlock(dim3, dim4, stride=2)
        self.convblock6_2 = ConvBlock(dim4, dim4)

        # 两个方向同时的降维——R:16->8 T:16->8
        self.convblock7_1 = ConvBlock(dim4, dim4, stride=2)
        self.convblock7_2 = ConvBlock(dim4, dim4)

        self.convblock8 = ConvBlock(dim4, dim5, kernel_size=(8, math.ceil(70 * 1.0 / 8)), padding=0)

        self.deconv1_1 = DeconvBlock(dim5, dim5, kernel_size=5)
        self.deconv1_2 = ConvBlock(dim5, dim5)

        self.deconv2_1 = DeconvBlock(dim5, dim4, kernel_size=4, stride=2, padding=1)
        self.deconv2_2 = ConvBlock(dim4, dim4)

        self.deconv3_1 = DeconvBlock(dim4, dim3, kernel_size=4, stride=2, padding=1)
        self.deconv3_2 = ConvBlock(dim3, dim3)

        self.deconv4_1 = DeconvBlock(dim3, dim2, kernel_size=4, stride=2, padding=1)
        self.deconv4_2 = ConvBlock(dim2, dim2)

        self.deconv5_1 = DeconvBlock(dim2, dim1, kernel_size=4, stride=2, padding=1)
        self.deconv5_2 = ConvBlock(dim1, dim1)
   
        # 裁剪输出层
        self.deconv6 = ConvBlock_Tanh(dim1, 1)

        测试: 

if __name__ == '__main__':
    # InversionNet
    x = torch.zeros((10, 5, 1000, 70))
    model = InversionNet(inchannel= 5, w = 70)
    out = model(x)
    print("out: ", out.size())

四、疑惑

  1. CNN网络架构?
  2.  完全端到端的理解?
  3. 步长、零填充的理解?
  4. 反池化、反卷积的理解?
  5. 滤波器?
  6. 零均值、单位方差和去相关?
  7. LeaklyReLU与ReLU的区别?
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算机网络基础学习框架可以帮助初学者系统地学习计算机网络的相关知识。以下是一份可能的学习框架: 1. 基础知识学习:掌握计算机基础、操作系统、编程语言等基础知识。可以通过自学或参加相关课程来获得。 2. 网络概述:了解计算机网络的基本概念、分类、结构和发展历程。可以通过阅读相关书籍、观看视频教程等方式来学习。 3. 网络协议:学习计算机网络的基本协议,包括TCP/IP协议、应用层协议、网络层协议、传输层协议等。可以通过阅读相关书籍、参加在线课程等方式来学习。 4. 网络拓扑:学习计算机网络的基本拓扑结构,包括总线型、环形、星型、树型、网状等。可以通过阅读相关书籍、观看视频教程等方式来学习。 5. 网络设备:了解计算机网络的基本设备,包括交换机、路由器、网关、防火墙等。可以通过阅读相关书籍、观看视频教程等方式来学习。 6. 网络安全:学习计算机网络的安全问题,包括网络攻击、防范措施、加密技术等。可以通过阅读相关书籍、参加安全课程等方式来学习。 7. 实践操作:通过实践操作,加深对计算机网络的理解和掌握。可以使用一些模拟软件、虚拟机或者云平台来进行实践。 8. 持续更新与深度研究:计算机网络是一个不断发展的领域,需要持续地更新和深度研究。可以通过参加相关会议、阅读相关论文或参加网络社区来获取最新的计算机网络知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值