“心中有歌,到处都是舞台”。
自从投入了自编码的深度学习研究后,一路走来就是磕磕碰碰。
上一篇将地震信号用在了自编码卷积神经网络降噪(见《地震去噪新探索——无监督卷积神经网络实战》),结果那叫一个惨。如下面的图示,上边是噪声图,下边是去噪图:
从去噪效果来看,仅能获取到一些支离破碎的有效信号,这是一张完全拿不出手的效果图。
01屡败屡战的调优之旅
卷积神经网络不是更能学习到特征细节,性能更好吗?为啥我做出来的效果如此之惨?
前期的参数设置包括:使用10000个28*28的训练小块,训练epoch:5,学习率:0.001,优化器:tf.train.AdamOptimizer(learn).minimize(cost),LOSS函数:tf.nn.sigmoid_cross_entropy_with_logits(labels=targets_, logits=logits_),cost = tf.reduce_mean(loss)
网络结构图为:
训练损失曲线:
1.归一化的优化
惨不忍睹的LOSS训练结果引起了我的注意。将收敛失败这个问题拿到网上去寻找答案,有大神说这是归一化没做好。
那就先进行2项优化:
一是控制训练样本的取值范围到(-1,1),使用方法是原值除以最大值的方法,就像这样:
noisy_imgs=noisy_imgs/abs(noisy_imgs).max()
二是在训练网络的每个卷积后增加BN,就像这样:
conv1 = tf.layers.conv2d(inputs_, 64, (3,3), padding='same', activation=tf.nn.relu)
conv1 = tf.layers.batch_normalization(conv1, training=True)
再进行训练,效果不明显,还是没有收敛。
另外,很多归一化的方法是将取值范围集中在(0,1),使用这样的算法:
imgs= (imgs-imgs.min())/(imgs.max()-imgs.min())#归一化到[0,1]
结果证明对于地震数据完全没法训练,曲线是这样的:
2.学习函数的调整
“一计不成,再生一计”。
我想到了对优化器和LOSS函数进行改动。
在神经网络学习中,损失函数的作用是度量神经网络的输出的预测值,计算与实际值之间的差距,可以说是实现学习的关键函数。常见的损失函数包括:最小二乘损失函数、交叉熵损失函数、回归中使用的smooth L1损失函数等。
而优化函数的原理是:把损失值从神经网络的最外层传递到最前面,实现反向传播学习,这是神经网络实现持续学习达到收敛的关键。如最基础的梯度下降算法包括:随机梯度下降算法,批量梯度下降算法,带动量的梯度下降算法,Adagrad,Adadelta,Adam等。
那我就先从优化器函数入手吧。
既然学习率为0.001无法收敛,那试试0.0001呢。结果还真收敛了,如下图:
那预测效果如何呢?结果是一塌糊涂,连基本特征都学习不到,如下图:
这是怎么回事呢?我的理解是学习率太高,就会让神经网络学习到更细粒度的特征,而失去了我们想要的特征。就相当于研究一个人的特征,我们通常是从五官、体型等方面来看,但如果从细胞的角度的去学习,那就无法还原人的外貌特征了。
另外,设置为0.0005也好不了多少。
那改动LOSS函数能不能起作用呢?
比如改为softmax_cross_entropy_with_logits,像这样:
loss = tf.nn.softmax_cross_entropy_with_logits(labels=targets_, logits=logits_)
结果是无法学习,如下图:
3.其它的尝试
两板斧过去,还没有看到变好的迹象。我没有放弃,我开始思考为啥原程序训练Mnist效果都如此好,换到地震数据训练就不行了呢?
我想到了训练样本数据是不是有问题。我又进行了以下尝试:
一是调整训练样本数据的尺寸:有128*128,40*40,32*32,28*28等。
二是对样本数据进行截断:地震数据不是异常值多,偏离度大吗。我就筛选数据集中的90%区间,区间外面的进行截断,再进行归一化。这样数据分布就均匀多了。
三是扩充采样数据来源,从不同的数据源采样。是不是数据更丰富,训练效果就会改观呢?
……
你可以想象做这些实验有多么琐碎和繁杂,然而现实却是如此的无情。最后结局都是一个——失败,根本拿不出一个像样的效果,连一个较为清晰的结果都没有。
02 柳暗花明,找到了一个方法
“山穷水复疑无路,柳暗花明又一村”。
在持续N天被现实按在地上摩擦后,我痛定思痛:到底解决的方向在哪里?
在现有这个无可救药的神经网络中,提高学习率可以收敛,但是无法学习到有效特征。降低学习率可以学习到有效特征但是无法收敛,也就是说无法持续优化的学习。整个成了一个悖论。
面对这张丑陋的预测结果图,我意识到可能是网络结构本身出了问题。很有可能是网络对图片数据学习有效,对地震数据学习就是不行。
在翻阅了其它研究者的论文后,我逐步聚焦到了一个结构——解码。我的程序在这部分是使用卷积核上采样的结构。像这样:
conv4 = tf.image.resize_nearest_neighbor(conv3, (8,8))
conv4 = tf.layers.conv2d(conv4, 32, (3,3), padding='same', activation=tf.nn.relu)
而其它地震论文结构却包含了一个我没有的结构——反卷积。
如果我也使用反卷积,甚至就只有卷积和反卷积这种最简单的自编码结构,效果如何呢?像这样的结构:
x = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
x = Conv2DTranspose(32, (3,3), padding='same', activation='relu', kernel_initializer='glorot_normal')(x)#反卷积
x = Conv2DTranspose(32, (3,3), padding='same', activation='relu', kernel_initializer='glorot_normal')(x)
decoded = Conv2DTranspose(1, (1,1), padding='same', activation='tanh', kernel_initializer='glorot_normal')(x)
结果是令人惊艳的。下图是收敛的效果,很快就能够收敛:
训练的效果更好。以下分别是原图,噪声图和去噪效果图:
可以看到,上面噪声几乎淹没了有效信号。然后通过训练,仅仅5个迭代,就较好的分离出了有效信号。
03 下一步计划
“既然选择了远方 便只顾风雨兼程”。
看来反卷积是是解决地震学习的一把钥匙。下一步我将研究反卷积能适应地震处理的原因,然后继续进行优化和创新,并使用其它算法做对比实验,争取做出更好的效果。
如果喜欢请点“赞”,如果小伙伴对程序感兴趣,可以联系我获取。