当前位置:   article > 正文

阿里云天池《“AI Earth”人工智能创新挑战赛》萌新体验_aliearth tensorflow

aliearth tensorflow

前言

一直都想参加一次阿里天池比赛,看到有公众号提了这次比赛的baseline,果断报名。0基础,开始了第一次数据科学比赛的尝试~

这次比赛遇到了各种各样的问题,几度想放弃,但是不忍心排200多名。来都来了,冲完B榜吧,也算是表明自己第一次参加天池大赛的态度,不能让母校的名字排在最后。

题目

https://tianchi.aliyun.com/competition/entrance/531871/introduction
在这里插入图片描述
发生在热带太平洋上的厄尔尼诺-南方涛动(ENSO)现象是地球上最强、最显著的年际气候信号。通过大气或海洋遥相关过程,经常会引发洪涝、干旱、高温、雪灾等极端事件,对全球的天气、气候以及粮食产量具有重要的影响。准确预测ENSO,是提高东亚和全球气候预测水平和防灾减灾的关键。

本次赛题是一个时间序列预测问题。基于历史气候观测和模式模拟数据,利用T时刻过去12个月(包含T时刻)的时空序列(气象因子),构建预测ENSO的深度学习模型,预测未来1-24个月的Nino3.4指数,如下图所示:

在这里插入图片描述

这题是一个典型的时间序列预测问题,看起来没那么难,但是认真一想还是有很多难点的,比如数据质量,内存限制,模型,都是可以改进的,下面是我的baseline。

数据分析

拿到数据,我都是一股脑往模型里扔,然后开始炼丹,炼着炼着,分数从-6变为-10、-13、-15、-22…最后都到NaN了,平时老师也总是说,不要一上来就上模型,先把数据分析清楚了,于是打算再花几个小时进行数据分析。

CMIP数据分析

CMIP是模拟数据,网友UCDuan说:

CMIP是气候模型的数据
你可以理解为不同情况下(不同的初始场和不同的气候模型)“地球”的真实情况,只是符合大致的‘物理规律’,但不是地球真实的历史情况。所以用CMIP就是想挖掘这个‘物理规律’。

这里我打算拿CMIP数据训练,SODA数据验证。

数据统计

以sst数据为例
在这里插入图片描述

在这里插入图片描述

趋势图

在这里插入图片描述
在这里插入图片描述
可以看出数据是经过处理的,每隔12个月,连续三组数据值是一样的
再加上下个特征,发现他们也是相似的
在这里插入图片描述
另外有些特征数据缺失,需要进行平均填充
在这里插入图片描述
方法如下:

tr_features2 = np.concatenate([sst_CMIP_shaped,t300_CMIP_shaped,va_CMIP_shaped,ua_CMIP_shaped],axis=-1)
tr_features2[np.isnan(tr_features2)] = np.mean(tr_features2)#对NaN值进行均值填充
  • 1
  • 2

SODA数据分析

代码

baseline来自这篇文章:https://mp.weixin.qq.com/s/63LPCHNo4zOA_UGDAc2xUQ
这篇文章完成了数据组织、处理、MLP模型构建、本地测试、上传代码,但是有很多问题,我进行了初步修正:

  1. 由于内存限制,CMIP数据只加载1000年==》全部
  2. 前面数据转换为csv文件,后面没有用到==》后面数据加载来源于csv文件
  3. 模型使用MLP==》模型改为3维CNN

代码链接:https://github.com/guhang987/-AI-Earth-
代码解释:

  1. ./ENSO/data文件夹
    存放原始数据与转换后的数据

在这里插入图片描述

  1. data_prepare.py
    将比赛提供的nc文件转换为csv文件
  2. train.ipynb
    训练模型
  3. main.py
    模型打包提交

训练

conda环境:

  • python 3.8
  • tensorflow 2.20

首先进行数据格式转换,提取数据前24个月,以及标签后12个月的数据。

soda_label = pd.read_csv('./ENSO/data/df_SODA_label.csv')['label']
sst_SODA = pd.read_csv('./ENSO/data/df_sst_SODA.csv')
t300_SODA = pd.read_csv('./ENSO/data/df_t300_SODA.csv')
ua_SODA = pd.read_csv('./ENSO/data/df_ua_SODA.csv')
va_SODA = pd.read_csv('./ENSO/data/df_va_SODA.csv')

sst_SODA = np.array(sst_SODA).reshape(100,36,24,72,1)[:,:12,:,:,:]
t300_SODA = np.array(t300_SODA).reshape(100,36,24,72,1)[:,:12,:,:,:]
va_SODA = np.array(va_SODA).reshape(100,36,24,72,1)[:,:12,:,:,:]
ua_SODA = np.array(ua_SODA).reshape(100,36,24,72,1)[:,:12,:,:,:]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

然后利用concat方法拼接这4个维度:


tr_features = np.concatenate([sst_SODA,t300_SODA,va_SODA,ua_SODA],axis=-1)
tr_features.shape
### 训练标签,取后24个
tr_labels = np.array(soda_label).reshape(-1,36)[:,12:]
tr_labels.shape
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

得到(100, 12, 24, 72, 4)的数据以及(100, 24)的标签。按8:2分割训练集与验证集。
下一步构建CNN模型:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 12, 24, 72, 4)     0         
_________________________________________________________________
conv3d (Conv3D)              (None, 9, 9, 32, 64)      671808    
_________________________________________________________________
max_pooling3d (MaxPooling3D) (None, 4, 4, 16, 64)      0         
_________________________________________________________________
conv3d_1 (Conv3D)            (None, 1, 1, 1, 128)      2097280   
_________________________________________________________________
flatten (Flatten)            (None, 128)               0         
_________________________________________________________________
dense (Dense)                (None, 64)                8256      
_________________________________________________________________
dropout (Dropout)            (None, 64)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 32)                2080      
_________________________________________________________________
dropout_1 (Dropout)          (None, 32)                0         
_________________________________________________________________
dense_2 (Dense)              (None, 24)                792       
=================================================================
Total params: 2,780,216
Trainable params: 2,780,216
Non-trainable params: 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

相关训练参数:

history        = model_cnn.fit(tr_fea,tr_label,
                    validation_data=(val_fea, val_label),
                    batch_size=4096, epochs=2000,
                    callbacks=[plateau, checkpoint, early_stopping],
                    verbose=1)
  • 1
  • 2
  • 3
  • 4
  • 5

之前是拼接SODA和CMIP数据(2000年),后来拼接SODA和CMIP数据(4368年)发现内存爆了,怎么改都不行。于是尝试多次model.fit方法分别输入SODA CMIP数据,中间用del 和gc.collect来释放内存。

#增量学习

for round_ in range(4):
    step=1000
    leng = step*36
    inde = list(range(step*round_*36+1))
    if(round_==4):
        leng = 600*36
    gc.collect()
    sst_CMIP = pd.read_csv('./ENSO/data/df_sst_CMIP.csv',header=None,skiprows=inde,nrows = leng)
    t300_CMIP = pd.read_csv('./ENSO/data/df_t300_CMIP.csv',header=None,skiprows=inde,nrows = leng)
    ua_CMIP = pd.read_csv('./ENSO/data/df_ua_CMIP.csv',header=None,skiprows=inde,nrows = leng)
    va_CMIP = pd.read_csv('./ENSO/data/df_va_CMIP.csv',header=None,skiprows=inde,nrows = leng)
    cmip_label = pd.read_csv('./ENSO/data/df_CMIP_label.csv',header=None,skiprows=inde,nrows = leng)[1]

    sst_CMIP.drop(sst_CMIP.columns[0],axis=1,inplace=True)
    t300_CMIP.drop(t300_CMIP.columns[0],axis=1,inplace=True)
    va_CMIP.drop(va_CMIP.columns[0],axis=1,inplace=True)
    ua_CMIP.drop(ua_CMIP.columns[0],axis=1,inplace=True)
    
    sst_CMIP_shaped = np.array(sst_CMIP).reshape(-1,36,24,72,1)[:,:12,:,:,:]
    t300_CMIP_shaped = np.array(t300_CMIP).reshape(-1,36,24,72,1)[:,:12,:,:,:]
    va_CMIP_shaped = np.array(va_CMIP).reshape(-1,36,24,72,1)[:,:12,:,:,:]
    ua_CMIP_shaped = np.array(ua_CMIP).reshape(-1,36,24,72,1)[:,:12,:,:,:]
    del va_CMIP
    del t300_CMIP
    del ua_CMIP
    del sst_CMIP

    gc.collect()
    tr_features2 = np.concatenate([sst_CMIP_shaped,t300_CMIP_shaped,va_CMIP_shaped,ua_CMIP_shaped],axis=-1)
    tr_features2[np.isnan(tr_features2)] = np.mean(tr_features2)#对NaN值进行均值填充
    del va_CMIP_shaped
    del t300_CMIP_shaped
    del ua_CMIP_shaped
    del sst_CMIP_shaped

    gc.collect()
    tr_labels2 = np.array(cmip_label).reshape(-1,36)[:,12:]
    model_cnn     = build_model()
    if round_ != 0:
        #加载上一轮模型
        
        model_cnn.load_weights('./model/model-%d.h5'%(round_-1))
    #存储本轮模型
    model_weights = "./model/model-%d.h5"%round_
    #保存最佳模型
    checkpoint = ModelCheckpoint(model_weights, monitor='val_loss', verbose=0, save_best_only=True, mode='min',
                             save_weights_only=True)
    plateau        = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, verbose=1, min_delta=1e-4, mode='min')
    early_stopping = EarlyStopping(monitor="val_loss", patience=20)
    model_cnn.fit(tr_features2,tr_labels2,
                    validation_data=(val_f,val_l),
                    batch_size=32, epochs=20000,
                    callbacks=[plateau, checkpoint, early_stopping],
                    verbose=2)
    prediction = model_cnn.predict(tr_features)
    #from   sklearn.metrics import mean_squared_error
    sc = score(y_true = tr_labels, y_preds = prediction)
    print("%d轮完成,分数%f"%(round_,sc))
    #3轮完成,分数-17.867135
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

总的来说,数据处理目前有三种思路:

  1. 只拿100年的SODA数据训练
  2. 拿4645年的CMIP数据训练,SODA数据作为验证集
  3. CMIP与SODA数据融合训练

模型的话,也可以用RNN来做,只不过提供的数据已经组织好了,用CNN就直接可以输入。于是我就拿了一个玩具CNN来做,可惜对CNN没啥理解,参数都是自己调的,不知道哪些超参最好,希望以后能搞明白。

我始终没搞清楚什么是气象中的模拟数据、真实历史数据,以上三种方法都尝试过,可惜各种奇怪的bug和每天几次的提交机会,让我无法验证

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/945645
推荐阅读
相关标签