温度预测示例
首先将相应数据集中数据取出
import os
fname = os.path.join("jena_climate_2009_2016.csv")
with open(fname) as f:
data = f.read()
lines = data.split("\n")
header = lines[0].split(",")
lines = lines[1:]
print(header)
print(len(lines))
利用split(",")函数,将文件读取出来的数据一块一块地送入lines中
解析数据
import numpy as np
temperature = np.zeros((len(lines),))
raw_data = np.zeros((len(lines), len(header) - 1))
for i, line in enumerate(lines):
values = [float(x) for x in line.split(",")[1:]]
temperature[i] = values[1]
raw_data[i, :] = values[:]
在此处利用np.zeros先初始化一个numpy的数组,随后利用循环将所有文件中的数据逐行送入数组当中
准备数据
mean = raw_data[:num_train_samples].mean(axis=0)
raw_data -= mean
std = raw_data[:num_train_samples].std(axis=0)
raw_data /= std
使用标准化将数据的范围缩小
利用timeseries_dataset_from_array()生成适用于时间序列预测的窗口数据集
import numpy as np
from tensorflow import keras
int_sequence = np.arange(10) // 生成0-9的整数数组
dummy_dataset = keras.utils.timeseries_dataset_from_array(
data=int_sequence[:-3], // 取0-6来作为抽样数据
targets=int_sequence[3:], // 对于data[N]开头的序列,其目标是data[N+3]
sequence_length=3, // 序列长度是3个时间步
batch_size=2, // 序列批量大小为2
)
for inputs, targets in dummy_dataset:
for i in range(inputs.shape[0]):
print([int(x) for x in inputs[i]], int(targets[i]))
利用此函数我们可以生成对应的“利用前几个小时的数据 预测 将来某个时间的数据”的序列
借此我们生成用于处理时间序列数据的训练、验证以及测试集
// 采样频率是每小时一个数据点,相当于原数据集中每6个数据点我们保留一个
sampling_rate = 6
// 给定过去5天的观测数据(120小时)
sequence_length = 120
// 预测目标是序列后,24小时的温度
delay = sampling_rate * (sequence_length + 24 - 1)
batch_size = 256
train_dataset = keras.utils.timeseries_dataset_from_array(
raw_data[:-delay],
targets=temperature[delay:],
sampling_rate=sampling_rate,
sequence_length=sequence_length,
shuffle=True,
batch_size=batch_size,
start_index=0,
end_index=num_train_samples)
val_dataset = keras.utils.timeseries_dataset_from_array(
raw_data[:-delay],
targets=temperature[delay:],
sampling_rate=sampling_rate,
sequence_length=sequence_length,
shuffle=True,
batch_size=batch_size,
start_index=num_train_samples,
end_index=num_train_samples + num_val_samples)
test_dataset = keras.utils.timeseries_dataset_from_array(
raw_data[:-delay],
targets=temperature[delay:],
sampling_rate=sampling_rate,
sequence_length=sequence_length,
shuffle=True,
batch_size=batch_size,
start_index=num_train_samples + num_val_samples)
每个此类数据集都会生成一个元组(samples, targets),其中samples是包含256个样本的批量,每个样本包含连续120小时的输入数据,而targets是包含相应的256个所需预测的目标温度的数组。
由于样本被随机打乱,所以samples[0]和samples[1]在时间上可能不接近
建立基本机器学习模型
为了确保研究复杂模型的方向,我们可以先尝试简单且计算代价小的机器学习模型
from tensorflow import keras
from tensorflow.keras import layers
inputs = keras.Input(shape=(sequence_length, raw_data.shape[-1]))
x = layers.Flatten()(inputs)
x = layers.Dense(16, activation="relu")(x)
outputs = layers.Dense(1)(x)
model = keras.Model(inputs, outputs)
callbacks = [
keras.callbacks.ModelCheckpoint("jena_dense.keras",
save_best_only=True)
]
model.compile(optimizer="rmsprop", loss="mse", metrics=["mae"])
history = model.fit(train_dataset,
epochs=10,
validation_data=val_dataset,
callbacks=callbacks)
model = keras.models.load_model("jena_dense.keras")
print(f"Test MAE: {model.evaluate(test_dataset)[1]:.2f}")
首先将数据展平,然后是两个Dense层,对于回归问题,其最后一个层我们通常没有激活函数
一维卷积模型
使用初始窗口长度为24的卷积层,每次查看24小时的数据(一个周期)。
我们对序列进行下采样时,相应地减小窗口尺寸
inputs = keras.Input(shape=(sequence_length, raw_data.shape[-1]))
x = layers.Conv1D(8, 24, activation="relu")(inputs)
x = layers.MaxPooling1D(2)(x)
x = layers.Conv1D(8, 12, activation="relu")(x)
x = layers.MaxPooling1D(2)(x)
x = layers.Conv1D(8, 6, activation="relu")(x)
x = layers.GlobalAveragePooling1D()(x)
outputs = layers.Dense(1)(x)
model = keras.Model(inputs, outputs)
callbacks = [
keras.callbacks.ModelCheckpoint("jena_conv.keras",
save_best_only=True)
]
model.compile(optimizer="rmsprop", loss="mse", metrics=["mae"])
history = model.fit(train_dataset,
epochs=10,
validation_data=val_dataset,
callbacks=callbacks)
model = keras.models.load_model("jena_conv.keras")
print(f"Test MAE: {model.evaluate(test_dataset)[1]:.2f}")
以上采用密集神经网络和卷积神经网络处理该问题的效果都不是很好,但这并不意味着机器学习不适用于该问题。
密集连接网络将时间序列展平,从输入数据中去除了时间的概念
卷积神经网络对每段数据都用同样的方式处理,甚至还应用了汇聚运算,这会破坏顺序信息
对于天气时间序列而言,它是一个序列,其中因果关系和顺序都很重要。有一类专门处理这种数据的神经网络架构叫做RNN。此处我们先来查看RNN的变体LSTM的一个简短案例
inputs = keras.Input(shape=(sequence_length, raw_data.shape[-1]))
x = layers.LSTM(16)(inputs)
outputs = layers.Dense(1)(x)
model = keras.Model(inputs, outputs)
callbacks = [
keras.callbacks.ModelCheckpoint("jena_lstm.keras",
save_best_only=True)
]
model.compile(optimizer="rmsprop", loss="mse", metrics=["mae"])
history = model.fit(train_dataset,
epochs=10,
validation_data=val_dataset,
callbacks=callbacks)
model = keras.models.load_model("jena_lstm.keras")
print(f"Test MAE: {model.evaluate(test_dataset)[1]:.2f}")
此LSTM模型在温度预测任务上的性能明显优于此前的神经网络
在此前的神经网络中,它们都有一个显著特征,没有记忆。它们对于每个输入都是单独处理的,在输入之间没有保存任何状态。这些网络想要处理数据点的序列或时间序列就需要一次性将整个序列输入其中,将整个序列转换为单个数据点。
比如在此前的密集连接网络中就是将5天的数据展平为一个大向量然后一次性处理。这样的网络被称为“前馈网络”
RNN则是一种具有内部环路的神经网络,在处理两个彼此独立的序列之间,RNN的状态会被重置,我们在此时仍然可以把一个序列看作单个数据点,即神经网络的单个输入,不同的是,这个数据点不是一步处理完,而是不断地被神经网络进行循环操作。