该系列的Jupyter放在下方:
RNN训练速度较慢,请选择算力较强的计算机。
由于RNN的训练过程严格遵循时序关系,无法像CNN一样并行计算,所以训练速度较慢。
时间反向传播
训练RNN的流程:
- 将RNN按照时间逐步展开
- 使用常规的误差反向传播
这种策略称为“时间反向传播”(BackPropagation Through Time, BPTT)。
预测时间序列
当数据是每个时间步长一个或多个值的序列,该数据成为时间序列。
eg:
- 网站每小时的用户活跃数
- 城市每日温度
- 使用多个指标来评估每个季度公司的财务状况
时间序列又可以分成单变量时间序列和多变量时间序列。例如在预测财务状况时,每个时间步长可能有多个值,如公司收入、债务情况等。
RNN的两个常用任务:预测和插值。
生成时间序列
为了方便,我们就不找真实数据了,而是自己创造一个相对随机而有点规律的时间序列。
生成时间序列的函数如下:
# 该函数返回一个[批处理大小, 时间步长, 维度]的Numpy数组
def generate_time_series(batch_size, n_steps):
freq1, freq2, offsets1, offsets2 = np.random.rand(4, batch_size, 1)
time = np.linspace(0, 1, n_steps)
series = 0.5 * np.sin((time - offsets1) * (freq1 * 10 + 10)) # wave 1
series += 0.2 * np.sin((time - offsets2) * (freq2 * 20 + 20)) # + wave 2
series += 0.1 * (np.random.rand(batch_size, n_steps) - 0.5) # + noise
return series[..., np.newaxis].astype(np.float32)
随机生成的时间序列可视化如下:

将生成的数据集按照7:2:1的比例划分:
np.random.seed(42)
n_steps = 50 #每个序列长度
# 训练:验证:测试=7:2:1
series = generate_time_series(10000, n_steps + 1)
X_train, y_train = series[:7000, :n_steps], series[:7000, -1]
X_valid, y_valid = series[7000:9000, :n_steps], series[7000:9000, -1]
X_test, y_test = series[9000:, :n_steps], series[9000:, -1]
搭建简单RNN
我们搭建一个只有单个神经元的单层RNN。我们不需要像CNN一样指定序列长度,因为RNN可以处理任意数量的时间步长,所以长度我设置为了None
。SimpleRNN默认使用双曲正切激活函数。
首先写一个绘制损失曲线的函数:
def plot_learning_curves(loss, val_loss):
plt.plot(np.arange(len(loss)) + 0.5, loss, "b.-", label="Training loss")
plt.plot(np.arange(len(val_loss)) + 1, val_loss, "r.-", label="Validation loss")
plt.gca().xaxis.set_major_locator(mpl.ticker.MaxNLocator(integer=True))
plt.axis([1, 20, 0, 0.05])
plt.legend(fontsize=14)
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.grid(True)
然后搭建简单RNN进行训练和预测:
np.random.seed(42)
tf.random.set_seed(42)
model = keras.models.Sequential([
keras.layers.SimpleRNN(1, input_shape=[None, 1])
])
optimizer = keras.optimizers.Adam(learning_rate=0.005)
model.compile(loss="mse", optimizer=optimizer)
history = model.fit(X_train, y_train, epochs=20,
validation_data=(X_valid, y_valid))
训练完成后通过均方误差对模型进行评估:
model.evaluate(X_valid, y_valid)
0.010885455287992955
绘制损失曲线:
plot_learning_curves(history.history["loss"], history.history["val_loss"])
plt.show()
图像如下:

绘制预测值和目标值:
y_pred = model.predict(X_valid)
plot_series(X_valid[0, :, 0], y_valid[0, 0], y_pred[0, 0])
plt.show()

Comments | NOTHING