波士顿房价-pytorch神经网络-5折5次交叉验证

举报
Yin-Manny 发表于 2021/11/22 16:24:21 2021/11/22
【摘要】 使用pytorch搭建神经网络回归模型,分析如下: (1)描述所使用的神经网络模型; (2)描述训练模型所使用的算法; (3)描述模型超参数(如神经网络模型结构对应的参数)确定的过程,分析模型训练结果,包括五次5折交叉验证及其结果、模型训练过程相应误差的变化情况等; (4)总结模型训练过程中的收获。
  • 神经网络回归模型:
    • 描述所使用的神经网络模型:
  • 我们所搭建的神经网络包括一层输入层,一层隐藏层,一层输出层。输入层输入维度为92,因为对特征进行了多项式处理,输出维度为hidden_size = 67;隐藏层输入维度为67,输出维度为67;输出层输入维度为67,输出维度为1。形状大概如下左图,代码如下右图:

1.png2.png

  • 对于激活函数,我们小组分别测试了Relu函数,tanh函数,sigmoid函数等激活函数,最终确定了Relu函数作为神经网络的激活函数。正是由于Relu具备引导适度稀疏的能力,Relu的使用,使得网络可以自行引入稀疏性,同时大大地提高了训练速度。因此它具有很好的效果。
  • 对于损失函数,神经网路模型在训练时,需要有一个指标来评价此时的神经网络的效果是否良好,从而调节参数使得拟合的效果更好。我们小组经过查找文档和分析,最终选择了平均绝对误差(MAE Mean Absolute Error)来作为损失函数。下面给出了MAE的计算公式:

3.png

选择MAE作为LOSS函数的原因:MAE是评价神经网络的经典指标,能够很好的给出模型的优劣。本题训练的模型最终使用MAPE来进行评价,所以在训练模型时使用MAE作为评价指标能够更好地使模型最终的MAPE更小。

  • 描述训练模型使用的算法:

优化器是神经网络在训练过程中不可或缺的,用来对模型进行修正从而达到使误差下降的目的。优化器的选择同样尤为重要,好的优化器能让模型的误差明显减小。我们小组一开始选择了随机梯度下降法(SGD)作为优化算法。但经过实验和讨论,我们小组一致认为,由于给出的数据样本规模小,且SGD难以解决跳出局部最优解的问题,所以SGD并不是最好的优化算法。

通过在查找文档和资料,我们决定选择Adam(Adaptive Moment Estimation)作为优化算法。在了解Adam之前,我们先学习了两种不同的算法:

  • 自适应梯度算法(AdaGrad)维护一个参数的学习速率,即不先给定学习率,而是根据模型的训练效果来更改学习率。传统的优化算法要么将学习率设置为常数,要么根据训练次数来更新学习率。而AdaGrad算法对于不同数量的类别数据会给出不同的学习率,对于多的类别数据,该算法给出越来越小的学习率,但对于少量的数据,会给出较大的学习率。下面给出AdaGrad的公式:

4.png

  • 动量优化算法:动量优化算法是在梯度下降算法的基础上做的改变,通过引入一个记录了历史梯度的信息动量来加速梯度下降的速度,同时往标准动量里加入了一个校正因子。因此这种算法的下降速度和下降方向会比梯度下降算法快且好。下面给出牛顿加速梯度(NAG)的公式:

5.png 

而我们小组使用的Adam优化算法融合了上述两种算法的优点,不仅仅使用了动量来加速下降的速度,并且并入了梯度一阶矩的估计,使其包括了偏置修正。Adam从梯度的第一次和第二次矩的预算来计算不同参数的自适应学习速率。下面给出Adam的算法策略:

6.png

  • 分析:
  • 确定模型的隐层层数:

我们把我们的数据集按照82的比例分成训练集和测试集,在固定隐层神经元个数hidden_size = 64的情况下,在训练集上训练模型,在测试集上求MAPE。比较不同隐层数的MAPE大小,最终确定了对于我们这么小的数据集,单隐层使最好的隐层数,也能防止模型太复杂导致过拟合。

  • 确定单隐层hidden_size的大小:

我们把我们的数据集按照82的比例分成训练集和测试集,在训练集上训练模型,在测试集上求MAPE。尝试了hidden_size=14-18, hidden_size=30-34, hidden_size=59-67, hidden_size=124-130, hidden_size=252-260和一些零碎的超参数后,确定了hidden_size超参数为67时是相对来说最佳的单隐层神经元个数。部分过程如下图:

hidden_size=63

7.png 

hidden_size=64

8.png

hidden_size=65

9.png

hidden_size=66

10.png

hidden_size=67 

11.png 

  • 当我们把数据集按照82的比例分成训练集和测试集,在训练集上训练模型,在测试集上求MAPE。相应模型误差的变化情况大致如下:

12.png

13.png

14.png

  • 五折五次交叉验证:

我们使用RepeatedKFold(n_splits=5, n_repeats=5, random_state=2652124)实现55次交叉验证,其中4折作为训练集用来训练模型,1折作为验证集用来求MAPE。五折五次交叉验证大致过程如下,我们打印了一个神经元参数的变化过程。由于篇幅原因,我们设置每次训练的次数num_epochs =2,目的是看看五折五次交叉验证的过程,而不去管它并没有收敛的事实,过程如下图:

15.png

16.png

17.png

在未设置早停的情况下,num_epochs 的大小会影响模型的训练结果,太小则欠拟合,太大则过拟合,我们设置了一个合理的num_epochs =16左右,达到了不错的效果。结果如下:

18.png

  • 感想:

经过前面两次的作业的教训,我们这次拿到训练数据,并没有直接开始预处理数据,选模型等。而是先对13个特征进行特征工程,检查他们和输出y的相关性,X特征之间的相关性,从中找出重要的特征和相对不重要的特征,画出各个特征的直方分布图,先对特征有一些大致的了解,再去进行对应的预处理,特征变换,模型搭建,训练,评估,这样子看起来最开始会消耗点时间,但是其实是“把时间用在刀刃上”,不仅让整个写作业过程更加流畅,而且也会让模型的准确率和误差有所改进。

调库和自己搭建模型都是神经网络的可选项,但是如果希望自己的模型有很大的灵活性,那么自己用pytorch或者tensorflow搭建模型是更好的选择,如果直接调库,那么一个MLPregression()就解决了模型问题,然而自己搭建模型,就是从模型的层数,神经元数,优化函数,损失函数,交叉验证选择……一步步完成任务,虽然需要看很多pytorch文档,但是对于以后搭建神经网络来说这是一劳永逸的事情,而且也有利于巩固我们上课所学习到的知识,让我们对前馈神经网络和反向传播原理有了更深刻的印象。最终看到自己的MAPE随着Epoch下降,心里也算得到了安慰。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。