pytorch的波传播模块。

deepwave的Python项目详细描述


深波

构建状态Codacy徽章

DeepWave为Pythorch提供了波传播模块(目前仅适用于恒密度声波/标量波方程)。它主要用于地震成像/反演。其中一个有趣的优点是,它允许您将操作链接在一起。例如,您可以使用deepwave使用自定义成本函数(只要pytorch能够自动区分它)执行fwi,或者在波传播前后添加一些其他操作,pytorch将反向传播所有这些操作。

波的传播和fwi可以使用深层神经网络来实现。但是,像tensorflow和pytorch这样的深度学习工具目前速度太慢,内存不足,无法对真实的地震数据集进行处理。DeepWave使用更高性能的波传播模块(用C和CUDA编写)扩展了Pythorch,因此您可以在不牺牲性能的情况下从Pythorch的便利性中获益。

DeepWave运行在CPU和NVIDIA GPU上。它应该在安装过程中自动检测兼容的GPU,如果发现任何GPU代码,则编译GPU代码。要在GPU上运行,必须以标准pytorch方式(使用.cuda().to(设备))将模型、源振幅、源和接收器位置张量传输到GPU。

安装

deepwave需要numpy,因此强烈建议首先安装anaconda。它还需要在安装deepwave之前安装pytorch(使用类似conda install pytorch cpu-c pytorch的方法)。然后,您可以使用

pip安装deepwave

或使用

pip安装git+https://github.com/ar4/deepwave.git

用法

deepwave可以做两件事:正向建模和反向传播。

正向建模

我们首先需要创建一个波传播模块。如果您熟悉训练神经网络,这与定义您的网络(或其中的一部分)并初始化权重是一样的。

prop=deepwave.scalar.Propagator({'vp':model},dx)

两个必需的参数是波速模型(model)和模型中使用的单元格大小(dx)。该模型应以pytorch浮子张量的形式提供,[nz,(ny,(nx))]。1d、2d和3d传播器可用,模型形状用于在它们之间进行选择。例如,如果希望一维波传播,则模型形状将为[nz]。单元格大小还应作为单个浮点(如果在每个维度中都相同)或包含每个空间维度中单元格大小的浮点张量提供;3d中为[dz,dy,dx],1d中为[dz]

现在我们可以呼叫我们的传播者。

receiver_amplitudes=prop(source_amplitudes,x_s,x_r,dt)

所需参数是源振幅、源坐标(xus)、接收器坐标(xur)和源样本之间的时间间隔(dt)。接收器振幅返回。源振幅s应该是一个形状为[nt,num_shots,num_sources_per_shot]的浮点张量,其中nt是时间采样数。请注意,每次放炮可以有多个震源,但在活动震源地震实验中通常只有一个震源。源坐标数组是形状为[num-shots,num-sources-per-shot,num-dimensions]的浮点张量,其中num-dimensions对应于模型中的维数。类似地,接收器坐标数组是形状为[num-shots,num-receivers-per-shot,num-dimensions]的浮点张量。坐标以与dx相同的单位指定,并且与模型的原点有关。时间步长dt应为常规浮点。返回的形状为[nt,num_shots,num_receivers_per_shot]的浮点张量包含接收器振幅。

可以使用不同的输入多次运行正向传播,例如,对数据集中的每个快照进行正向建模。您可能已经注意到,传播器还被设计为同时转发多个单独的快照(输入中的num_shots维度)。这样做可能比单独传播每个快照提供更好的性能,但也可能会耗尽内存。

下面是一个完整的示例:

importmathimporttorchimportdeepwavedx=5.0# 5m in each dimensiondt=0.004# 4msnz=20ny=40nt=int(1/dt)# 1speak_freq=4peak_source_time=1/peak_freq# constant 1500m/s modelmodel=torch.ones(nz,ny)*1500# one source and receiver at the same locationx_s=torch.Tensor([[[0,20*dx]]])x_r=x_s.clone()source_amplitudes=deepwave.wavelets.ricker(peak_freq,nt,dt,peak_source_time).reshape(-1,1,1)prop=deepwave.scalar.Propagator({'vp':model},dx)receiver_amplitudes=prop(source_amplitudes,x_s,x_r,dt)

反向传播/反转(fwi)

fwi试图通过修改模型来匹配预测的和真实的接收器振幅。这类似于在训练期间修改神经网络中的权重。为了实现这一点,我们首先指定我们需要计算与我们的模型有关的梯度。

model.requires_grad=True

我们还需要指定要使用的优化算法和损失/成本/目标函数。

optimizer=torch.optim.Adam([model],lr=10)criterion=torch.nn.MSELoss()

我选择使用学习率为10的ADAM优化器,并使用均方误差(MSE)作为成本函数。mse cost函数是pytorch提供给我们的,但我也可以自己编写cost函数并使用它(只要pytorch可以自动区分它)。

当我们的传播器初始化为上面的正向建模部分时,我们可以迭代优化模型。

foriterinrange(num_iter):optimizer.zero_grad()receiver_amplitudes_pred=prop(source_amplitudes,x_s,x_r,dt)loss=criterion(receiver_amplitudes_pred,receiver_amplitudes_true)loss.backward()optimizer.step()

在每次迭代中,我们将梯度归零,从当前模型计算预测的接收器振幅,使用我们的成本函数将其与真实数据进行比较,反向传播计算相对于模型的损耗梯度,然后更新模型。

Pythorch的灵活性意味着很容易修改它以满足您自己的需要。

有关使用deepwave for fwi的完整示例,请参见本笔记本

利用深波进行震源反演也是可能的。只需在源振幅张量上将设置为真,就需要_grad

born正演模拟(用于分层和lsrtm)

要执行born正向建模,请使用bornpropagator。除了背景波速模型外,还需要散射模型("图像")。例如,将以下行添加到上面的常规正向建模示例中:

scatter=torch.zeros_like(model)scatter[10,20]=100

这将创建一个散射模型,其点散射体的振幅为100 m/s。然后,将创建传播器的线替换为使用born传播器的线:

prop=deepwave.scalar.BornPropagator({'vp':model,'scatter':scatter},dx)

结果数据应仅包含来自散射波场的记录,因此不会有任何直接到达。

要执行lsrtm,请优化变量scatter。Born传播子目前不支持优化源振幅或波速模型。

有关使用DeepWave进行LSRTM的示例,请参见本笔记本

注释

  • 深波只是测试使用Python 3.6。
  • 对于无反射曲面,将曲面处的PML宽度设置为零。例如,在3d中,当另一侧的pml宽度为10个单元格时,如果自由曲面位于第一个维度的开头,则在创建传播器时提供参数pml_width=[0,10,10,10,10]。格式为[z1,z2,y1,y2,x1,x2],其中z1,y1和x1是z,y和x维度开始处的pml宽度,z2,y2和x2是这些维度结束处的pml宽度。
  • 要将波浪模拟限制在测量覆盖的区域(源和接收器),请在创建传播器时提供测量键盘关键字参数。例如,要使用整个Z维度,但距离Y和X维度中的第一个和最后一个源/接收器最多100米,请使用survey_pad=[none,none,100,100,100,100],其中none表示继续到模型的边缘,格式与用于pml_宽度。每个条目的默认值都是none
  • @lukasmosser发现GCC 4.9或更高版本是必需的(;18)。
  • 支持镜头上的分布式并行化,但不支持镜头内的分布式并行化;每个镜头必须在一个节点内运行。
  • 目前,前向源波场保存在存储器中,以便在反向传播期间使用。这意味着真实的三维测量可能需要比可用内存更多的内存。这将在以后的版本中修复。

贡献

我们非常感谢您对改善深海波浪的帮助。如果您在使用deepwave时遇到任何困难,请将其作为github问题报告,以便修复。如果您有让deepwave更好的功能建议或其他想法,请将其作为github问题报告。如果你想帮助编码,那将是特别美妙的。github问题包含一个需要工作的列表。如果您看到要尝试的,请要求将其分配给您。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java两个构造函数?   java for(inti:x)做什么?   java如何将一个bean的构造函数参数传递给嵌套bean   java从易趣链接提取项目ID   java多线程BufferedReader   安卓全新应用程序在R.java中抛出“语法错误,插入“}”以完成类体”   java Spring启动依赖注入请求范围的bean   java给定的时间,然后约定和异常处理。和莫基托和朱尼特在一起   与Android Studio的java Oracle数据库连接   在web服务器(Heroku)上承载可运行jar文件(Discord bot)的java   java如何每隔n秒在imageview中更改图像   java不理解“volatile”关键字   java使用JPA编写自定义SQL查询   java如何使用filechannel作为参数来编写对象