乐趣区

关于人工智能:海洋气象预测Baseline4TensorFlowtorch版本MLPTCNNRNNLSTM模型训练以及预测

人工智能翻新挑战赛:陆地气象预测 Baseline[4]完整版(TensorFlow、torch 版本)含数据转化、模型构建、MLP、TCNN+RNN、LSTM 模型训练以及预测

1. 赛题简介

我的项目链接以及码源见文末

2021“AI Earth”人工智能翻新挑战赛,以“AI 助力精准气象和陆地预测”为主题,旨在摸索人工智能技术在气象和陆地畛域的利用。

本赛题的背景是厄尔尼诺 – 北方涛动 (ENSO) 景象。ENSO 景象是厄尔尼诺 (EN) 景象和北方涛动 (SO) 景象的合称,其中厄尔尼诺景象是指赤道中东太平洋左近的海表面温度继续异样增暖的景象,北方涛动景象是指寒带东太平洋与寒带西太平洋气压场存在的气压变动相同的跷跷板景象。厄尔尼诺景象和北方涛动景象理论是反常气象别离在陆地和大气中的体现,二者密切相关,因而合称为厄尔尼诺 – 北方涛动景象。

ENSO 景象会在世界大部分地区引起极其天气,对寰球的天气、气象以及粮食产量具备重要的影响,精确预测 ENSO,是进步东亚和寰球气象预测程度和防灾减灾的要害。Nino3.4 指数是 ENSO 景象监测的一个重要指标,它是指 Nino3.4 区 (170°W – 120°W,5°S – 5°N) 的均匀海温距平指数,用于反馈海表温度异样,若 Nino3.4 指数间断 5 个月超过 0.5℃就断定为一次 ENSO 事件。本赛题的指标,就是基于历史气象观测和模式模仿数据,利用 T 时刻过来 12 个月 (蕴含 T 时刻) 的时空序列,预测将来 1 – 24 个月的 Nino3.4 指数。

基于以上信息能够看出,咱们本期的组队学习要实现的是一个时空序列的预测工作。

比赛题目

数据简介

本赛题应用的训练数据包含 CMIP5 中 17 个模式提供的 140 年的历史模仿数据、CMIP6 中 15 个模式提供的 151 年的历史模仿数据和美国 SODA 模式重建的 100 年的历史观测异化数据,采纳 nc 格局保留,其中 CMIP5 和 CMIP6 别离是世界气象钻研打算 (WCRP) 的第 5 次和第 6 次耦合模式比拟打算,这二者都提供了多种不同的气象模式对于多种气象变量的模仿数据。这些数据蕴含四种气象变量:海表温度异样(SST)、热含量异样(T300)、纬向风异样(Ua)、经向风异样(Va),数据维度为(year, month, lat, lon),对于训练数据提供对应月份的 Nino3.4 指数标签数据。简而言之,提供的训练数据中的每个样本为某年、某月、某个维度、某个经度的 SST、T300、Ua、Va 数值,标签为对应年、对应月的 Nino3.4 指数。

须要留神的是,样本的第二维度 month 的长度不是 12 个月,而是 36 个月,对应从以后 year 开始间断三年的数据,例如 SODA 训练数据中 year 为 0 时蕴含的是从第 1 – 第 3 年逐月的历史观测数据,year 为 1 时蕴含的是从第 2 年 – 第 4 年逐月的历史观测数据,也就是说,样本在工夫上是有穿插的。

另外一点须要留神的是,Nino3.4 指数是 Nino3.4 区域从以后月开始间断三个月的 SST 平均值,也就是说,咱们也能够不间接预测 Nino3.4 指数,而是以 SST 为预测指标,间接求得 Nino3.4 指数。

测试数据为国内多个陆地材料异化后果提供的随机抽取的 $N$ 段长度为 12 个月的工夫序列,数据采纳 npy 格局保留,维度为(12, lat, lon, 4),第一维度为间断的 12 个月份,第四维度为 4 个气象变量,按 SST、T300、Ua、Va 的程序寄存。测试集文件序列的命名如 test_00001_01_12.npy 中 00001 示意编号,01 示意起始月份,12 示意终止月份。

训练数据阐明

每个数据样本第一维度(year)表征数据所对应起始年份,对于 CMIP 数据共 4645 年,其中 1 -2265 为 CMIP6 中 15 个模式提供的 151 年的历史模仿数据(总共:151 年 15 个模式 =2265);2266-4645 为 CMIP5 中 17 个模式提供的 140 年的历史模仿数据(总共:140 年 17 个模式 =2380)。对于历史观测异化数据为美国提供的 SODA 数据。

其中每个样本第二维度(mouth)表征数据对应的月份,对于训练数据均为 36,对应的从以后年份开始间断三年数据(从 1 月开始,共 36 月),比方:

SODA_train.nc 中 [0,0:36,:,:] 为第 1 - 第 3 年逐月的历史观测数据;

SODA_train.nc 中 [1,0:36,:,:] 为第 2 - 第 4 年逐月的历史观测数据;
…,
SODA_train.nc 中 [99,0:36,:,:] 为第 100-102 年逐月的历史观测数据。


CMIP_train.nc 中 [0,0:36,:,:] 为 CMIP6 第一个模式提供的第 1 - 第 3 年逐月的历史模仿数据;
…,
CMIP_train.nc 中 [150,0:36,:,:] 为 CMIP6 第一个模式提供的第 151- 第 153 年逐月的历史模仿数据;

CMIP_train.nc 中 [151,0:36,:,:] 为 CMIP6 第二个模式提供的第 1 - 第 3 年逐月的历史模仿数据;
…,
CMIP_train.nc 中 [2265,0:36,:,:] 为 CMIP5 第一个模式提供的第 1 - 第 3 年逐月的历史模仿数据;
…,
CMIP_train.nc 中 [2405,0:36,:,:] 为 CMIP5 第二个模式提供的第 1 - 第 3 年逐月的历史模仿数据;
…,
CMIP_train.nc 中 [4644,0:36,:,:] 为 CMIP5 第 17 个模式提供的第 140- 第 142 年逐月的历史模仿数据。

其中每个样本第三、第四维度别离代表经纬度(南纬 55 度北纬 60 度,东经 0360 度),所有数据的经纬度范畴雷同。

训练数据标签阐明

标签数据为 Nino3.4 SST 异样指数,数据维度为(year,month)。

CMIP(SODA)_train.nc 对应的标签数据以后时刻 Nino3.4 SST 异样指数的三个月滑动平均值,因而数据维度与维度介绍同训练数据统一

注:三个月滑动平均值为以后月与将来两个月的平均值。

测试数据阐明

测试用的初始场(输出)数据为国内多个陆地材料异化后果提供的随机抽取的 n 段 12 个工夫序列,数据格式采纳 NPY 格局保留,维度为(12,lat,lon, 4),12 为 t 时刻及过来 11 个时刻,4 为预测因子,并依照 SST,T300,Ua,Va 的程序寄存。

测试集文件序列的命名规定:test_编号_起始月份_终止月份.npy,如 test_00001_01_12_.npy。

评估指标

本赛题的评估指标如下:

$$
Score = \frac{2}{3} \times accskill – RMSE
$$

其中 $accskill$ 为相关性技巧评分,计算形式如下:

$$
accskill = \sum_{i=1}^{24} a \times ln(i) \times cor_i \\
(i \leq 4, a = 1.5; 5 \leq i \leq 11, a = 2; 12 \leq i \leq 18, a = 3; 19 \leq i, a = 4)
$$

能够看出,月份 $i$ 减少时系数 $a$ 也增大,也就是说,模型能精确预测的工夫越长,评分就越高。

$cor_i$ 是对于 $N$ 个测试集样本在时刻 $i$ 的预测值与理论值的相关系数,计算公式如下:

$$
cor_i = \frac{\sum_{j=1}^N(y_{truej}-\bar{y}_{true})(y_{predj}-\bar{y}_{pred})}{\sqrt{\sum(y_{truej}-\bar{y}_{true})^2\sum(y_{predj}-\bar{y}_{pred})^2}}
$$

其中 $y_{truej}$ 为时刻 $i$ 样本 $j$ 的理论 Nino3.4 指数,$\bar{y}_{true}$ 为该时刻 $N$ 个测试集样本的 Nino3.4 指数的均值,$y_{predj}$ 为时刻 $i$ 样本 $j$ 的预测 Nino3.4 指数,$\bar{y}_{pred}$ 为该时刻 $N$ 个测试集样本的预测 Nino3.4 指数的均值。

$RMSE$ 为 24 个月份的累计均方根误差,计算公式为:

$$
RMSE = \sum_{i=1}^{24}rmse_i \\
rmse = \sqrt{\frac{1}{N}\sum_{j=1}^N(y_{truej}-y_{predj})^2}
$$

赛题剖析

剖析上述赛题信息能够发现,咱们须要解决的是以下问题:

  • 对于一个时空序列预测问题,要如何开掘工夫信息?如何开掘空间信息?
  • 数据中给出的特色是四个气象畛域公认的、通用的气象变量,咱们很难再由此结构新的特色。如果不结构新的特色,要如何从给出的特色中挖掘出更多的信息?
  • 训练集的数据量不大,总共只有 $140\times17+151\times15+100=4745$ 个训练样本,对于数据量小的预测问题,咱们通常须要从以下两方面思考:

    • 如何减少数据量?
    • 如何结构小(参数量小,减小过拟合危险)而深(能提取出足够丰盛的信息)的模型?

2. 线下数据转换

  • 将数据转化为咱们所相熟的模式,每个人的格调不一样,此处能够作为如何将 nc 文件转化为 csv 等文件

数据转化

## 工具包导入 & 数据读取
### 工具包导入

'''
装置工具
# !pip install netCDF4 
''' 
import pandas as pd
import numpy  as np
import tensorflow as tf
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import scipy 
from netCDF4 import Dataset
import netCDF4 as nc
import gc
%matplotlib inline 

数据读取

SODA_label 解决
  1. 标签含意
标签数据为 Nino3.4 SST 异样指数,数据维度为(year,month)。CMIP(SODA)_train.nc 对应的标签数据以后时刻 Nino3.4 SST 异样指数的三个月滑动平均值,因而数据维度与维度介绍同训练数据统一
注:三个月滑动平均值为以后月与将来两个月的平均值。
  1. 将标签转化为咱们相熟的 pandas 模式
label_path       = './data/SODA_label.nc'
label_trans_path = './data/' 
nc_label         = Dataset(label_path,'r')
 
years            = np.array(nc_label['year'][:])
months           = np.array(nc_label['month'][:])

year_month_index = []
vs               = []
for i,year in enumerate(years):
    for j,month in enumerate(months):
        year_month_index.append('year_{}_month_{}'.format(year,month))
        vs.append(np.array(nc_label['nino'][i,j]))

df_SODA_label               = pd.DataFrame({'year_month':year_month_index}) 
df_SODA_label['year_month'] = year_month_index
df_SODA_label['label']      = vs

df_SODA_label.to_csv(label_trans_path + 'df_SODA_label.csv',index = None)
df_SODA_label.head()

<div>
<style scoped>

.dataframe tbody tr th:only-of-type {vertical-align: middle;}

.dataframe tbody tr th {vertical-align: top;}

.dataframe thead th {text-align: right;}

</style>

year_month label
0 year_1_month_1 -0.40720701217651367
1 year_1_month_2 -0.20244435966014862
2 year_1_month_3 -0.10386104136705399
3 year_1_month_4 -0.02910841442644596
4 year_1_month_5 -0.13252995908260345

</div>

转化

SODA_train 解决
SODA_train.nc 中 [0,0:36,:,:] 为第 1 - 第 3 年逐月的历史观测数据;SODA_train.nc 中 [1,0:36,:,:] 为第 2 - 第 4 年逐月的历史观测数据;…,
SODA_train.nc 中 [99,0:36,:,:] 为第 100-102 年逐月的历史观测数据。
SODA_path        = './data/SODA_train.nc'
nc_SODA          = Dataset(SODA_path,'r') 
  • 自定义抽取对应数据 & 转化为 df 的模式;

index 为年月; columns 为 lat 和 lon 的组合

def trans_df(df, vals, lats, lons, years, months):
    '''(100, 36, 24, 72) -- year, month,lat,lon''' 
    for j,lat_ in enumerate(lats):
        for i,lon_ in enumerate(lons):
            c = 'lat_lon_{}_{}'.format(int(lat_),int(lon_))  
            v = []
            for y in range(len(years)):
                for m in range(len(months)): 
                    v.append(vals[y,m,j,i])
            df = v
    return df
year_month_index = []

years              = np.array(nc_SODA['year'][:])
months             = np.array(nc_SODA['month'][:])
lats             = np.array(nc_SODA['lat'][:])
lons             = np.array(nc_SODA['lon'][:])


for year in years:
    for month in months:
        year_month_index.append('year_{}_month_{}'.format(year,month))

df_sst  = pd.DataFrame({'year_month':year_month_index}) 
df_t300 = pd.DataFrame({'year_month':year_month_index}) 
df_ua   = pd.DataFrame({'year_month':year_month_index}) 
df_va   = pd.DataFrame({'year_month':year_month_index})
%%time
df_sst = trans_df(df = df_sst, vals = np.array(nc_SODA['sst'][:]), lats = lats, lons = lons, years = years, months = months)
df_t300 = trans_df(df = df_t300, vals = np.array(nc_SODA['t300'][:]), lats = lats, lons = lons, years = years, months = months)
df_ua   = trans_df(df = df_ua, vals = np.array(nc_SODA['ua'][:]), lats = lats, lons = lons, years = years, months = months)
df_va   = trans_df(df = df_va, vals = np.array(nc_SODA['va'][:]), lats = lats, lons = lons, years = years, months = months)
label_trans_path = './data/'
df_sst.to_csv(label_trans_path  + 'df_sst_SODA.csv',index = None)
df_t300.to_csv(label_trans_path + 'df_t300_SODA.csv',index = None)
df_ua.to_csv(label_trans_path   + 'df_ua_SODA.csv',index = None)
df_va.to_csv(label_trans_path   + 'df_va_SODA.csv',index = None)
CMIP_label 解决
label_path       = './data/CMIP_label.nc'
label_trans_path = './data/'
nc_label         = Dataset(label_path,'r')
 
years            = np.array(nc_label['year'][:])
months           = np.array(nc_label['month'][:])

year_month_index = []
vs               = []
for i,year in enumerate(years):
    for j,month in enumerate(months):
        year_month_index.append('year_{}_month_{}'.format(year,month))
        vs.append(np.array(nc_label['nino'][i,j]))

df_CMIP_label               = pd.DataFrame({'year_month':year_month_index}) 
df_CMIP_label['year_month'] = year_month_index
df_CMIP_label['label']      = vs

df_CMIP_label.to_csv(label_trans_path + 'df_CMIP_label.csv',index = None)
df_CMIP_label.head()

<div>
<style scoped>

.dataframe tbody tr th:only-of-type {vertical-align: middle;}

.dataframe tbody tr th {vertical-align: top;}

.dataframe thead th {text-align: right;}

</style>

year_month label
0 year_1_month_1 -0.26102548837661743
1 year_1_month_2 -0.1332537680864334
2 year_1_month_3 -0.014831557869911194
3 year_1_month_4 0.10506672412157059
4 year_1_month_5 0.24070978164672852

</div>

CMIP_train 解决

CMIP_train.nc 中 [0,0:36,:,:] 为 CMIP6 第一个模式提供的第 1 - 第 3 年逐月的历史模仿数据;…,
CMIP_train.nc 中 [150,0:36,:,:] 为 CMIP6 第一个模式提供的第 151- 第 153 年逐月的历史模仿数据;CMIP_train.nc 中 [151,0:36,:,:] 为 CMIP6 第二个模式提供的第 1 - 第 3 年逐月的历史模仿数据;…,
CMIP_train.nc 中 [2265,0:36,:,:] 为 CMIP5 第一个模式提供的第 1 - 第 3 年逐月的历史模仿数据;…,
CMIP_train.nc 中 [2405,0:36,:,:] 为 CMIP5 第二个模式提供的第 1 - 第 3 年逐月的历史模仿数据;…,
CMIP_train.nc 中 [4644,0:36,:,:] 为 CMIP5 第 17 个模式提供的第 140- 第 142 年逐月的历史模仿数据。其中每个样本第三、第四维度别离代表经纬度(南纬 55 度北纬 60 度,东经 0360 度),所有数据的经纬度范畴雷同。
CMIP_path       = './data/CMIP_train.nc'
CMIP_trans_path = './data'
nc_CMIP  = Dataset(CMIP_path,'r') 
nc_CMIP.variables.keys()
dict_keys(['sst', 't300', 'ua', 'va', 'year', 'month', 'lat', 'lon'])



nc_CMIP['t300'][:].shape
(4645, 36, 24, 72)



year_month_index = []

years              = np.array(nc_CMIP['year'][:])
months             = np.array(nc_CMIP['month'][:])
lats               = np.array(nc_CMIP['lat'][:])
lons               = np.array(nc_CMIP['lon'][:])

last_thre_years = 1000
for year in years:
    '''数据的起因,咱们'''
    if year >= 4645 - last_thre_years:
        for month in months:
            year_month_index.append('year_{}_month_{}'.format(year,month))

df_CMIP_sst  = pd.DataFrame({'year_month':year_month_index}) 
df_CMIP_t300 = pd.DataFrame({'year_month':year_month_index}) 
df_CMIP_ua   = pd.DataFrame({'year_month':year_month_index}) 
df_CMIP_va   = pd.DataFrame({'year_month':year_month_index})
  • 因为内存限度, 咱们临时取最初 1000 个 year 的数据
def trans_thre_df(df, vals, lats, lons, years, months, last_thre_years = 1000):
    '''(4645, 36, 24, 72) -- year, month,lat,lon''' 
    for j,lat_ in (enumerate(lats)):
#         print(j)
        for i,lon_ in enumerate(lons):
            c = 'lat_lon_{}_{}'.format(int(lat_),int(lon_))  
            v = []
            for y_,y in enumerate(years):
                '''数据的起因,咱们'''
                if y >= 4645 - last_thre_years:
                    for m_,m in  enumerate(months): 
                        v.append(vals[y_,m_,j,i])
            df = v
    return df
%%time
df_CMIP_sst  = trans_thre_df(df = df_CMIP_sst,  vals   = np.array(nc_CMIP['sst'][:]),  lats = lats, lons = lons, years = years, months = months)
df_CMIP_sst.to_csv(CMIP_trans_path + 'df_CMIP_sst.csv',index = None)
del df_CMIP_sst
gc.collect()

df_CMIP_t300 = trans_thre_df(df = df_CMIP_t300, vals   = np.array(nc_CMIP['t300'][:]), lats = lats, lons = lons, years = years, months = months)
df_CMIP_t300.to_csv(CMIP_trans_path + 'df_CMIP_t300.csv',index = None)
del df_CMIP_t300
gc.collect()

df_CMIP_ua   = trans_thre_df(df = df_CMIP_ua,   vals   = np.array(nc_CMIP['ua'][:]),   lats = lats, lons = lons, years = years, months = months)
df_CMIP_ua.to_csv(CMIP_trans_path + 'df_CMIP_ua.csv',index = None)
del df_CMIP_ua
gc.collect()

df_CMIP_va   = trans_thre_df(df = df_CMIP_va,   vals   = np.array(nc_CMIP['va'][:]),   lats = lats, lons = lons, years = years, months = months)
df_CMIP_va.to_csv(CMIP_trans_path + 'df_CMIP_va.csv',index = None)
del df_CMIP_va
gc.collect()
(36036, 1729)


3. 数据建模

工具包导入 & 数据读取

工具包导入

import pandas as pd
import numpy  as np
import tensorflow as tf
from tensorflow.keras.optimizers import Adam 
import joblib
from netCDF4 import Dataset
import netCDF4 as nc
import gc
from   sklearn.metrics import mean_squared_error
import numpy as np
from tensorflow.keras.callbacks import LearningRateScheduler, Callback
import tensorflow.keras.backend as K
from tensorflow.keras.layers import *
from tensorflow.keras.models import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.callbacks import *
from tensorflow.keras.layers import Input 
%matplotlib inline 

数据读取

SODA_label 解决
  1. 标签含意
标签数据为 Nino3.4 SST 异样指数,数据维度为(year,month)。CMIP(SODA)_train.nc 对应的标签数据以后时刻 Nino3.4 SST 异样指数的三个月滑动平均值,因而数据维度与维度介绍同训练数据统一
注:三个月滑动平均值为以后月与将来两个月的平均值。
  1. 将标签转化为咱们相熟的 pandas 模式
df_SODA_label = pd.read_csv('./data/df_SODA_label.csv')
df_CMIP_label = pd.read_csv('./data/df_CMIP_label.csv') 

训练集验证集构建

df_SODA_label['year']  = df_SODA_label['year_month'].apply(lambda x: x[:x.find('m') - 1])
df_SODA_label['month'] = df_SODA_label['year_month'].apply(lambda x: x[x.find('m') :])

df_train = pd.pivot_table(data = df_SODA_label, values = 'label',index = 'year', columns = 'month')
year_new_index    = ['year_{}'.format(i+1)  for i in range(df_train.shape[0])]
month_new_columns = ['month_{}'.format(i+1) for i in range(df_train.shape[1])]
df_train = df_train[month_new_columns].loc[year_new_index]

模型构建

MLP 框架
def RMSE(y_true, y_pred):
    return tf.sqrt(tf.reduce_mean(tf.square(y_true - y_pred)))

def RMSE_fn(y_true, y_pred):
    return np.sqrt(np.mean(np.power(np.array(y_true, float).reshape(-1, 1) - np.array(y_pred, float).reshape(-1, 1), 2)))

def build_model(train_feat, test_feat): #allfeatures, 
    inp    = Input(shape=(len(train_feat)))  
    
    x = Dense(1024, activation='relu')(inp)  
    x = Dropout(0.25)(x) 
    x = Dense(512, activation='relu')(x)   
    x = Dropout(0.25)(x)  
    output = Dense(len(test_feat), activation='linear')(x)   
    model  = Model(inputs=inp, outputs=output)

    adam = tf.optimizers.Adam(lr=1e-3,beta_1=0.99,beta_2 = 0.99) 
    model.compile(optimizer=adam, loss=RMSE)

    return model
模型训练
feature_cols = ['month_{}'.format(i+1) for i in range(12)]
label_cols   = ['month_{}'.format(i+1) for i in range(12, df_train.shape[1])] 
model_mlp = build_model(feature_cols, label_cols)
model_mlp.summary()
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 12)]              0         
_________________________________________________________________
dense (Dense)                (None, 1024)              13312     
_________________________________________________________________
dropout (Dropout)            (None, 1024)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               524800    
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 24)                12312     
=================================================================
Total params: 550,424
Trainable params: 550,424
Non-trainable params: 0
_________________________________________________________________


tr_len = int(df_train.shape[0] * 0.8)
tr_fea     = df_train[feature_cols].iloc[:tr_len,:].copy()
tr_label   = df_train[label_cols].iloc[:tr_len,:].copy()
 
val_fea     = df_train[feature_cols].iloc[tr_len:,:].copy()
val_label   = df_train[label_cols].iloc[tr_len:,:].copy() 


model_weights = './user_data/model_data/model_mlp_baseline.h5'

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)
history        = model_mlp.fit(tr_fea.values, tr_label.values,
                    validation_data=(val_fea.values, val_label.values),
                    batch_size=4096, epochs=200,
                    callbacks=[plateau, checkpoint, early_stopping],
                    verbose=2) 
Epoch 00053: ReduceLROnPlateau reducing learning rate to 6.25000029685907e-05.
1/1 - 0s - loss: 0.6567 - val_loss: 0.6030
Epoch 54/200
1/1 - 0s - loss: 0.6571 - val_loss: 0.6030
Epoch 55/200
1/1 - 0s - loss: 0.6541 - val_loss: 0.6030
Epoch 56/200
1/1 - 0s - loss: 0.6539 - val_loss: 0.6030
Epoch 57/200
1/1 - 0s - loss: 0.6477 - val_loss: 0.6030
Epoch 58/200

Epoch 00058: ReduceLROnPlateau reducing learning rate to 3.125000148429535e-05.
1/1 - 0s - loss: 0.6498 - val_loss: 0.6029
Epoch 59/200
1/1 - 0s - loss: 0.6451 - val_loss: 0.6029
Epoch 60/200
1/1 - 0s - loss: 0.6458 - val_loss: 0.6029
Metrics
def rmse(y_true, y_preds):
    return np.sqrt(mean_squared_error(y_pred = y_preds, y_true = y_true))

def score(y_true, y_preds):
    accskill_score = 0
    rmse_score     = 0
    a = [1.5] * 4 + [2] * 7 + [3] * 7 + [4] * 6
    y_true_mean = np.mean(y_true,axis=0) 
    y_pred_mean = np.mean(y_true,axis=0)

    for i in range(24): 
        fenzi = np.sum((y_true[:,i] -  y_true_mean[i]) *(y_preds[:,i] -  y_pred_mean[i]) ) 
        fenmu = np.sqrt(np.sum((y_true[:,i] -  y_true_mean[i])**2) * np.sum((y_preds[:,i] -  y_pred_mean[i])**2) ) 
        cor_i= fenzi / fenmu
    
        accskill_score += a[i] * np.log(i+1) * cor_i
        
        rmse_score += rmse(y_true[:,i], y_preds[:,i]) 
    return  2 / 3.0 * accskill_score - rmse_score
y_val_preds = model_mlp.predict(val_fea.values, batch_size=1024)
print('score', score(y_true = val_label.values, y_preds = y_val_preds))

4. 模型预测

模型构建

在下面的局部,咱们曾经训练好了模型,接下来就是提交模型并在线上进行预测,这块能够分为三步:

  • 导入模型;
  • 读取测试数据并且进行预测;
  • 生成提交所需的版本;
import tensorflow as tf
import tensorflow.keras.backend as K
from tensorflow.keras.layers import *
from tensorflow.keras.models import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.callbacks import *
from tensorflow.keras.layers import Input 
import numpy as np
import os
import zipfile

def RMSE(y_true, y_pred):
    return tf.sqrt(tf.reduce_mean(tf.square(y_true - y_pred)))

def build_model(train_feat, test_feat): #allfeatures, 
    inp    = Input(shape=(len(train_feat)))  
    
    x = Dense(1024, activation='relu')(inp)  
    x = Dropout(0.25)(x) 
    x = Dense(512, activation='relu')(x)   
    x = Dropout(0.25)(x)  
    output = Dense(len(test_feat), activation='linear')(x)   
    model  = Model(inputs=inp, outputs=output)

    adam = tf.optimizers.Adam(lr=1e-3,beta_1=0.99,beta_2 = 0.99) 
    model.compile(optimizer=adam, loss=RMSE)

    return model

feature_cols = ['month_{}'.format(i+1) for i in range(12)]
label_cols   = ['month_{}'.format(i+1) for i in range(12, 36)] 
model = build_model(train_feat=feature_cols, test_feat=label_cols)
model.load_weights('./user_data/model_data/model_mlp_baseline.h5')

模型预测


test_path = './tcdata/enso_round1_test_20210201/'

### 0. 模仿线上的测试汇合
# for i in range(10):
#     x = np.random.random(12) 
#     np.save(test_path + "{}.npy".format(i+1),x)

### 1. 测试数据读取
files = os.listdir(test_path)
test_feas_dict = {}
for file in files:
    test_feas_dict[file] = np.load(test_path + file)
    
### 2. 后果预测
test_predicts_dict = {}
for file_name,val in test_feas_dict.items():
    test_predicts_dict[file_name] = model.predict(val.reshape([-1,12]))
#     test_predicts_dict[file_name] = model.predict(val.reshape([-1,12])[0,:])

### 3. 存储预测后果
for file_name,val in test_predicts_dict.items(): 
    np.save('./result/' + file_name,val)

打包到 run.sh 目录下方

# 打包目录为 zip 文件
def make_zip(source_dir='./result/', output_filename = 'result.zip'):
    zipf = zipfile.ZipFile(output_filename, 'w')
    pre_len = len(os.path.dirname(source_dir))
    source_dirs = os.walk(source_dir)
    print(source_dirs)
    for parent, dirnames, filenames in source_dirs:
        print(parent, dirnames)
        for filename in filenames:
            if '.npy' not in filename:
                continue
            pathfile = os.path.join(parent, filename)
            arcname = pathfile[pre_len:].strip(os.path.sep)   #相对路径
            zipf.write(pathfile, arcname)
    zipf.close()
make_zip() 

我的项目链接以及码源

云端链接:
人工智能翻新挑战赛陆地气象预测 Baseline[4]完整版

更多文章请关注公重号:汀丶人工智能

5. 晋升方向

模型性能晋升能够参考:在下述根底上改变

“AI Earth”人工智能翻新挑战赛:助力精准气象和陆地预测 Baseline[2]:数据探索性剖析(温度风场可视化)、CNN+LSTM 模型建模

“AI Earth”人工智能翻新挑战赛:助力精准气象和陆地预测 Baseline[3]:TCNN+RNN 模型、SA-ConvLSTM 模型

  • 模型角度:咱们只应用了简略的 MLP 模型进行建模,能够思考应用其它的更加 fancy 的模型进行尝试;
  • 数据层面:构建一些特色或者对数据进行一些数据变换等;
  • 针对损失函数设计各种 trick 的晋升技巧;
退出移动版