keras神经网络做简单的回归问题

咸鱼了半个多月了,要干点正经事了。

最近在帮老师用神经网络做多变量非线性的回归问题,没有什么心得,但是也要写个博文当个日记。

该回归问题是四个输入,一个输出。自己并不清楚这几个变量有什么关系,因为是跟遥感相关的,就瞎做呗。

  • 数据预处理的选择

刚开始选取了最大最小值的预处理方法,调了很久的模型但是最后模型的输出基本不变。

换了z-score的预处理方法,模型的输出才趋于正常。

  • 损失函数的选择

对于回归问题,常用的损失函数有三种,一个是平方误差函数,一个是绝对值误差函数,还有一个是交叉熵函数。

在其他参数都不变的时候分别采用这三个损失函数:

1.交叉熵

2.绝对值误差函数

3.平方误差函数

结论:从上面三个图中国可以看出,相同条件下,绝对值误差函数得到的效果好一些。

  • batch_size大小的选择

bach_size = 32

bach_size = 64

bach_size = 128

batch_size = 256

在两个不同的batch_size下,网络最后的loss值都差不多,但是在验证集上,当batch_size = 64/128时,loss曲线比较稳定。

结论:一定范围内,batch_size越大,其确定的下降方向就越准,引起训练震荡越小.随着batch_size增大,处理相同的数据量的速度越快。但是随着batchsize增大,达到相同精度所需要的epoch数量越来越多。过大的batch_size的结果是网络很容易收敛到一些不好的局部最优点。同样太小的batch_size会使得训练速度很慢,训练不容易收敛。

  • 是否添Dropout层

不加dropout层

加了Dropout层

加了Dropout层后模型的loss值反而升高,但是测试集上的loss下降能平稳一些。

  •  深层网络和浅层网络的选择

我自己觉得这样一个简单的问题其实浅层网络就能解决,但是老师想搭一下深度学习的车,没办法只能用比较一下两个模型。

含有一个隐层的全连接网络,64个神经元,最后模型的loss值为:0.1032

含有两个隐层的全连接网络,第一层32个神经元,第二层16个神经元,最后的loss值为0.0995

含有三个隐层的全连接网络,第一层32个神经元,第二层16个神经元,第三层8个神经元,最后模型的loss值为0.0986

含有四个隐层的全连接网络,第一层32个神经元,第二层16个神经元,第三层8个神经元,第四层4个神经元,最后模型的loss值为0.0993

含有五个隐层的全连接网络,第一层32个神经元,第二层16个神经元,第三层8个神经元,第四层4个神经元,第五层2个神经元,最后模型的loss值为0.0991

含有五个隐层的全连接网络,第一层32个神经元,第二层16个神经元,第三层8个神经元,第四层4个神经元,第五层2个神经元,第六层2个神经元,最后模型的loss值为0.0988

........

结论:在一定范围内,随着网络层的加深,模型的准确率升高。超过一定范围,随着网络层的加深,模型的准确率不但不升反而下降,测试集上的准确率也会下降,所以这并不是出现了过拟合。

  • 模型宽度的选择

由于上一个实验中三层模型的loss值最低,所以我选择三层模型来做这个对于模型宽度选择的实验。

1、含有三个隐层的全连接网络,第一层32个神经元,第二层16个神经元,第三层8个神经元,最后模型的loss值为0.0986

2、含有三个隐层的全连接网络,第一层32个神经元,第二层32个神经元,第三层16个神经元,最后模型的loss值为0.0986

3、含有三个隐层的全连接网络,第一层32个神经元,第二层32个神经元,第三层32个神经元,最后模型的loss值为0.0960

4、含有三个隐层的全连接网络,第一层32个神经元,第二层64个神经元,第三层32个神经元,最后模型的loss值为0.0967

5、含有三个隐层的全连接网络,第一层32个神经元,第二层64个神经元,第三层64个神经元,最后模型的loss值为0.0967

结论:在一定范围内,网络模型越宽,模型的准确率越高,但是超过某一阈值后,模型的准确率不再提高,测试集上loss下降震荡越来越明显,说明模型的复杂度已经高于回归问题真是模型的复杂度。

  • 尝试残差网络

第一种残差网络:

def identity_block(x):
        out = Dense(32)(x)
        #out = BatchNormalization()(out)
        out = Activation('tanh')(out)
        #out = Dropout(0.1)(out)
        out = Dense(32)(x)
        #out = Dropout(0.1)(out)
        #out = BatchNormalization()(out)
        out = Activation('tanh')(out)

        out = Dense(4)(out)
        #out = BatchNormalization()(out)

        out = merge([out,x],mode='sum')
        out = Activation('tanh')(out)
        return out

  

 

结论:和全连接网络相比,残差网络loss下降很快,测试集上loss下降曲线很平滑,但是模型的准确率却不如普通三层的全连接网络,最终的loss值为0.1021。

第二种残差网络:

def fc_block(x):
        out = Dense(32)(x)
        out = Activation('tanh')(out)
        out = Dense(32)(x)
        out = Dropout(0.1)(out)
        out = Activation('tanh')(out)
        out = Dense(32)(out)

        x = Dense(32)(x)

        out = merge([out, x], mode = 'sum')
        out = Activation('tanh')(out)
        return out

  

结论:第二种残差网络的loss值为0.1016,比第一种残差网络的效果能好一点。在ResNet中,这两个模块是交替使用的。

将两个模块叠加之后,模型的准确率并没有提升,应该是模型过度复杂了,最后模型的loss值为0.1027。

  •  relu还是tanh

由于输出值的范围是[-1, 1],因此模型的输出层的激活函数只能选择tanh。

在隐藏层中,可以选择relu和tanh作为隐藏层的激活函数。

模型结构为3层,神经元分别是32,32,32。就是上一个步骤中loss最低的网络结构,在上一个步骤中隐层的激活层使用的是tanh,loss值为0.0960

将tanh换成relu:

采用relu作为激活函数,模型的计算速度会加快,因为求导很简单。在这个问题只使用relu会使模型的准确率下降。一般在复杂的模型中使用relu比较多。

原文地址:https://www.cnblogs.com/catpainter/p/8891091.html