Pytorch实现波阻抗反演

1 引言

地震波阻抗反演是在勘探与开发期间进行储层预测的一项关键技术。地震波阻抗反演可消除子波影响,仅留下反射系数,再通过反射系数计算出能表征地层物性变化的物理参数。常用的有道积分、广义线性反演、稀疏脉冲反演、模拟退火反演等技术。

随着勘探与开发的深入,研究的地质目标已经从大套厚层砂体转向薄层砂体,而利用常规波阻抗反演方法刻画薄层砂体不仅要消耗大量人力、物力,且反演得到的波阻抗精度也难以满足实际需求。近年来,深度学习在地震反演和解释等地震领域显现出了巨大的潜力,其中,卷积神经网络(Convolution Neural Networks,CNN)是解决地震反演的一大有力工具。本文将介绍如何搭建CNN网络进行波阻抗反演。

2 Python环境配置

我们将使用Python语言以及Pytorch深度学习框架完成实验,因此首先需要配置Python环境。

(1)安装Anaconda

下载地址Anaconda | The World's Most Popular Data Science Platform

Anaconda是一个开源的Python和R语言的发行版本,用于计算科学(数据科学、机器学习、大数据处理和预测分析),致力于简化软件包管理系统和部署。

安装过程“下一步、下一步”,在这一步时,勾选添加Anaconda到环境变量(注意:在环境变量中有QT、R语言等时,须在“编辑环境变量”中手动将Anaconda路径下移,防止变量、路径被覆盖)

(tips:Python和Anaconda都有蟒蛇的意思)

选择Anaconda主要有几个原因:

  • Anaconda的包使用软件包管理系统Conda进行管理,提供了conda install xxx命令,与pip install xxx功能相同。当pip安装库出现一些未知错误时,Conda可以作为补充,省去非必要的报错纠结;
  • Anaconda整合了本机中的Python环境与Python包路径,并且提供虚拟环境管理,使得不同Python版本(Python2.x,Python3.x)、CPU/GPU版第三方库可以并列共存。避免了在今后使用中出现版本、路径、环境混乱的问题;
  • 下载安装Anaconda可以一键获取新手套装,无需从Python官网从零开始。

随Anaconda一同下载的有

  • Anaconda Navigator:是包含在Anaconda中的图形用户界面,用户可以通过Anaconda Navigator启动应用,在不使用命令行的情况下管理软件包、创建虚拟环境和管理路径。

  • Jupyter Notebook:是一个基于Web的交互式计算环境,用于创建Jupyter Notebook文档。这类文档是一个JSON文档,包含一个有序的输入/输出单元格列表,这些单元格可以包含代码、文本(使用Markdown语言)、数学、图表和富媒体 (Rich media),通常以“.ipynb”结尾扩展。Jupyter Notebook的最大的优点就是可以“做一步看一步”,对于初学和开荒Python项目时,可以更简单、高效地编程。

  • Spyder,是一个开源、免费的Python集成开发环境(IDE)。其最大优点是模仿MATLAB的“工作空间”的功能,便于观察变量的值、维度、类型等信息。

  • Anaconda Prompt:等同Window PowerShell和cmd。

(2)安装Pycharm

下载地址Download PyCharm: Python IDE for Professional Developers by JetBrains

由捷克JetBrains公司专为Python打造,PyCharm具备一般IDE的功能,比如,调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。PyCharm是商业软件,与Visual Stidio类似,有收费的专业版(Professional)和免费的社区版(Community),社区版能够满足一般编程需要,专业版集成了Jupyter Notebook并且支持远程开发。

下载Community版后,安装过程除了调整路径外,没有需要操作的地方,非必须的可选项都不打勾,然后“下一步下一步”。

安装完成后来到新建工程,以及配置Python环境的环节:

第一次创建工程、加载环境需要等上几分钟,读条完成后,这个工程的Python环境及编辑器就配置完成了。

3 Pytorch实战

首先我们需要在本地安装Pytorch,打开Anaconda Prompt或Window PowerShell或cmd,安装指令为

  1. pip install torch torchvision torchaudio
  2. 或者
  3. conda install pytorch torchvision torchaudio cpuonly -c pytorch

即可安装CPU版Pytorch(GPU版的安装稍复杂,此处不作详细介绍),随后开始本次项目的实战部分。

(1)数据准备

Step 1 导入数据

导入的数据包括地震记录,此处的数据已经被整理存储为.mat格式,通过scipy.io库将其读入。地震道与波阻抗数据都是文件中的键值对,从原始数据中抽取出部分作为实验数据集。

  1. dataframe = sio.loadmat('Train_DataSyn_Ricker30.mat')
  2. #从文件中分别提取提取地震道与波阻抗数据
  3. Seismic_data = dataframe['Seismic'] #地震道
  4. Impedance_data = dataframe['Imp']/1e6 #波阻抗
  5. #随机抽取部分道,作为训练集
  6. howMany = 2020
  7. np.random.seed(9) #随机种子,便于复现
  8. indxRand = [randint(0,dataframe['Seismic'].shape[1]-1) for p in range(0,howMany)] #随机索引
  9. #地震道
  10. Seismic_data = Seismic_data.transpose() #转置
  11. Seismic_data = Seismic_data[indxRand,:] #通过索引抽取
  12. #波阻抗
  13. Impedance_data = Impedance_data.transpose()
  14. Impedance_data = Impedance_data[indxRand,:]

数据展示如下:

我们的目标即是通过建立CNN模型挖掘规律,建立地震振幅属性\(\Longrightarrow\)波阻抗的映射,在未知波阻抗的地方可用地震记录进行预测,实现波阻抗反演。

Step 2 分割数据集

通常一个机器学习项目会需要我们对数据集进行分割,划分为训练集(建模)、验证集(调整超参数与初步评估)和测试集(评估模型)。

  1. #其中验证集500个,测试集1000个,剩余(520)为训练集
  2. howManyToValidate = 500
  3. howManyToTest = 1000
  4. #对输入Seismic与标签Imp进行相同的索引与处理
  5. #用numpy索引切片的方式进行划分
  6. valX = (Seismic_data[:howManyToValidate,:])
  7. testX = (Seismic_data[howManyToValidate:howManyToValidate+howManyToTest,:])
  8. trainX = (Seismic_data[howManyToValidate+howManyToTest:,:])
  9. valImp = (Impedance_data[:howManyToValidate,:])
  10. testImp = (Impedance_data[howManyToValidate:howManyToValidate+howManyToTest,:])
  11. trainImp = (Impedance_data[howManyToValidate+howManyToTest:,:])
  12. #转为torch中的Tensor格式
  13. #此时数据为(道数,采样点数)的二维数组,按照torch的输入格式整理为(道数,数据高度,数据长度),便于后续输入道CNN网络中
  14. valX = torch.FloatTensor(np.reshape(valX, (valX.shape[0], 1, valX.shape[1])))
  15. testX = torch.FloatTensor(np.reshape(testX, (testX.shape[0], 1, testX.shape[1])))
  16. trainX = torch.FloatTensor(np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1])))
  17. valImp = torch.FloatTensor(np.reshape(valImp, (valImp.shape[0], 1, valImp.shape[1])))
  18. testImp = torch.FloatTensor(np.reshape(testImp, (testImp.shape[0], 1, testImp.shape[1])))
  19. trainImp = torch.FloatTensor(np.reshape(trainImp, (trainImp.shape[0], 1, trainImp.shape[1])))

(2) 建模

Step 1 建立网络

采用一维卷积神经网络(1D CNN)进行波阻抗的生成与预测,具体步骤与结构如下图。

创建神经网络通常也就是创建一个继承自***torch.nn.Module***的类,而将网络层及其连接定义在类中的方法中

  1. noOfNeurons = 60 #定义卷积核个数
  2. dilation = 1
  3. kernel_size = 300 #卷积核尺寸
  4. stride = 1 #卷积核滑动步长
  5. padding = int(((dilation*(kernel_size-1)-1)/stride-1)/2) #0填充个数
  6. class CNN(nn.Module):
  7. def __init__(self): #构造函数
  8. super(CNN, self).__init__() #前面三行为固定格式
  9. self.layer1 = nn.Sequential( #nn.Sequential为一个顺序的容器
  10. #Conv1d的前两个参数分别表示输入通道数与输出通道数,又有卷积核个数=卷积层输出通道数
  11. nn.Conv1d(1, noOfNeurons, kernel_size=kernel_size, stride=1, padding = padding+1),#卷积层
  12. nn.ReLU()) #ReLu激活函数
  13. self.layer2 = nn.Sequential(
  14. nn.Conv1d(noOfNeurons, 1, kernel_size=kernel_size, stride=1, padding = padding+2),
  15. nn.ReLU())
  16. def forward(self, x): #在forward中将网络像搭积木一样连接起来
  17. out = self.layer1(x)
  18. out = self.layer2(out)
  19. return out
  20. cnn = CNN() #实例对象

注:①在PyTorch中,可以把神经网络类中forward函数看作一个专用函数,它专门用于编写前向传播的计算方法,并且已经写在了nn.Module的“出厂设置”中,在传入数据时便会开始执行,如上例中,使用cnn(x)本质上等于cnn.forward(x),显式使用后者反而报错。

②关于激活函数

激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,能够完成极其复杂的分类或回归任务。若没有激活函数,则每层就相当于矩阵乘法。

Sigmoid——nn.Sigmoid()

\(\text{Sigmoid}(x) = \sigma(x) = \frac{1}{1 + \exp(-x)}\)

优点:

能够将函数压缩至区间[0,1]之间,保证数据稳定,波动幅度小

缺点:

  • 函数在两端的饱和区梯度趋近于0,当反向传播时容易出现梯度消失或梯度爆炸
  • 输出不是0均值(zero-centered),导致收敛缓慢
  • 运算量较大

如果我们在多个层中堆叠sigmoid,则系统学习效率可能低下,并且需要仔细初始化。因此,对于深度神经网络,首选ReLU函数。

ReLU(Rectified Linear Unit,修正线性单元)——nn.ReLU()

\(\text{ReLU}(x) = (x)^{+} = \max(0,x)\)

优点:

  • 梯度不饱和,收敛速度快
  • 减轻反向传播时梯度弥散的问题
  • 无需进行指数运算,运算速度快、复杂度低

缺点:

  • 输出不是0均值(zero-centered)
  • 对参数初始化和学习率非常敏感,容易出现神经元死亡。

常用的激活函数还有许多:

**Step 2 定义训练参数**

  1. #定义与训练有关的超参数
  2. num_epochs = 500 #迭代轮数
  3. batch_size = 1 #批次大小
  4. learning_rate = 0.001 #学习率
  5. batch_size_tot = trainX.shape[0]
  6. no_of_batches = int((batch_size_tot - batch_size_tot%batch_size)/batch_size) #总批数
  7. loss_fn = nn.MSELoss() #损失函数,此处为一个回归任务,采用均方根误差作为损失值
  8. optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate) #优化器选择为Adam

注:①pytorch中的nn模块提供了很多可以直接使用的loss函数,常用的有:

损失函数 名称 适用场景
torch.nn.MSELoss() 均方误差损失 回归
torch.nn.L1Loss() 平均绝对值误差损失 回归
torch.nn.CrossEntropyLoss() 交叉熵损失 多分类
torch.nn.BCELoss() 二分类交叉熵损失 二分类
torch.nn.MultiLabelMarginLoss() 多标签分类的损失 多标签分类

②使用Loss函数会对每个样本计算其损失,然后开始梯度下降去降低损失\(w+=-\alpha dx\),最基础的是一次优化输入一个样本的随机梯度下降(Stochastic gradient descent,SGD),或是一个小批次(Mini-batch)。除此之外还有很多种不同的优化器,torch.optim是一个实现了各种优化算法的库。它们采取不同的策略更新梯度,比初始的梯度下降更加高效:

函数 描述 公式
torch.optim.SGD SGD算法 \(w=w-{\frac {\eta }{n}}\sum _{i=1}^{n}\nabla J_{i}(w)\)
torch.optim.SGD
(Momentum=0.9...)
Momentum算法 \(m=b_1*m-\alpha dx\)
\(w=w+m\)
torch.optim.AdaGrad AdaGrad算法 \(v=v+dx^2\)
\(w=w-\alpha *\frac{dx}{\sqrt v }\)
torch.optim.RMSProp RMSprop算法
(Root Mean Square Prop)
Momentum+AdaGrad
\(v=b_1*v+(1-b_1)*dx^2\)
\(w=w-\alpha *\frac{dx}{\sqrt v }\)
torch.optim.Adam Adam算法
(Adaptive momentum)
\(m=b_1*m+(1-b_1)*dx\)
\(v=b_2*v+(1-b_2)*dx^2\)
\(w=w-\alpha *\frac{m}{\sqrt v }\)

Step3 训练

  1. for epoch in range(num_epochs): #开始迭代
  2. for i in range(no_of_batches):
  3. #地震道数据
  4. #通过手动索引的方式建立batch
  5. #使用Variable对Tensor进行封装,便于改变Tensor的.data、.grad、.grad_fn属性
  6. traces = Variable(trainX[i*batch_size:(i+1)*batch_size,:,:])
  7. imp_label = Variable(trainImp[i*batch_size:(i+1)*batch_size,:,:])
  8. '''以下5行代码为固定格式,几乎所有pytorch网络都是同样的'''
  9. outputs = cnn(traces) #将训练数据输入道cnn模型中,前向传播
  10. loss = loss_fn(outputs, imp_label) #计算损失
  11. optimizer.zero_grad() #每一批次计算完成后梯度清零
  12. loss.backward() #反向传播
  13. optimizer.step() #梯度更新
  14. #然后在每一批次训练完成后,用交叉验证集检验
  15. traces_val = Variable(valX)
  16. outputs_val = cnn(traces_val)
  17. imp_val = Variable(valImp)
  18. loss_val = loss_fn(outputs_val, imp_val)
  19. #打印
  20. print ('Epoch [%d/%d], Iter [%d], Train Loss: %.6f, Validation Loss: %.6f'
  21. %(epoch+1, num_epochs, i+1, loss.data.cpu().numpy(), loss_val.data.cpu().numpy()))

输出如下:

  1. Epoch [1/500], Iter [1400], Train Loss: 0.357334, Train Loss: 0.099698, Validation Loss: 0.489520, Validation Loss: 0.121744
  2. Epoch [2/500], Iter [1400], Train Loss: 0.279390, Train Loss: 0.088157, Validation Loss: 0.453510, Validation Loss: 0.117180
  3. Epoch [3/500], Iter [1400], Train Loss: 0.249917, Train Loss: 0.083377, Validation Loss: 0.435483, Validation Loss: 0.114828
  4. Epoch [4/500], Iter [1400], Train Loss: 0.277595, Train Loss: 0.087873, Validation Loss: 0.431772, Validation Loss: 0.114337
  5. ...

模型的损失值曲线图如下:

### (3)预测

Step 1 预测测试集

通常测试集也是有标签的,我们能够直观地对比模型的预测效果与精度。

  1. #抽取出待测的地震道
  2. sampleNumber = 25
  3. TestingSetSeismicTrace = Variable(testX[sampleNumber:sampleNumber+1,:,:]) #输入数据
  4. CNN_ImpedancePrediction = cnn(TestingSetSeismicTrace) #预测结果

图中展示了4道的真实波阻抗与CNN预测波阻抗:

**Step 2 保存&加载模型**

训练一次模型往往需要花费很长时间,将模型保存下来,在需要的时候载入,避免关闭程序后再重新训练。

  1. #保存模型
  2. with open('cnn.pkl', 'wb') as pickle_file:
  3. torch.save(cnn.state_dict(), pickle_file)
  4. #加载模型
  5. #加载时需要先实例化对象
  6. cnn_new = CNN()
  7. with open('cnn.pkl', 'rb') as pickle_file:
  8. cnn_new.load_state_dict(torch.load(pickle_file))

Step 3 应用

应用时往往没有标签(波阻抗),需要模型由已知数据预测未知。

  1. dataframe = sio.loadmat('HardTest_DataSyn_Ricker30.mat')
  2. TestingSeismic = dataframe['wz_with_multiples']
  3. TestingSeismic = TestingSeismic.transpose()[:, 0:333]
  4. TestingImpedance = dataframe['IpTimeVec']/1e6
  5. TestingImpedance = TestingImpedance.transpose()[:, 0:333]
  6. print(TestingImpedance.shape[1])
  7. sampleNumber = 25
  8. #抽取应用数据的地震道
  9. AppSeismicTrace = AppSeismic[sampleNumber,:]
  10. #Numpy.array-->Tensor-->Variable
  11. AppSeismicTraceTorch = torch.FloatTensor(np.reshape(AppSeismicTrace, (1,1, AppSeismicTrace.shape[0]))) #输入尺寸与训练集保持一致,第一个1表示应用当前单个样本
  12. AppSeismicTraceTorch = Variable(AppSeismicTraceTorch) #封装成Variable
  13. #用加载的cnn_new模型去预测
  14. CNN_ImpedancePrediction = cnn_new(AppSeismicTraceTorch)

于是,我们便完成了,通过建立神经网络模型,从地震记录反演波阻抗的整个过程。

完整代码

  1. import torch.nn as nn
  2. import torch.autograd
  3. from torch.autograd import Variable
  4. import scipy.io as sio
  5. import matplotlib.pyplot as plt
  6. %matplotlib inline
  7. %config InlineBackend.figure_format = 'svg'
  8. import numpy as np
  9. from random import randint
  10. #******************导入数据*********************
  11. dataframe = sio.loadmat('Train_DataSyn_Ricker30.mat')
  12. #从文件中分别提取提取地震道与波阻抗数据
  13. Seismic_data = dataframe['Seismic'] #地震道
  14. Impedance_data = dataframe['Impedance']/1e6 #波阻抗
  15. #随机抽取部分道,作为训练集
  16. howMany = 2020
  17. np.random.seed(9) #随机种子,便于复现
  18. indxRand = [randint(0,dataframe['Seismic'].shape[1]-1) for p in range(0,howMany)] #随机索引
  19. #地震道
  20. Seismic_data = Seismic_data.transpose() #转置
  21. Seismic_data = Seismic_data[indxRand,:] #通过索引抽取
  22. #波阻抗
  23. Impedance_data = Impedance_data.transpose()
  24. Impedance_data = Impedance_data[indxRand,:]
  25. dt = 4.3875e-4
  26. time = np.linspace(0,(Seismic_data.shape[1]-1)*dt,Seismic_data.shape[1])
  27. #*********************分割数据集****************************
  28. #其中验证集500个,测试集1000个,剩余(520)为训练集
  29. howManyToValidate = 500
  30. howManyToTest = 1000
  31. #对输入Seismic与标签Imp进行相同的索引与处理
  32. #用numpy索引切片的方式进行划分
  33. valX = (Seismic_data[:howManyToValidate,:])
  34. testX = (Seismic_data[howManyToValidate:howManyToValidate+howManyToTest,:])
  35. trainX = (Seismic_data[howManyToValidate+howManyToTest:,:])
  36. valImp = (Impedance_data[:howManyToValidate,:])
  37. testImp = (Impedance_data[howManyToValidate:howManyToValidate+howManyToTest,:])
  38. trainImp = (Impedance_data[howManyToValidate+howManyToTest:,:])
  39. #转为torch中的Tensor格式
  40. #此时数据为(道数,采样点数)的二维数组,按照torch的输入格式整理为(道数,数据高度,数据长度),便于后续输入道CNN网络中
  41. valX = torch.FloatTensor(np.reshape(valX, (valX.shape[0], 1, valX.shape[1])))
  42. testX = torch.FloatTensor(np.reshape(testX, (testX.shape[0], 1, testX.shape[1])))
  43. trainX = torch.FloatTensor(np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1])))
  44. valImp = torch.FloatTensor(np.reshape(valImp, (valImp.shape[0], 1, valImp.shape[1])))
  45. testImp = torch.FloatTensor(np.reshape(testImp, (testImp.shape[0], 1, testImp.shape[1])))
  46. trainImp = torch.FloatTensor(np.reshape(trainImp, (trainImp.shape[0], 1, trainImp.shape[1])))
  47. #********************建模*********************
  48. noOfNeurons = 60 #定义卷积核个数
  49. dilation = 1
  50. kernel_size = 300 #卷积核尺寸
  51. stride = 1 #卷积核滑动步长
  52. padding = int(((dilation*(kernel_size-1)-1)/stride-1)/2) #0填充个数
  53. class CNN(nn.Module):
  54. def __init__(self): #构造函数
  55. super(CNN, self).__init__() #前面三行为固定格式
  56. self.layer1 = nn.Sequential( #nn.Sequential为一个顺序的容器
  57. #Conv1d的前两个参数分别表示输入通道数与输出通道数,又有卷积核个数=卷积层输出通道数
  58. nn.Conv1d(1, noOfNeurons, kernel_size=kernel_size, stride=1, padding = padding+1),#卷积层
  59. nn.ReLU()) #ReLu激活函数
  60. self.layer2 = nn.Sequential(
  61. nn.Conv1d(noOfNeurons, 1, kernel_size=kernel_size, stride=1, padding = padding+2),
  62. nn.ReLU())
  63. def forward(self, x): #在forward中将网络像搭积木一样连接起来
  64. out = self.layer1(x)
  65. out = self.layer2(out)
  66. return out
  67. cnn = CNN() #实例对象
  68. #*************************训练************************
  69. #定义与训练有关的超参数
  70. num_epochs = 500 #迭代轮数
  71. batch_size = 1 #批次大小
  72. learning_rate = 0.001 #学习率
  73. batch_size_tot = trainX.shape[0]
  74. no_of_batches = int((batch_size_tot - batch_size_tot%batch_size)/batch_size) #总批数
  75. loss_fn = nn.MSELoss() #损失函数,此处为一个回归任务,采用均方根误差作为损失值
  76. optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate) #优化器选择为Adam
  77. for epoch in range(num_epochs): #开始迭代
  78. for ii in range(no_of_batches):
  79. #地震道数据
  80. #通过手动索引的方式建立batch
  81. #使用Variable对Tensor进行封装,便于改变Tensor的.data、.grad、.grad_fn属性
  82. traces = Variable(trainX[ii*batch_size:(ii+1)*batch_size,:,:])
  83. imp_label = Variable(trainImp[ii*batch_size:(ii+1)*batch_size,:,:])
  84. '''以下5行代码为固定格式,几乎所有pytorch网络都是同样的'''
  85. outputs = cnn(traces) #将训练数据输入道cnn模型中,前向传播
  86. loss = loss_fn(outputs, imp_label) #计算损失
  87. optimizer.zero_grad() #每一批次计算完成后梯度清零
  88. loss.backward() #反向传播
  89. optimizer.step() #梯度更新
  90. #然后在每一批次训练完成后,用交叉验证集检验
  91. traces_val = Variable(valX)
  92. outputs_val = cnn(traces_val)
  93. imp_val = Variable(valImp)
  94. loss_val = loss_fn(outputs_val, imp_val)
  95. #打印
  96. print ('Epoch [%d/%d], Iter [%d], Train Loss: %.6f, Validation Loss: %.6f'
  97. %(epoch+1, num_epochs, ii+1, loss.data.cpu().numpy(), loss_val.data.cpu().numpy()))
  98. #**********************测试集可视化对比**************************
  99. #取出4道
  100. sampleNumbers = np.array([21,50,162,206])
  101. fig, axs = plt.subplots(1, 4, sharey=True)
  102. axs[0].invert_yaxis()
  103. fig.suptitle('Samples of Testing Data Predictions')
  104. for i in range(4):
  105. sampleNumber = sampleNumbers[i];
  106. TestingSetSeismicTrace = Variable(testX[sampleNumber:sampleNumber+1,:,:])
  107. CNN_ImpedancePrediction = cnn(TestingSetSeismicTrace)
  108. #Numpy数据作图用
  109. TestingSetSeismicTrace = testX[sampleNumber,:].numpy().flatten()
  110. TestingSetImpedanceTrace = testImp[sampleNumber,:].numpy().flatten()
  111. CNN_ImpedancePrediction = CNN_ImpedancePrediction.data.cpu().numpy().flatten()
  112. line1, = axs[i].plot(TestingSetImpedanceTrace, time, 'r-')
  113. axs[i].set_xlabel('Impedance')
  114. if i==0:
  115. axs[i].set_ylabel('Time(s)')
  116. line2, = axs[i].plot(CNN_ImpedancePrediction, time, 'k--')
  117. lgd = plt.legend((line1, line2), ('True Impedance', 'CNN Impedance'), bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
  118. #********************模型保存&加载*********************
  119. #保存模型
  120. with open('cnn.pkl', 'wb') as pickle_file:
  121. torch.save(cnn.state_dict(), pickle_file)
  122. #加载模型
  123. #加载时需要先实例化对象
  124. cnn_new = CNN()
  125. with open('cnn.pkl', 'rb') as pickle_file:
  126. cnn_new.load_state_dict(torch.load(pickle_file))
  127. #**********************应用************************
  128. Appdataframe = sio.loadmat('HardTest_DataSyn_Ricker30.mat')
  129. AppSeismic = Appdataframe['Seismic']
  130. AppSeismic = AppSeismic.transpose()
  131. sampleNumber = 25
  132. #抽取应用数据的地震道
  133. AppSeismicTrace = AppSeismic[sampleNumber,:]
  134. #Numpy.array-->Tensor-->Variable
  135. AppSeismicTraceTorch = torch.FloatTensor(np.reshape(AppSeismicTrace, (1,1, AppSeismicTrace.shape[0]))) #输入尺寸与训练集保持一致,第一个1表示应用当前单个样本
  136. AppSeismicTraceTorch = Variable(AppSeismicTraceTorch) #封装成Variable
  137. #用加载的cnn_new模型去预测
  138. CNN_ImpedancePrediction = cnn_new(AppSeismicTraceTorch)
  139. #作图
  140. fig, ax1 = plt.subplots()
  141. ax1.plot(time, AppSeismicTrace, 'b-')
  142. ax1.set_xlabel('time (s)')
  143. ax1.set_ylabel('Seismic Amplitude', color='b')
  144. ax1.tick_params('y', colors='b')
  145. ax2 = ax1.twinx()
  146. ax2.plot(time, CNN_ImpedancePrediction.detach().numpy().flatten(), 'r-')
  147. ax2.set_ylabel('Impedance', color='r')
  148. ax2.tick_params('y', colors='r')
  149. fig.tight_layout()
  150. plt.show()

数据与源码CNN_based_impedance_inversion/Challenge_testing_Facies_variograms at master · vishaldas/CNN_based_impedance_inversion (github.com)

引用文献

[1] Vishal Das;Ahinoam Pollack;Uri Wollner;Tapan Mukerji.Convolutional neural network for seismic impedance inversion[J].Geophysics,2019,Vol.84(6): R869-R880

[2]王治强. 稀疏脉冲反褶积及其波阻抗反演研究[D].中国石油大学(北京),2018.DOI:10.27643/d.cnki.gsybu.2018.001091.

[3] Activation and loss functions (part 1) · Deep Learning (atcold.github.io)

[4] https://www.w3cschool.cn/article/78828381.html

Pytorch实现波阻抗反演的更多相关文章

  1. PyTorch官方中文文档:torch.nn

    torch.nn Parameters class torch.nn.Parameter() 艾伯特(http://www.aibbt.com/)国内第一家人工智能门户,微信公众号:aibbtcom ...

  2. [PyTorch]PyTorch/python常用语法/常见坑点

    目录 1. make_grid() 2. join与os.path.join() 3. 读文件写文件 4. json操作 5. tensorboard使用 6. python shutil.move ...

  3. hdu1695 GCD(莫比乌斯反演)

    题意:求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d). 知识点: 莫比乌斯反演/*12*/ 线性筛求莫比乌 ...

  4. BZOJ 2154: Crash的数字表格 [莫比乌斯反演]

    2154: Crash的数字表格 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 2924  Solved: 1091[Submit][Status][ ...

  5. BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status] ...

  6. BZOJ 2820: YY的GCD [莫比乌斯反演]【学习笔记】

    2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1624  Solved: 853[Submit][Status][Discu ...

  7. BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 4032  Solved: 1817[Submit] ...

  8. Bzoj2154 Crash的数字表格 乘法逆元+莫比乌斯反演(TLE)

    题意:求sigma{lcm(i,j)},1<=i<=n,1<=j<=m 不妨令n<=m 首先把lcm(i,j)转成i*j/gcd(i,j) 正解不会...总之最后化出来的 ...

  9. 莫比乌斯函数筛法 & 莫比乌斯反演

    模板: int p[MAXN],pcnt=0,mu[MAXN]; bool notp[MAXN]; void shai(int n){ mu[1]=1; for(int i=2;i<=n;++i ...

随机推荐

  1. 使用 LOAD DATA LOCAL INFILE,sysbench 导数速度提升30%

    1. LOAD DATA INFILE 为什么比 INSERT 快? 2. sysbench 压测 MySQL 的四个标准步骤. 3. 怎么让 sysbench 支持 LOAD DATA LOCAL ...

  2. C++五子棋(六&七)——游戏结束

    规则原理 如图 判断游戏结束 chessData.h //row,col 表示当前落子 bool checkWin(ChessData* game, int row, int col); 横.竖.斜( ...

  3. Codeforeces 13B

    计算几何二维基础

  4. gin框架使用【4.请求参数】

    GET url: http://127.0.0.1:8080/users?id=1&name=卷毛狒狒 package mainimport ( "github.com/gin-go ...

  5. JAVA语言学习day16--7月22日

    ###15用户选择功能 * A: 用户选择功能 * a: 案例代码 import java.util.ArrayList; import java.util.Scanner; /* * 超市管理系统主 ...

  6. 2021.08.01 P4311 数字序列(左偏树)

    2021.08.01 P4311 数字序列(左偏树) [P4331 BalticOI 2004]Sequence 数字序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1 ...

  7. 2021.07.17 P4170 染色(区间DP)

    2021.07.17 P4170 染色(区间DP) [P4170 CQOI2007]涂色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 重点: 1.目标状态可以由哪些状态转移过来. ...

  8. ABP框架入门

    技术要求 在开始使用 ABP 框架之前,您需要在计算机上安装一些工具. IDE/编辑器 本书假设您使用的是Visual Studio 2022(支持 .NET 6.0 的 v10.0)或更高版本.如果 ...

  9. Go学习-基本语法(一)

    前言 一直对Service Mesh相关内容比较感兴趣,后面一路学习了Dcoker.Kubernetes等相关内容,可以说是对基本概念和使用有一定了解,随着开始学习一些相关的组件的时候,发现基本上全部 ...

  10. 【译】defer-panic-and-recover

    Go 有通用的控制流程:if,for,switch,goto.它也有go语句用于让代码运行在单独的协程.这里我将讨论一些不常见的问题:defer,panic 和 recover. defer语句将函数 ...