天池AI Earth挑战赛 PyTorch深度学习模型改进记录(无代码版)

0、前言

为节省篇幅,本记录的代码放在另一篇博客里,链接

1、截至2月23日14:40(best score=-19.6)

1.1、基本思路

从测试的角度来看,输入数据维度: ( m o n t h s , l a t s , l o n s , f e a t u r e s ) (months, lats, lons, features) (months,lats,lons,features)
其中, m o n t h s = 24 , l a t s = 24 , l o n s = 72 , f e a t u r e s = 4 months=24, lats=24,lons=72,features=4 months=24,lats=24,lons=72,features=4
输出数据维度: ( m o n t h s , ) (months,) (months,),其中, m o n t h s = 24 months=24 months=24
训练时维度与测试匹配,只是多一个 b a t c h batch batch维度,人为设定。
training input: ( b a t c h , m o n t h s , l a t s , l o n s , f e a t u r e s ) (batch,months, lats, lons, features) (batch,months,lats,lons,features)
training output: ( b a t c h , m o n t h s ) (batch,months) (batch,months)

框架与toy model类似,CNN+时序模型(LSTM/GRU/Seq2Seq/Attention…)
把12个月先看做12通道的图片,用卷积核提取像素点特征,然后再输入时序模型,时序模型的output长度(24)大于input长度(12),所以我觉得LSTM或GRU大概不会很合适。Linear层一般是对特征feature做变换吧,对序列长度做变换合适吗?

我个人觉得滑窗/历史平移好像不太行,因为测试的时候是不给历史的Nino 3.4 index的,除非。。。用历史特征先预测出历史的Nino 3.4 index,然后再做滑窗,但是那样会很麻烦,我估计效果不会太好。

对label做一阶/二阶差分我觉得也不太合适,做差分一般是为了消除趋势,但是这么做好像一般是用在只有label的情况下的?比方说只有客流量数据,要用前一段时间客流量预测之后的客流量。但是这个题不一样吧,他还给了4个气象因子呢,气象因子也是有趋势的吧,我们消除了label的趋势,是不是也要消除一下features的趋势?按理说Nino 3.4 index是会随着这四个特征变化而变化的。所以我觉得应该不用差分吧。二来,差分后还原是要初值的,初值哪里来?正如下面一段也涉及初值的问题。

如果是Seq2Seq这种的话,decoder的初始值是啥呢?在机器翻译中一般是<SOS>/<BOS>,但是正如上面说的测试的时候没有历史的label,所以我觉得要么就拿label的均值or中位数这种统计量充当初值,要么就用LSTM/GRU先预测一个初值,再输入。

1.2、数据预处理

见代码段1.2.1

  • 其实sklearn里是有train_test_splitStandardScaler的,但是我还是写了自己的版本,减少第三方库的使用,加快docker build速度。
  • 训练数据量可以说是很大很大了,把所有数据连接起来(也就是通过CMIP_gen(13)生成的pkl文件)大概是1.48GB,直接把我小破笔记本卡的不要不要的。所以我产生了分批训练的想法,每400个样本作为一批,具体下小节再说。
  • 从上一小节对input和output的分析来看,sample里只有36个月的前12个月才是有用的,所以我扔掉了sample的后24个月的数据;label里只有后24个月才是有用的,所以我扔掉了前12个月的数据。

为了验证不同模式的样本可以混合起来训练,我画了SODA和CMIP+SODA(Total)的分布。
画图代码见代码段1.2.2

max: 4.1381884   min: -3.5832222   mean: -0.14928016   std: 0.8475895
SODA_max:3.1885402   SODA_min: -2.0704737   mean: -0.005200089   std: 0.7847775

可以看出来两种的统计量差不多,分布的差别也不大,属于中心很接近的两个正态分布。
P.S. 分布直方图有三种颜色,淡紫色是SODA和Total重合的部分。
在这里插入图片描述
我原来还有个缩小数据规模的想法,就是对不同CMIP模式取均值,但是分析一通后发现,不同CMIP模式的相关性似乎不是很高。。。
在这里插入图片描述
我挑了CMIP6前四种模式的第一年的sst,小标题是相关系数,无论是从相关系数还是从散点分布来看,都看不出什么相关性。所以最后我还是没有取均值。

1.3、网络结构

见代码段1.3.1

  • Seq2Seq和Attention还没来得及试,我总感觉最后通过一个Linear层得到24个月的label这么做哪里怪怪的,按我以前的学习Linear一般是对特征做变换,但这24个月显然不是特征吧,而是时间点,应该用many to many的模型来得到24个时间点更合适
  • 据说RNN用正交初始化效果不错,参考链接

1.4、训练网络

见代码段1.4.1

与score对应,损失函数也是让越往后的时间点预测权重更高,这么做也是希望拿更高的score

见代码段1.4.2

评价体系与官方保持一致,代码参考了时间序列实践 - 赛题理解及Baseline12:10处的截屏,并做了一定改动。

见代码段1.4.3

以上是超参数的设定。
昨天,我只让SODA参与训练验证。主要问题是过拟合太严重了,Dropout,BatchNorm,weight decay, flooding,early stop各种奇技淫巧差不多都用了,还是没法抑制过拟合,说明网络基本上没学到什么重要的特征。但是另一方面来说也还可以,验证集score最高能达到17,不小的正数了。但是测试后发现分数还是-20左右。
在这里插入图片描述

今天,我把把SODA CMIP数据一起输进去训练,CUDA溢出了,难受了。
在这里插入图片描述
再试试分批训练。每一批是一个大的Batch,一共是1+12个Batches(一个SODA,十二个CMIP),SODA批次有100个样本,CMIP批次前11个都是400个样本,最后一个批次是245个样本。
在这里插入图片描述
蓝色训练集,红色验证集。可以看出score具有很明显的周期性,每个峰值都是SODA的score,说明SODA还是比较好学的,CMIP就比较难学。

对曲线做平滑处理
在这里插入图片描述
纵然score一直是负的,并且强烈波动,但毕竟趋势是向好的,说明数据特征是可学习的。但是到训练后期仿佛就进入一个瓶颈了,score不上升loss也不下降了。

这种周期性大概就是深度学习模型的“灾难遗忘”,通俗来讲就是学了后面的忘了前面的。

2、截至2月23日23:30(best score=6.2)

2.1、模型结构

据说maxout激活函数能一定程度上防止灾难遗忘(参见花书第六章第三节[1])
在这里插入图片描述
然后我就自己写了一个maxout模块(因为PyTorch没有现成的),代替ReLU。但是效果很烂,loss很难下降,train score 和 vali score都很难上升,可能是我代码写得有问题。要么就是非线性程度太高不利于学习。(图片文字就是上一张图的下一段)
在这里插入图片描述
见代码段2.1.1

我也把我的代码贴出来(参考了nn.Linear源码),供大家讨论。我把channel数目看作神经元个数,因为maxout是激活函数,所以激活前后神经元个数不变,我在网上看的一些maxout代码,都改变了神经元个数(channels),我感觉不太符合激活函数的本意。BTW,有关maxout去年我在b站做了一个讲解视频,有兴趣的可以去看看。

然而这都不是重点!maxout根本就训练不起来,直接打入冷宫叭~

2.2、训练网络

后来我就试试把所有SODA和300个CMIP样本合起来训练(之前是400个CMIP,现在把其中100个替换成SODA)。没想到效果贼好??vali score竟然达到了26!!虽然还是有严重过拟合,因为train score可以达到90-100,但是还是很不错的了。我赶紧提交结果,发现真的可以欸,test score到6了哈哈哈!
在这里插入图片描述
Reference:
[1]Ian Goodfellow, Yoshua Bengio, Aaron Courville.Deep Learning[M].MIT Press:,2016:167-168.

3、截至2月24号19:10(best score=6.2)

3.1、数据预处理

还在苦苦思索如何准备一个合适的训练集。。。基本的想法是“及时复习”。每次复习200个、新学400个样本。

见代码段3.1.1

3.2、训练网络

就用这种training data set 训练了6次,在第6次第24个epoch,验证集score勉勉强强提升到了30.31。
在这里插入图片描述
就用这个30.31的模型来测试,提交结果后发现只有-11.52???心态又崩了啊
在这里插入图片描述
总结一下目前的一些待实现的ideas:BoTorch、Attention、持续学习。

4、截至2月24日23:21(best score=13.87)

4.1、网络结构

上述ideas还没来得及实现,因为我相信“复习”法肯定有效果。窃以为上次的-11.5分还是因为过拟合太严重了,所以我加入了更多的dropout抑制过拟合。
在这里插入图片描述

4.2、训练网络

依然采用复习大法。现在vali score提升到34.11了,这个峰值出现在第一个round第二个Batch的第4个epoch,后面就进入瓶颈期了。

在这里插入图片描述

另外很明显可以看到train score 和vali score差距变小了,周期性仍然存在但是波动没有那么强烈了,说明dropout真的是有效果的!可以从一定程度缓解灾难遗忘~

提交结果后发现test score提升到了13.87!啊啊啊啊啊好棒!
在这里插入图片描述

5、截至2月25日12:58(best score=17.89)

5.1、网络结构

今天早晨起来,再次审视了一下昨晚的结构,感觉dropout还是有不合理之处
在这里插入图片描述
这四个dropout不合适,因为做完第二次max pooling 每个气象因子的每个时间步只剩1×3=3个像素了,这样dropout好像最后就寥寥无几了?不合适不合适,所以我把这边的dropout去掉了。到目前为止一共是5处dropout(4个池化后的,1个cat后的)。

5.2、训练网络

增加了两个batch。
在这里插入图片描述
vali score最高达到了35.8,提交结果后test score是17.89
在这里插入图片描述
比较一下三次正test score的结果。用所给test样例可视化。
在这里插入图片描述

  • 绿色线条是最初的,只用了前四百个样本(70SODA+330CMIP),dropout也只有一处。
  • 蓝色线条是第二次的,用了6个batches(400+600×5),dropout有9处。
  • 橙色线条是最新的,用了8个batches(400+600×7),dropout有5处。

可以断定,前三个月label肯定是急速上升,这大概是sample 400的短板;后几个月label应该分布在0-0.3之间。最后可以考虑做集成学习(按test score加权?)。

6、截至2月25日23:41(best score=17.89)

6.1、网络结构

成绩没有进步,但想说两点:

  • 之前的GRU都是有问题的,__init__的时候忘记设置batch_first=True了,但是竟然能预测的很好。。。?改过来以后发现,反而没有之前预测的好。
  • 试了attention机制,发现效果不尽如人意,代码段放上来,哎,也许是写的有问题,大家看看。
    代码段6.1.1,attention的代码

Encoder很好弄,比较难的是Decoder。因为input有四种气象因子,至少有四个特征(实际上做完最后一个max pooling再拉平是12个特征),output是一维的,也就是只有一个特征,这也太少了。一个最简单的想法是用Linear,但我不甘于此。回想NLP中通常用词嵌入的方法来给每个词编码,我就产生了一个很naive的想法,我能不能也把这些Nino 3.4 index也当成一个一个词呢?因为咱们做的是回归,数据是连续分布的,总不能有无穷多个“词”吧?所以我进而想到了规定一个精度。比方说精度为0.001,那么,0.3001和0.3002是同一个词,但是0.301和0.302是两个不同的词。

这样一来,根据我们在1.2中算的最值,可以粗略地把范围划在 [ − 4 , 5 ] [-4,5] [4,5],精度取0.01,一共有 5 − ( − 4 ) 0.01 + 1 = 901 \frac{5-(-4)}{0.01}+1=901 0.015(4)+1=901个“词”。考虑到inference的时候可能会超出这个范围,必须在embedding前加一个线性整流单元把上次的预测值clip在 [ − 4 , 5 ] [-4,5] [4,5]里面。

关于初值的问题,SODA均值-0.005,总体均值-0.149,我粗略地取了-0.05,没什么道理,就是在俩均值之间随便选了一个点。如果这么选的话,可以把这个初值作为超参,最后慢慢调参去吧~

关于这个的结果。。。可能是哪儿出bug了,我竟然预测出一条水平线🤦‍

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值