DL-FWI——数据驱动的全波形反演
目录
5)地震数据(Seismic Data)、速度模型(Velocity Model)、道(Trace)
1. DL-FWI基础知识
1)何为全波形反演
地质勘探过程中的关键问题——探究地下结构的构造
- 钻井
- 波在不同介质结构中的运动速度不同,因此有人提出:在地表设置巨大的振动源来引发向下的波传导,同时在地表设置接收器来接受这些反馈(反射)信号,通过分析波的构造从而分析地下结构的构造。如炸药充当地震波
- 能控制能量和频率的非炸药震源称为可控震源。它通过一个特殊改装的车辆来控制。
- 通过右图的结构推测左图构造的问题就称之为全波形反演(FWI),即通过可控震源与接收器得到的反射信号所绘制出的地震数据推测地下真实结构的问题。从地震数据到速度模型,一个地震数据可能对应于多个速度模型。
- 正演(Forward modeling)指的是根据地下介质的物性参数,运用物理方程和数值计算方法,模拟真实地震波传播过程并得到合成地震记录的过程。可以认为正演是反演的逆过程:即通过地层图模拟地震波形。从速度模型到地震数据,一个速度模型只能生成一个地震数据。
2)FWI的数学表示(传统方式)
传统的FWI:使用声波方程或弹性波方程等波动方程来模拟地震波在地下介质中的传播过程。
大致过程: 根据一个初始的简化模型,使用声波或弹性波方程等进行正演模拟,得到模拟的地震波场数据(预测数据), 将观测的地震数据与模拟的地震数据之间的差异作为目标函数,使用优化算法(如梯度下降法)调整模型参数,使目标函数最小化,从而实现模拟数据与观测数据的匹配。
传统的FWI的求解方案是利用物理学上的波动方程(Wave Equation)来求解的,在这个过程中会通过多次迭代,吗,时间开销是巨大的, 而且依赖于初始解,存在病态性。
全波形反演的传统工作流程如下:
- 数据采集:不同于传统炸药,可控震源可以由操作者控制震源的能量和频率。通过控制震源产生人工地震波,并在地表设置接收器来接收反馈信号。
- 数据预处理:采集到的地震数据需要预处理,包括去除噪声、进行数据校正和滤波等。预处理的目标是减少数据中的干扰因素,以提高反演的准确性。
- 初始模型建立:在进行FWI之前,需要建立一个初始模型。初始模型可以是基于地质知识、地震剖面解释、地质模型等进行建立,可以是均匀的或简化的地下介质模型。
- 反演迭代:FWI的核心是迭代过程,通过将观测数据与模拟数据进行比较,并根据两者之间的差异来调整模型参数。在每次迭代中,根据当前模型生成的新的模拟数据,计算与观测数据直接的差异。根据残差信息来更新模型参数,如地下介质的速度、密度等。这个过程会不断重复直到达到预设的终止条件。
- 结果分析与解释:在完成全波形反演后,地质勘探专家需要对反演结果进行分析和解释,评估反演模型的准确性和可靠性,并与地质知识和先前的研究结果进行对比。通过关注地下介质的速度和密度变化,人们可以了解地下的岩石类型、构造特征和界面形态等。
3)FWI的端到端深度学习解释
- 端到端:把逆算子用神经网络代替进行预测,用深度网络直接进行输入输出的一种方法。即已知的地震数据和真实的地下介质模型(如速度模型等)作为训练集。设计一个深度神经网络模型(如CNN),其输入为地震数据,输出为预测的速度模型,并与真实的速度模型(作为标签)进行比较,不断迭代优化此模型,进而去推测地下构造。
注:在机器学习中,端到端方法是直接从原始数据开始,自动地从输入数据中学习并提取有用的特征,并最终产生所需的输出结果,中间不需要人工设计特征或额外的处理步骤。
- DL-FWI通常在训练阶段需要更多时间,实际预测花费时间很少,只需要几秒钟。一旦建立了良好的通用网络,那么就可以大大地减少FWI计算时间。
- 神经网络可以自然地将空间相关性作为正则化引入生成速度模型,这样可以抑制梯度中的噪声并减轻局部最小。(未理解)神经网络中的正则化
4)DL-FWI的基本发展和分类
- 严格的端到端手段:尝试通过设计构建完善的网络去拟合函数
,将设计侧重在网络的设计中,它们大多是CNN的编-解码结构,但这种设计可能会弱化一些物理意义和空间信息。 补充1:编码:把较大图像通过卷积的各种操作将其压缩成较小的、通道数较长的一种结构。 补充2:卷积神经网络CNN机器学习算法之——卷积神经网络(CNN)原理讲解
- 空间信息的嵌入手段:强调在空间中提供重要的信息参与训练,这个过程中伴随着其他特征网络的维度控制,这个时候就会有DNN参与进来。
嵌入特征有非常强的空间解释性,但是目前嵌入有关论文的开源性很差。 - 非严格端到端网络架构结构(GAN等)
- 训练场景(无监督等)
- 训练思路(渐进迁移等)
5)地震数据(Seismic Data)、速度模型(Velocity Model)、道(Trace)
- 地震数据:在位置A触发振动源,所有接收器都会陆续接收到波信号,这些信号可以绘制出炮面图A。然后移动振动源到位置B、C触发振动源,同理我们会得到炮面图B,C。振动源动而接收器没动,故这些炮面图互不相同。因此放S个炮就可以得到S个炮面图,我们将他们"捆”在一起,成为一个"S-通道的图集",同时炮面图的宽度=接收器个数,高度=采样时长。
- 速度模型:每个像素点表示的是波在这个介质中传播的速度。它所表示的物理意义更接近于"速度值”的分布,只因这种分布与地表构造强相关,故我们可以通过这种”速度值”的分布来分析地层样貌。
- 道:单个检波器采集到的数据, 它为一个时序, 称为一个道 (trace)。
- 在计算机中的解释:地震图像中的任意一个纵向的向量。如果这个图像宽R,那么它最多就有R个道,如果这个图像高T,那么每个道的长度都是T,维度为(T x 1)。
- 在物理意义上的解释:任意一个地震检波器在T时间内接受到的波形信号组,是一个时间序列数据。
2. 数据中的信息与数据的运用
1)数据集:
数据集本身是由若于个{ 地震数据-速度模型 }构成的数据对,任何一个地震数据必然有其对应的速度模型,反之亦然。
SEG盐体数据:描述了一个大约2km×3km的地下二维剖面区域。采样后(距离10m进行一个采样),地下的像素区域大小为201×301,波在这个地下区域的传播速度为1500m/s~4482m/s。
这个SEG盐数据是现实地下盐层三维分析数据通过剖面切片获得的,一共获得了140个切面数据。
图中黄色部分代表盐体(Salt Body),波在这个介质中的传播较快:
盐体:指地下储存着盐类矿物质的岩体,通常由氯化钠、硫酸钠、硼酸盐等组成。这些盐体往往形成在海洋或湖泊的底部,因为这些地方有更多的水分和盐分,有利于盐类矿物质的沉积和聚集。在一些地方,盐体可以被开采并用于食品加工、化学工业等领域。
SEG盐体数据的模拟数据:
- 真实数据的量匮乏,而DL-FWI的一般网络都是非常吃数据量的模型,故还需要通过合成一些同SEG盐数据类似分布的模拟数据来进行预训练,作为网络背景。
- 该模拟数据集有1700个与SEG盐数据大小相同的合成速度模型。
- 每幅图像都有不同宽度的层,从大约5到12层不等。为了精确模仿盐体,每个速度模型在中间或底部随机嵌入了随机形状的盐体。同时模拟数据的地层速度波动也控制在2000km/s~4500km/s。
- 这个模拟数据最早出现于FCNVMB提供的开源数据.
地震波数据采集参数相关参数:
- Grid spacing(网格间距):每个像素点放在真实的环境下是10*10m的方格,即地下模型离散化时的网格间距为10米
- Source frequency:震源频率25hz
- Source spacing(震源间距):每个采样的间距103.45m,即每一炮之间的距离。
- Source numbers(震源数量):设置了29炮
- Receiver spacing(接收器间距):接收器的间距是10m,
- Receiver numbers(接收器数量):接收器数量301
- Time Spacing(时间采样间隔):时间采样是2000个采样点,共2s,时间间隔0.001s
OpenFWI数据集:
- OpenFWI是近一两年随着DL-FWI的蓬勃发展而诞生的大规模、多结构基准数据集的集合。它包含了12个根据不同先验合成的数据集,其中包括一个3D数据集。
- 而这12个数据集又可以细分为四类数据,Vel类(地层面比较平滑,没有断层),Fault类(断层),Style类,Kimberlina类(基于气体存储构造的数据集)。除Style外,它们都表示不同的地下结构,Style则为一种自然图像的迁移假想地层。
- A/B代表地层的难度分级,A简单,B复杂
下采样?(未解决)
2)数据的操作:读取
目前,FWI的数据并没有统一的格式系统,以.mat和.npy为例。
- 一般来说,地震数据都存储在.mat中的一个单变量中(.mat可存储多个变量),而Python可以直接读取.mat文件中的某个变量。
import scipy.io
numpy_file = scipy.io.loadmat(mat_file)[ "var_name"]
- .npy是Python的numpy变量直接存储的格式,它的读取非常方便,直接就读取得到某个变量。
import numpy as np
dataset = np.load(np_file)
3)数据的操作:存储
地震数据的存储操作相对较少,但在长期训练过程中,额外保存中间变量可以节省时间操作,主要建议是通过.npy来进行保存(既方便写也方便读)。
import numpy as np
dataset = np.save(np_file)
4)数据的操作:展示
SEG地震数据注解:
- figsize(w,h):设置长宽比 ;
- extent
(left, right, bottom, top)
:指定显示的范围,它表示左、右、下和上的坐标。 - cmap参数可以用来控制图像的色彩映射方式,它可以是预设的颜色映射,比如'gray'、'hot'等等,也可以是用户自定义的颜色映射。
- vmin和vmax参数:用于控制图像显示像素值的范围,通常情况下图像中的像素值是在[0,1]之间的,通过设置vmin和vmax参数可以将像素值的范围限定在指定区间内。
-
subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None):调整子区的展现效果,值均为0~1之间,即控制图像留白区域。
def pain_seg_seismic_data(para_seismic_data):
'''
PLotting seismic data images of SEG salt datasets
: param para_seismic_data: Seismic data (4e0 x 3e1)(numpy)
: param is_coLorbar: whether to add a color bar (1 means add,0 is the defauLt,means don't add)
'''
fig,ax = plt.subplots(figsize=(6.2,8).dpi = 120)
im = ax.imshow(para_seismic_data,extent=[0,300,400,0],cmap=plt.cm.seismic,vmin=-0.4,vmax=0.44)
ax.set_xlabel( 'Position (km)',font21)
ax.set_ylabel( 'Time (s)',font21)
ax.set_xticks(np.linspace(0,300,5))
ax.set yticks(np.linspace(e,400,5))
ax.set_xticklabels(1abels = [0,0.75,1.5,2.25,3.0],size=21)
ax.set_yticklabels(labels = [0.0,0.50,1.00,1.50,2.00],size=21)
plt.rcParams ['font.size']= 14 #set colorbar font size
divider = make_axes_locatable(ax)
cax = divider.append_axes("top",size="3%",pad=0.32)
plt.colorbar(im,ax=ax,cax=cax,orientation='horizontal')
plt.subplots_adjust(bottom=0.08,top=0.98,left=0.11,right=0.99)
plt.show
附:Matplotlib 是 Python 生态系统的一个重要组成部分,是用于可视化的绘图库,它提供了一整套和 matlab 相似的命令 API 和可视化界面,可以生成出版质量级别的精美图形。
安装成功后,即可以在 Python 中像使用其它库一样导入和使用 Matplotlib,而无需更多文件的配置,通常我们将其导入后使用别名 mpl:
import matplotlib as mpl
OpenWFI地震数据注解:
- cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]):
- src:原始图像。
- dsize:目标图像尺寸。
- dst:目标图像,可以不传入,函数会自动创建—个。
- fx:沿水平方向的缩放比例。
fy:沿垂直方向的缩放比例。 - interpolation:插值方法,可选值包括cv2.INTER_NEAREST(最近邻插值法)、cv2.INTER_LINEAR(双线性插值法,默认)、cv2.INTER_AREA(基于局部像素的重采样)、cv2.INTER_CUBIC(基于4x4像素邻域的3次插值法)、cv2.INTER_LANCZOS4(基于8x8像素邻域的Lanczos插值)等。
def pain_openfwi_seismic_data(para_seismic_data):
'''
PLotting seismic data images of openfwi dataset
: param para_seismic_data: Seismic data (1eee x 70)(numpy)
'''
data = cv2.resize(para_seismic_data,dsize=(400,301),interpolation=cv2.INTER_CUBIC)
fig, ax = plt.subplots(figsize=(6.1,8),dpi = 120)
im = ax.imshon(data,extent=[0,0.7,1.0,0],cmap=plt.cm.seismic,vmin=-18,vmax=19)
ax.set_xlabel( 'Position(km)' , font21)
ax.set_ylabel( 'Time (s)', font21)
ax.set_xticks(np.linspace(0,0.7,5))
ax.set_yticks(np.linspace(0,1.0,5))
ax.set_xticklabels(labels=[0,0.17,0.35,0.52,0.7],size=21)
ax.set_yticklabels(1abels=[0,0.25,0.5,0.75,1.0], size=21)
plt.rcParams ['font.size']= 14 # Set colorbar font size
divider = make_axes_locatable(ax)
cax = divider.append_axes( "top", size="3%", pad=0.3)
plt.colorbar(im, ax=ax, cax=cax, orientation='horizontal')
plt.subplots_adjust(bottom=0.08,top=0.98,1eft=0.11,right=0.99)
plt.show()
SEG速度模型注解:
def pain_seg_velocity_model(para_velocity_model,min_velocity,max_velocity):
'''
:param para_veLocity_model: veLocity model (200 x 301)(numpy)
:param min_velocity: upper limit of velocity in the veLocity modeL
:param max_veLocity: Lower limit of velocity in the veLocity modeL
:return:
'''
fig, ax = plt.subplots(figsize=(5.8,4.3),dpi=150)
im = ax.imshow(para_velocity_model,extent=[0,3,2,0],vmin=min_velocity,
vmax=max_velocity)
ax.set_xlabel( 'Position(km)', font18)
ax.set ylabel( 'Depth(km)', font18)
ax.tick_params (labelsize=14)
plt.rcParams [ 'font.size'] = 14 # Set colorbar font size
divider = make_axes_locatable(ax)
cax = divider.append_axes("top", size="3%", pad=0.32)
plt.colorbar(im, ax=ax, cax=cax, orientation='horizontal',
ticks=np.linspace(min_velocity,max_velocity,7))
plt.subplots_adjust(bottom=0.12,top=0.95,left=0.11,right=0.99)
plt.show()