时间序列:使用LSTM模型进行天气预测 |
您所在的位置:网站首页 › 多变量时间序列分类数据分析法 › 时间序列:使用LSTM模型进行天气预测 |
本教程介绍了使用递归神经网络(RNN)进行时间序列预测的流程。包括两个部分:首先,预测单变量时间序列,然后预测多变量时间序列。 文章目录 1. 数据集介绍2. 单变量单步输出预测2.1 数据标准化2.2 样本划分2.3 绘制曲线2.4 基准测试2.5 LSTM 建模 3. 多变量多步输出预测3.1 数据标准化3.2 单步预测模型3.3 多步预测模型 数据集和代码下载代码环境: python version: 3.7.6 tensorflow version: 2.1.0导入必要的包 import tensorflow as tf import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np import os import pandas as pd mpl.rcParams['figure.figsize'] = (8, 6) mpl.rcParams['axes.grid'] = False 1. 数据集介绍使用 Max Planck Institute for Biogeochemistry 的天气时间序列数据集 。 该数据集包含14个不同的特征,例如气温,大气压力和湿度。从2003年开始,每10分钟收集一次。为了提高效率,本文仅使用2009年至2016年之间收集的数据。 1.下载数据集 zip_path = tf.keras.utils.get_file( origin='https://storage.googleapis.com/tensorflow/tf-keras-datasets/jena_climate_2009_2016.csv.zip', fname='jena_climate_2009_2016.csv.zip', extract=True) csv_path, _ = os.path.splitext(zip_path)2.加载数据集 df = pd.read_csv(csv_path) df.head()
给定一个特定的时间,假设要预测未来6小时的温度。为了做出此预测,选择使用5天的观察时间。因此,创建一个包含最后720(5x144)个观测值的窗口以训练模型。 下面的函数返回上述时间窗以供模型训练。参数 history_size 是过去信息的滑动窗口大小。target_size 是模型需要学习预测的未来时间步,也作为需要被预测的标签。 下面使用数据的前300,000行当做训练数据集,其余的作为验证数据集。总计约2100天的训练数据。 TRAIN_SPLIT = 300000设置种子以确保可重复性。 tf.random.set_seed(13) 2. 单变量单步输出预测首先,使用一个特征(温度)训练模型,并在使用该模型做预测。 1.从数据集中提取温度 uni_data = df['T (degC)'] uni_data.index = df['Date Time'] uni_data.head()2.观察一下这些数据随时间变化的情况 uni_data.plot(subplots=True)在训练神经网络之前缩放特征很重要。标准化是通过减去平均值并除以每个特征的标准偏差来进行缩放的一种常用方法。也可以使用 tf.keras.utils.normalize 将值缩放到[0,1]范围内。 uni_data = uni_data.values uni_train_mean = uni_data[:TRAIN_SPLIT].mean() uni_train_std = uni_data[:TRAIN_SPLIT].std() uni_data = (uni_data-uni_train_mean)/uni_train_std 2.2 样本划分现在为单变量模型创建数据。本部分为模型提供最后20个温度观测值,预测下一个时间步长的温度。 univariate_past_history = 20 univariate_future_target = 0 # shape 分别为:(299980, 20, 1);(299980,) x_train_uni, y_train_uni = univariate_data(uni_data, 0, TRAIN_SPLIT, univariate_past_history, univariate_future_target) x_val_uni, y_val_uni = univariate_data(uni_data, TRAIN_SPLIT, None, univariate_past_history, univariate_future_target)输出: Single window of past history [[-1.99766294] [-2.04281897] [-2.05439744] [-2.0312405 ] [-2.02660912] [-2.00113649] [-1.95134907] [-1.95134907] [-1.98492663] [-2.04513467] [-2.08334362] [-2.09723778] [-2.09376424] [-2.09144854] [-2.07176515] [-2.07176515] [-2.07639653] [-2.08913285] [-2.09260639] [-2.10418486]] Target temperature to predict -2.1041848598100876 2.3 绘制曲线现在已经创建了数据,看一个例子。提供给网络的信息以蓝色表示,并且它必须预测红叉处的值。 def create_time_steps(length): return list(range(-length, 0)) def show_plot(plot_data, delta, title): labels = ['History', 'True Future', 'Model Prediction'] marker = ['.-', 'rx', 'go'] time_steps = create_time_steps(plot_data[0].shape[0]) # 横轴刻度 if delta: future = delta else: future = 0 plt.title(title) for i, x in enumerate(plot_data): if i: plt.plot(future, plot_data[i], marker[i], markersize=10, label=labels[i]) else: plt.plot(time_steps, plot_data[i].flatten(), marker[i], label=labels[i]) plt.legend() plt.xlim([time_steps[0], (future+5)*2]) plt.xlabel('Time-Step') return plt在继续训练模型之前,先设置一个简单的基准。在给定输入点的情况下,基线方法将查看所有历史记录,并预测下一个点是最近20个观测值的平均值。 def baseline(history): return np.mean(history) show_plot([x_train_uni[0], y_train_uni[0], baseline(x_train_uni[0])], 0, 'Baseline Prediction Example')递归神经网络(RNN)是一种非常适合时间序列数据的神经网络。RNN分步处理时间序列,维护内部状态,以汇总所见信息。 使用 tf.data 来随机整理,批处理和缓存数据集。 BATCH_SIZE = 256 BUFFER_SIZE = 10000 train_univariate = tf.data.Dataset.from_tensor_slices((x_train_uni, y_train_uni)) train_univariate = train_univariate.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat() val_univariate = tf.data.Dataset.from_tensor_slices((x_val_uni, y_val_uni)) val_univariate = val_univariate.batch(BATCH_SIZE).repeat()批处理后的数据shape: 让我们现在训练模型。由于数据集的大小很大,为了节省时间,每个epoch将仅使用200个step(batch_size=256,所以一个epoch使用 200 * 256 个数据),而不是像通常那样遍历完整的训练数据。 EVALUATION_INTERVAL = 200 EPOCHS = 10 simple_lstm_model.fit(train_univariate, epochs=EPOCHS, steps_per_epoch=EVALUATION_INTERVAL, validation_data=val_univariate, validation_steps=50)预测: for x, y in val_univariate.take(3): plot = show_plot([x[0].numpy(), y[0].numpy(), simple_lstm_model.predict(x)[0]], 0, 'Simple LSTM model') plot.show()
原始数据集包含十四个特征。为简单起见,本节仅考虑原始的十四个中的三个。使用的功能是气温,大气压力和空气密度。 要使用更多特征,将其名称添加到此列表中即可。 features_considered = ['p (mbar)', 'T (degC)', 'rho (g/m**3)']查看数据: features = df[features_considered] features.index = df['Date Time'] features.head()
单步预测任务中,模型将根据提供的某些历史记录来学习预测未来的单个点。 下面的函数实现了滑动窗口截取数据,它根据给定的窗口宽度对过去的观测值进行采样。 def multivariate_data(dataset, target, start_index, end_index, history_size, target_size, step, single_step=False): data = [] labels = [] start_index = start_index + history_size if end_index is None: end_index = len(dataset) - target_size for i in range(start_index, end_index): indices = range(i-history_size, i, step) # step表示间隔采样步长,6表示每个小时只使用一个采样值(原数据集每10分钟采集一次) data.append(dataset[indices]) if single_step: labels.append(target[i+target_size]) else: labels.append(target[i:i+target_size]) return np.array(data), np.array(labels)在本教程中,输入给网络最近五天的数据,即720个观测值。每隔一小时进行一次重采样,因为60分钟内不会发生剧烈变化。因此,120个重采样值表示最近五天的温度状况。对于单步预测模型,数据点的标签是未来12小时的温度。所以,使用之后72(12 * 6)个观测值作为标签。 past_history = 720 future_target = 72 STEP = 6 x_train_single, y_train_single = multivariate_data(dataset, dataset[:, 1], 0, TRAIN_SPLIT, past_history, future_target, STEP, single_step=True) x_val_single, y_val_single = multivariate_data(dataset, dataset[:, 1], TRAIN_SPLIT, None, past_history, future_target, STEP, single_step=True)划分数据集: train_data_single = tf.data.Dataset.from_tensor_slices((x_train_single, y_train_single)) train_data_single = train_data_single.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat() val_data_single = tf.data.Dataset.from_tensor_slices((x_val_single, y_val_single)) val_data_single = val_data_single.batch(BATCH_SIZE).repeat()训练: single_step_model = tf.keras.models.Sequential() single_step_model.add(tf.keras.layers.LSTM(32, input_shape=x_train_single.shape[-2:])) single_step_model.add(tf.keras.layers.Dense(1)) single_step_model.compile(optimizer=tf.keras.optimizers.RMSprop(), loss='mae') single_step_history = single_step_model.fit(train_data_single, epochs=EPOCHS, steps_per_epoch=EVALUATION_INTERVAL, validation_data=val_data_single, validation_steps=50)绘制损失曲线: def plot_train_history(history, title): loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(len(loss)) plt.figure() plt.plot(epochs, loss, 'b', label='Training loss') plt.plot(epochs, val_loss, 'r', label='Validation loss') plt.title(title) plt.legend() plt.show()测试 该模型具有每小时过去5天采样的三个特征的历史记录(120个数据点),因为目标是预测温度,所以该图仅显示过去的温度。预测是在未来一天进行的(因此,历史记录和预测之间存在差距)。 for x, y in val_data_single.take(3): plot = show_plot([x[0][:, 1].numpy(), y[0].numpy(), single_step_model.predict(x)[0]], 12, 'Single Step Prediction') plot.show()
在多步骤预测模型中,给定过去的采样值,预测未来一系列的值。对于多步骤模型,训练数据再次包括每小时采样的过去五天的记录。但是,这里的模型需要学习预测接下来12小时的温度。由于每10分钟采样一次数据,因此输出为72个预测值。 future_target = 72 x_train_multi, y_train_multi = multivariate_data(dataset, dataset[:, 1], 0, TRAIN_SPLIT, past_history, future_target, STEP) x_val_multi, y_val_multi = multivariate_data(dataset, dataset[:, 1], TRAIN_SPLIT, None, past_history, future_target, STEP)划分数据集 train_data_multi = tf.data.Dataset.from_tensor_slices((x_train_multi, y_train_multi)) train_data_multi = train_data_multi.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat() val_data_multi = tf.data.Dataset.from_tensor_slices((x_val_multi, y_val_multi)) val_data_multi = val_data_multi.batch(BATCH_SIZE).repeat()绘制样本点数据 def multi_step_plot(history, true_future, prediction): plt.figure(figsize=(12, 6)) num_in = create_time_steps(len(history)) num_out = len(true_future) plt.plot(num_in, np.array(history[:, 1]), label='History') plt.plot(np.arange(num_out)/STEP, np.array(true_future), 'bo', label='True Future') if prediction.any(): plt.plot(np.arange(num_out)/STEP, np.array(prediction), 'ro', label='Predicted Future') plt.legend(loc='upper left') plt.show() for x, y in train_data_multi.take(1): multi_step_plot(x[0], y[0], np.array([0]))由于此处的任务比先前的任务复杂一些,因此该模型现在由两个LSTM层组成。最后,由于需要预测之后12个小时的数据,因此Dense层将输出为72。 multi_step_model = tf.keras.models.Sequential() multi_step_model.add(tf.keras.layers.LSTM(32, return_sequences=True, input_shape=x_train_multi.shape[-2:])) multi_step_model.add(tf.keras.layers.LSTM(16, activation='relu')) multi_step_model.add(tf.keras.layers.Dense(72)) multi_step_model.compile(optimizer=tf.keras.optimizers.RMSprop(clipvalue=1.0), loss='mae')训练: multi_step_history = multi_step_model.fit(train_data_multi, epochs=EPOCHS, steps_per_epoch=EVALUATION_INTERVAL, validation_data=val_data_multi, validation_steps=50)训练日志: Epoch 1/10 200/200 [==============================] - 73s 363ms/step - loss: 0.5750 - val_loss: 0.3137 Epoch 2/10 200/200 [==============================] - 73s 367ms/step - loss: 0.4429 - val_loss: 0.2951 Epoch 3/10 200/200 [==============================] - 79s 393ms/step - loss: 0.3839 - val_loss: 0.2793 Epoch 4/10 200/200 [==============================] - 85s 426ms/step - loss: 0.3062 - val_loss: 0.2240 Epoch 5/10 200/200 [==============================] - 98s 488ms/step - loss: 0.2162 - val_loss: 0.2058 Epoch 6/10 200/200 [==============================] - 103s 514ms/step - loss: 0.2185 - val_loss: 0.2108 Epoch 7/10 200/200 [==============================] - 107s 537ms/step - loss: 0.2061 - val_loss: 0.2055 Epoch 8/10 200/200 [==============================] - 108s 539ms/step - loss: 0.2016 - val_loss: 0.1971 Epoch 9/10 200/200 [==============================] - 92s 462ms/step - loss: 0.2047 - val_loss: 0.1969 Epoch 10/10 200/200 [==============================] - 98s 490ms/step - loss: 0.1937 - val_loss: 0.1833绘制损失曲线: 预测: |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |