周报(8.5-8.12)

周报(8.5-8.12)

本周工作

犯傻分享

标准化值域和激活函数值域不符

我之前在复现InversionNet网络代码的过程中,因为我的设备内存不足,所以重写了Dataset类,实现分段加载数据来缓解内存压力。在写数据处理部分的代码时,为了模型更好的拟合,我是用了我更熟悉的标准化对数据进行了处理。标准化的公式为:
Z = X − μ σ Z = \frac{X-μ}{σ} Z=σXμ
其中 μ μ μ是原始数据的均值, σ σ σ是原始数据的标准差。经过公式处理之后, Z Z Z是一个均值为0,标准差为1的量,那么速度模型的值域就较为平均落到了横轴的附近,能够满足模型训练和预测中需要。

在这里插入图片描述

但在实际经过训练InversionNet之后,我发现我的模型收敛的较早,性能也离师兄师姐训练出来的模型还有一段差距,找了好一会原因,最后发现是InversionNet模型最后的Tanh激活函数的问题。

在这里插入图片描述

因为Tanh是一个值域为[-1, 1]的函数,把Tanh放到最后的模型只能拟合[-1, 1]的结果。但是数据经标准差后只能保证约68%的大部分数据落到[-1, 1]的区间内,还有部分数据会超过这个范围,这些超出[-1, 1]范围的数据是无法被网络拟合的,所以训练到最后模型里最佳结果会有一段无法缩小的距离。

师兄的DD-Net里的示例代码是对数据进行了归一化的处理,公式为:
Z = X − X m i n X m a x − X m i n Z = \frac{X-X_{min}}{X_{max}-X_{min}} Z=XmaxXminXXmin
归一化操作的值域就一定能落在[-1, 1]之间,也能被Tanh拟合。但是标准化仍然有着一定优势,如数据
[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 20 ] [1, 2, 3, 4, 5, 6, 7, 8, 9, 20] [1,2,3,4,5,6,7,8,9,20]
平均值为6.5。

归一化后数据为
[ 0 , 0.0526 , 0.1053 , 0.1579 , 0.2105 , 0.2632 , 0.3158 , 0.3684 , 0.4211 , 1 ] [0, 0.0526, 0.1053, 0.1579, 0.2105,0.2632, 0.3158, 0.3684, 0.4211, 1] [0,0.0526,0.1053,0.1579,0.2105,0.2632,0.3158,0.3684,0.4211,1]
归一化后平均值为0.2895,有9个数据落入了以0.5为分界线的前半个区间,前9个数据的标准差为0.1359,最后数据离平均点的距离为0.7105。

标准化后数据为
[ − 1.0735 , − 0.8783 , − 0.6831 , − 0.4880 , − 0.2928 , − 0.0976 , 0.0976 , 0.2928 , 0.4880 , 2.6349 ] [-1.0735, -0.8783, -0.6831, -0.4880, -0.2928, -0.0976, 0.0976, 0.2928, 0.4880, 2.6349] [1.0735,0.8783,0.6831,0.4880,0.2928,0.0976,0.0976,0.2928,0.4880,2.6349]
标准化后有6个数据落入了以0为分界线的前半个区间,前9个数据的标准差为0.5040,最后数据离平均点的距离为2.6349。

上述数据可以这样理解:

  1. 在20这个离群点的作用下,前9个数据在归一化中被压缩的很近,丧失了区分度。

    如果使用标准差,前9个数据虽然也被压缩了,但是程度远没有归一化那么大(0.1359与0.5040)。

    结论是数据更能保存自己的特征。

  2. 看最后一个元素,受限于[-1, 1]的值域空间,归一化中离群点离平均点的距离为0.7105,而最小元素离平均点的距离为0.2895,约等于原始数据到平均点的距离的比例:[5.5: 13.5]。

    但如果使用了标准差,最大元素和最小元素到平均值点的距离为[1.0735: 2.6349],这个比例实际上大于了原始的比例。

    结论是标准差更能体现不同值到平均点的距离关系。

综上所述,使用标准差处理的数据更具区分度,距离越远的元素标准差后距离会更远,这两点都有利于网络的训练,标准化也有缩放数据的功能。但需要注意的是标准差的值域不止[-1, 1],不能用tanh。

显存爆炸

在训练过程中,从训练InversionNet到FCNVMB的过程中,保持原有的batch_size后训练时报出out of memery的问题。为了节省显存,我对pytorch的显存占用机制进行了探索。

探索显存占用

工具:Pytorch-Memory-Utils:https://github.com/Oldpan/Pytorch-Memory-Utils/

测试:训练使用FlatVel_A、batch_size为10的FCNVMB修改版网络

测试结果:

在这里插入图片描述

  1. 0-110.6的增长是加载模型的内存占用。

  2. 110.6-124.0的增长是加载地层数据。

  3. 124.0-124.2的增长是加载速度模型数据。

  4. 124.2-1905.2的增长是训练过程中产生的梯度数据。

  5. 1979.2-1905.2的差值是残差连接和其他临时数据。

  6. 1905.2-124.3的差值是loss.backward()后被删除的梯度数据。

  7. 124.3-456.1是optimizer.step()后产生的数据。

  8. 456.1-456.1是重新读取新的数据时的数据。

  9. 456.1-345.5是optimizer.zero_grad()后减少的数据。

同时之后每次读取数据后,内存占用也为456.1。

显存占用的结论
  1. 由上文1-3步得知,模型及数据集共计占用124.2Mb,只占显存最高占用中很少的一部分。
  2. 由上文第4步得知,占用显存最大的一部分为模型前向计算时pytorch自动计算的用于反向传播的梯度数据。
  3. 由上文第5步得知,跳跃连接/残差连接保留的特征图像会占用极少一部分显存,基本不需要担心跳跃连接本身产生的显存问题,但跳跃连接仍可能产生更多的梯度?这里需要进一步验证。
  4. 在loss.backward()反向传播后梯度显存被释放。
  5. 7-9步,优化器会占用一部分显存,暂时不了解这部分显存用于何种用途。
减少显存的方法
  1. 由结论3可得,使用del及时删除不再使用的变量,如残差连接中的梯度等。

  2. 由结论2可得,要想降低前向计算时产生的梯度数据,要么调整模型本身,要么减小batch_size。但很多时候我们无法减少模型复杂度,只能调低batch_size。

  3. 同样由结论2得知,pytorch可以使用with torch.no_grad()来避免梯度的计算。停止计算梯度,可以用于验证集loss的计算,加快运行速度,减少显存占用,但不能用于训练过程,包括pad,剪裁图片仍然改变了输入输出,过程中会产生梯度变化,因此这个过程中也不能使用直接赋值的方式进行剪裁,这种方式仍然会丢失梯度。

    torch.no_grad()与model.eval()

    torch.no_grad(): 停止梯度计算

    model.eval():使模型停用dropout、bn等操作

使用更好的函数

在进行数据处理时,部分操作的速度过慢,部分操作出现报错,经查,是由于一下问题导致的:

  1. 在读取OpenFWI时使用的是numpy数据结构,训练时使用的是Tensor数据结构。Tensor(list(ndarryObject1, ndarryObject2))非常慢,使用Tensor(list(float1, float2))会报错,改用Tensor.from_numpy(numpy(list(ndarryObject1, ndarryObject2)))可以大大加快转换速度。
  2. Tensor(ndarryObject)会造成数据复制,造成双倍内存占用,减慢运行效率。Tensor.from_numpy(ndarryObject)是就地操作,Tensor会共用numpy数据结构内的原始数据。

正演学习

学习了地震正演技术,但仍需加强学习

上周已得到的用于正演的二维声波方程:
1 v 2 ∂ 2 U ∂ t 2 = ∂ 2 U ∂ x 2 + ∂ 2 U ∂ z 2 \frac{1}{v^2}\frac{∂^2U}{∂t^2}=\frac{∂^2U}{∂x^2}+\frac{∂^2U}{∂z^2} v21t22U=x22U+z22U

我们需要对该过程进行二维差分,二维差分相当于获取周围点的信息,并将连续的公式离散化,获得以下公式
1 v 2 U k + 1 − 2 U k + U k − 1 Δ t 2 = U i + 1 , j k − 2 U i , j k + U i − 1 , j k Δ x 2 + U i + 1 , j k − 2 U i , j k + U i − 1 , j k Δ z 2 + \frac{1}{v^2} \frac{U^{k+1}−2U^k+U^{k−1}}{Δt^2}= \frac{U_{i+1,j}^k−2U_{i,j}^k+U_{i−1,j}^k}{Δx^2}+ \frac{U_{i+1,j}^k−2U_{i,j}^k+U_{i−1,j}^k}{Δz^2}+ v21Δt2Uk+12Uk+Uk1=Δx2Ui+1,jk2Ui,jk+Ui1,jk+Δz2Ui+1,jk2Ui,jk+Ui1,jk+
其中,k表示时间序列,我们可以在已知k和k-1时间序列的情况下求出k+1的波动情况,进而模拟波的传播。

下周任务

  1. 选择具体方向,开展研究。
  2. 继续学习地震正演原理,数学原理。
  3. 继续学习地震反演原理,深度学习原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值