参考:
- https://tensorflow.google.cn/tutorials/structured_data/time_series
#显示所有列(参数设置为None代表显示所有行,也可以自行设置数字)
pd.set_option('display.max_columns',None)
#禁止自动换行(设置为Flase不自动换行,True反之)
pd.set_option('expand_frame_repr', False)
def loadWeatherData():
# 如果直接下载不了,将提前下载好的数据集放到指定的dataset目录(xx\.keras\datasets\)
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)
print(csv_path)
# 使用pands读取csv文件
df = pd.read_csv(csv_path)
print(df.head())
每10分钟一条记录 如上所示,每10分钟记录一次观察。这意味着,在一个小时内,你将有6次观察。同样,一天将包含144 (6x24)次观测。
给定一个特定的时间,假设你想预测未来6小时的温度。为了做出预测,你选择使用5天的观测。因此,您将创建一个包含最后720(5x144)次观察的窗口来训练模型。可能有许多这样的配置,这使这个数据集成为一个很好的实验对象。
下面的函数返回上面描述的模型训练时间窗口。参数history_size
是信息的过去窗口的大小。target_size是需要预测的标签。
def univariate_data(dataset, start_index, end_index, history_size, target_size):
'''
dataset:
start_index:
end_index:
history_size:
target_size:
@return: 特征, 标签
'''
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)
# Reshape data from (history_size,) to (history_size, 1)
data.append(np.reshape(dataset[indices], (history_size, 1)))
labels.append(dataset[i+target_size])
return np.array(data), np.array(labels)
1.2、单一变量预测
1.2.1、提取单一便利,此例中提取温度
# 抽取单一变量, 此处为温度,以供使用预测
uni_data = df['T (degC)']
# 线性的数据结构, series是一个一维数组
# Pandas 会默然用0到n-1来作为series的index, 但也可以自己指定index( 可以把index理解为dict里面的key )
uni_data.index = df['Date Time']
print(type(uni_data), '\n' ,uni_data.head())
数据可视化
#可视化
uni_data.plot(subplots=True)
plt.show()
Note: The mean and standard deviation should only be computed using the training data.
# 训练数据的平均及标准差
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
1.2.3、拆分训练集与验证数据集
# 训练集
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)
print ('Single window of past history')
print (x_train_uni[0])
print ('\n Target temperature to predict')
print (y_train_uni[0])
下图中蓝色线是给网络训练的数据, 红色叉叉是要预测的数据
def create_time_steps(length):
return list(range(-length, 0))
def baseline(history):
# 历史的平均值,作为预测的对比基线
return np.mean(history)
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
show_plot([x_train_uni[0], y_train_uni[0]], 0, 'Sample Example')
plt.show()
在继续训练模型之前,让我们首先设置一个简单的基线。给定一个输入点,基线方法查看所有历史记录,并预测下一个点是最近20个观察值的平均值。
show_plot([x_train_uni[0], y_train_uni[0], baseline(x_train_uni[0])], 0,
'Baseline Prediction Example')
plt.show()
让我们看看你是否可以使用递归神经网络来超越这个基线。
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()
# 创建一个LSTM模型
simple_lstm_model = tf.keras.models.Sequential([
tf.keras.layers.LSTM(8, input_shape=x_train_uni.shape[-2:]),
tf.keras.layers.Dense(1)
])
# 编译模型
simple_lstm_model.compile(optimizer='adam', loss='mae')
for x, y in val_univariate.take(1):
print(simple_lstm_model.predict(x).shape)
# 训练模型
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)
1.2.4.3、预测
# 预测
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()
# 原数据集中有14个特征, 此处为了方便,暂时只提取3个特征
features_considered = ['p (mbar)', 'T (degC)', 'rho (g/m**3)']
uni_data = df[features_considered]
# 线性的数据结构, series是一个一维数组
# Pandas 会默然用0到n-1来作为series的index, 但也可以自己指定index( 可以把index理解为dict里面的key )
uni_data.index = df['Date Time']
print(type(uni_data), '\n', uni_data.head())
# 可视化
uni_data.plot(subplots=True)
plt.show()
print(type(uni_data))
uni_data = uni_data.values
# 数据的平均及标准差 axis=0 按照列计算
uni_train_mean = uni_data[:TRAIN_SPLIT].mean(axis=0)
uni_train_std = uni_data[:TRAIN_SPLIT].std(axis=0)
# 归一化
uni_data = (uni_data - uni_train_mean) / uni_train_std
print(uni_data.shape, uni_train_mean.shape, uni_train_std.shape)
在单一步骤设置中,模型会根据提供的历史预测未来的单一点。
下面的函数执行与下面相同的窗口任务,但是,这里它根据给定的步长采样过去的观察结果。
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) # 五天数据, 每小时抽取一次, 本来5天720份数据,现在使用120份数据代替过去5天的历史
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)
1.3.2.1、构建输入数据
BATCH_SIZE = 256
BUFFER_SIZE = 10000
train_univariate = tf.data.Dataset.from_tensor_slices((x_train_single, y_train_single))
train_univariate = train_univariate.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()
val_univariate = tf.data.Dataset.from_tensor_slices((x_val_single, y_val_single))
val_univariate = val_univariate.batch(BATCH_SIZE).repeat()
1.3.2.2、模型
# 创建一个LSTM模型
simple_lstm_model = tf.keras.models.Sequential([
tf.keras.layers.LSTM(32, input_shape=x_train_single.shape[-2:]),
tf.keras.layers.Dense(1)
])
# 编译模型
simple_lstm_model.compile(optimizer=tf.keras.optimizers.RMSprop(), loss='mae')
for x, y in val_univariate.take(1):
print(simple_lstm_model.predict(x).shape, simple_lstm_model.predict(x))
# 训练模型
EVALUATION_INTERVAL = 200
EPOCHS = 10
history = simple_lstm_model.fit(train_univariate, epochs=EPOCHS,
steps_per_epoch=EVALUATION_INTERVAL,
validation_data=val_univariate, 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()
plot_train_history(history, 'Single Step Training and validation loss')
for x, y in val_univariate.take(3):
plot = show_plot([x[0][:, 1].numpy(), y[0].numpy(),
simple_lstm_model.predict(x)[0]], 12,
'Single Step Prediction')
plot.show()
在多步预测模型中,给定过去的历史,模型需要学习预测未来的一系列值。因此,与只预测单个未来点的单步模型不同,多步模型预测未来的序列。对于多步骤模型,训练数据同样由过去5天每小时采样的记录组成。然而,在这里,模型需要学习预测未来12小时的温度。由于每10分钟进行一次对话,因此输出72个预测。对于这个任务,需要相应地准备数据集,因此第一步只是再次创建它,但是使用不同的目标窗口。
1.3.3.1、构建输入数据
# 原数据集中有14个特征, 此处为了方便,暂时只提取3个特征
features_considered = ['p (mbar)', 'T (degC)', 'rho (g/m**3)']
uni_data = df[features_considered]
# 线性的数据结构, series是一个一维数组
# Pandas 会默然用0到n-1来作为series的index, 但也可以自己指定index( 可以把index理解为dict里面的key )
uni_data.index = df['Date Time']
uni_data = uni_data.values
# 数据的平均及标准差
uni_train_mean = uni_data[:TRAIN_SPLIT].mean(axis=0)
uni_train_std = uni_data[:TRAIN_SPLIT].std(axis=0)
# 归一化
dataset = (uni_data - uni_train_mean) / uni_train_std
print(dataset.shape, dataset[0: 1])
past_history = 720 # 过去5天总共有720份观测数据(每10分钟一次)
future_target = 72 # 由于60min不会出现大的巨变,所以进行抽样,每小时一次
STEP = 6 #
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)
print('Single window of past history : {}'.format(x_train_multi[0].shape))
print('\n Target temperature to predict : {}'.format(y_train_multi[0].shape))
BATCH_SIZE = 256
BUFFER_SIZE = 10000
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()
for x, y in train_data_multi.take(1):
multi_step_plot(x[0], y[0], np.array([0]))
在此图和随后的类似图中,每小时对历史和未来数据进行采样。
def multi_step_plot(history, true_future, prediction, STEP=6):
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()
# 构建模型
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')
EVALUATION_INTERVAL = 200
EPOCHS = 10
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)
loss
# loss
plot_train_history(multi_step_history, 'Multi-Step Training and validation loss')
# 预测
for x, y in val_data_multi.take(3):
multi_step_plot(x[0], y[0], multi_step_model.predict(x)[0])