titlegetatitle 2018-10-18
对天气进行建模通常是一个非常复杂的主题,需要深入理解物理,数学和现代计算。影响天气的因素有很多:温度,压力,空气和水汽/水蒸气的流体流动,地球的旋转运动:所有在我们生活的大气中起重要作用的元素。天气预报的基础依赖于Navier-Stokes方程 - 通过将牛顿第二运动定律应用于流体运动而产生的三个简单微分方程。这些方程式涉及动量守恒。虽然方程式可能很简单,但解决它们以在高空间分辨率下提供准确的天气预测是非常困难的并且计算成本很高。
这是因为为了获得准确的天气预报,需要在更好和更精细的网格中测量不同的参数(温度,压力等)并将它们输入到超级计算机中,然后将这些数字处理以找出最可能的情况。问题是气象学家需要平衡模型精度和计算时间。如果您需要高度精确的模型,那么最终可能会在事件发生后输出其结果的模型。如果您需要更快的结果,您的模型精度会显着降低。
进入深度学习模型。深度学习模型的想法是学习卫星数据或雷达数据,甚至只是温度记录,天气模式,并使用它们来训练算法。由于需要大量数据来正确训练算法,因此训练本身是很耗时的。但是一旦训练完成并且深度神经网络已经“学习”了数据中的模式,计算机就可以基于对大气条件的实时观察非常快速地生成预测。这对于预测接下来几个小时的事件至关重要,特别是在传统模型的运行计算成本高且结果很慢的情况下。
使用的方法是卷积LSTM模型,已经证明在气象预测中非常准确。卷积LSTM在LSTM单元内添加卷积运算。这结合了ConvNets的模式识别和纯LSTM网络的“记忆”特性。因此,该算法有望在雷达图像序列中找到模式,然后预测预期的降雨量。
对于这个项目,我选择的数据集来自CIKM 2017竞赛(https://tianchi.aliyun.com/competition/information.htm?raceId=231596&_lang=en_US),该竞赛提供10,000个雷达图像序列的训练集。每个序列由15个具有4个波段的图像组成。这四个波段是不同大气高度(0.5,1.5,2.5和3.5 km)的雷达扫描。提供两个不同的测试集,每个测试集由另外2,000个序列组成。
该项目的挑战之一是使工作所需的大量存储空间。未压缩的数据是3.5 GB,一旦解压缩它需要~24 GB并且是字符串文本格式。将数据转换为HDF5格式,其中每个图像存储在适当的数组切片中,数据集达到~70 GB。为了能够处理所有这些数据,一切都可在亚马逊ec2实例服务器上远程运行。
CIKM挑战本身只对雷达图像中心位置的降雨量感兴趣。为了模拟降雨量,实施了如下所示的keras convLSTM网络。Python代码如下:
def fn_get_model_convLSTM_2(): model = Sequential() model.add(ConvLSTM2D(filters=32, kernel_size=(7, 7), input_shape=(None, 101, 101, 1), return_sequences=True, go_backwards=True, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.4, recurrent_dropout=0.2 )) model.add(BatchNormalization()) model.add(ConvLSTM2D(filters=16, kernel_size=(7, 7), return_sequences=True, go_backwards=True, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.4, recurrent_dropout=0.2 )) model.add(BatchNormalization()) model.add(ConvLSTM2D(filters=8, kernel_size=(7, 7), return_sequences=False, go_backwards=True, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.3, recurrent_dropout=0.2 )) model.add(BatchNormalization()) model.add(Conv2D(filters=1, kernel_size=(1, 1), activation='relu', data_format='channels_last')) model.add(MaxPooling2D(pool_size=(4, 4), padding='same')) model.add(Flatten()) model.add(BatchNormalization()) model.add(Dropout(0.25)) model.add(Dense(512, activation='relu')) model.add(BatchNormalization()) model.add(Dropout(0.4)) model.add(Dense(512, activation='relu')) model.add(BatchNormalization()) model.add(Dropout(0.4)) model.add(Dense(128, activation='relu')) model.add(BatchNormalization()) model.add(Dropout(0.4)) model.add(Dense(1, activation='linear')) print(model.summary()) return model
这基本上由dense 网络顶部的3层LSTM卷积组成,然后返回单个值 - 降雨量。由于数据集仍然太大,我决定只使用40%的训练集训练算法 - 这使我可以减少相当多的计算时间。在剩余的60%的训练集中,选择500个序列(5%)作为验证集。
平均而言,在两个测试集上计算的均方根误差为13.43!
这部分工作既有趣又可以看到这种算法在尝试预测下一个图像帧时如何执行。图像预测的算法Python代码如下:
def fn_get_model_convLSTM_tframe_5(): model = Sequential() model.add(ConvLSTM2D(filters=64, kernel_size=(7, 7), input_shape=(None, 101, 101, 1), padding='same', return_sequences=True, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.3, recurrent_dropout=0.3, go_backwards=True )) model.add(BatchNormalization()) model.add(ConvLSTM2D(filters=32, kernel_size=(7, 7), padding='same', return_sequences=True, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.4, recurrent_dropout=0.3, go_backwards=True )) model.add(BatchNormalization()) model.add(ConvLSTM2D(filters=32, kernel_size=(7, 7), padding='same', return_sequences=True, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.4, recurrent_dropout=0.3, go_backwards=True )) model.add(BatchNormalization()) model.add(ConvLSTM2D(filters=32, kernel_size=(7, 7), padding='same', return_sequences=False, activation='tanh', recurrent_activation='hard_sigmoid', kernel_initializer='glorot_uniform', unit_forget_bias=True, dropout=0.4, recurrent_dropout=0.3, go_backwards=True )) model.add(BatchNormalization()) model.add(Conv2D(filters=1, kernel_size=(1, 1), activation='sigmoid', padding='same', data_format='channels_last')) print(model.summary()) return model
这个神经网络也接受了40%的数据训练,下面显示了预测帧的样子:
来自卷积LSTM网络的预测。前5帧是真实数据,其余是预测图像
注意,为了预测帧5,使用了真实图像,但是当我们沿着预测移动时,在下一个预测帧中使用越来越多已经预测的图像。这导致在误差传播方面的级联效应。下图显示了帧数增加时错误的传播方式。
预测与真实雷达图像的并排比较
可以清楚地看到,对于短期天气预测,使用机器学习有很大的前景。这不仅可以提高预测的准确性,还可以在诸如山洪等灾难性事件的情况下挽救生命。
另一方面,深度神经网络的力量也在该项目中得到了强有力的证明。详细代码:https://github.com/TeaPearce/precipitation-prediction-convLSTM-keras/blob/master/precip_v09.py