Deep Learning with Python
这篇文章是我学习《Deep Learning with Python》(第二版,François Chollet 著) 时写的系列笔记之一。文章的内容是从 Jupyter notebooks 转成 Markdown 的,你可以去 GitHub 或 Gitee 找到原始的 .ipynb
笔记本。
你可以去这个网站在线阅读这本书的正版原文(英文)。这本书的作者也给出了配套的 Jupyter notebooks。
本文为 第6章 深度学习用于文本和序列 (Chapter 6. Deep learning for text and sequences) 的笔记之一。
文章目录
6.3 Advanced usage of recurrent neural networks
循环神经网络的高级用法
今回,我们通过一个实例,来了解循环神经网络的几个技巧:循环 dropout, 堆叠循环层,双向循环层。
温度预测问题
我们将使用某气象站记录的天气时间序列数据集(耶拿数据集),在这个数据集中,有每 10 分钟记录的 14 个量(比如气温、气压、湿度、风向等),这个数据集里有好多年的记录,这里我们只选用 2009—2016 年的。用这个数据集来构建模型,最后目标是输入最近的一些数据(几天的数据点),预测未来 24 小时的气温。
首先,下载并解压这个数据集:
cd ~/Somewhere
mkdir jena_climate
cd jena_climate
wget https://s3.amazonaws.com/keras-datasets/jena_climate_2009_2016.csv.zip
unzip jena_climate_2009_2016.csv.zip
看一下数据:
import os
data_dir = "/Volumes/WD/Files/dataset/jena_climate"
fname = os.path.join(data_dir, '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))
print(lines[0])
['"Date Time"', '"p (mbar)"', '"T (degC)"', '"Tpot (K)"', '"Tdew (degC)"', '"rh (%)"', '"VPmax (mbar)"', '"VPact (mbar)"', '"VPdef (mbar)"', '"sh (g/kg)"', '"H2OC (mmol/mol)"', '"rho (g/m**3)"', '"wv (m/s)"', '"max. wv (m/s)"', '"wd (deg)"']
420551
01.01.2009 00:10:00,996.52,-8.02,265.40,-8.90,93.30,3.33,3.11,0.22,1.94,3.12,1307.75,1.03,1.75,152.30
把数据放到 Numpy 数组中:
import numpy as np
float_data = np.zeros((len(lines), len(header)-1))
for i, line in enumerate(lines):
values = [float(x) for x in line.split(',')[1:]]
float_data[i, :] = values
print(float_data.shape)
(420551, 14)
我们把气温的变化画出来,周期性很明显:
from matplotlib import pyplot as plt
temp = float_data[:, 1]
plt.plot(range(len(temp)), temp)
再看看前 10 天的数据(数据 10 分钟记一条,所以 1 天是 144 条):
plt.plot(range(1440), temp[: 1440])
这个图可以看出是个冬天的,每天的气温变化也是有周期性的(后面几天比较明显)。
接下来就要开始尝试做预测模型的工作了。首先明确一下我们的问题:给定过去 lookback
个时间步(10分钟一个),我们没 steps
步采样一次,让你去预测未来 delay
时间步的气温:
lookback = 720
: 过去5天的观察数据steps = 6
: 每小时采样一次观察数据delay = 144
: 目标是未来24小时
数据准备
- 数据标准化:让各种特征在数量上差距不大
# 数据标准化
mean = float_data[:200000].mean(axis=0)
float_data -= mean
std = float_data[:200000].std(axis=0)
float_data /= std
- 把数据放到一个生成器,yield 出
(samples, targets)
,samples 是输入的数据批,targets 是对应的目标温度数组。
# 生成时间序列样本及其目标的生成器
def generator(data, # 原始数据
lookback, # 输入数据包括过去多少个时间步
delay, # 目标是未来的多少个时间步
min_index, max_index, # 指定从 data 的那个部分抽取
shuffle=False, # 打乱样本 or 按顺序抽取
batch_size=128, # 每批的样本数
step=6): # 数据采样的周期
if max_index is None:
max_index = len(data) - delay - 1
i = min_index + lookback
while True:
if shuffle:
rows = np.random.randint(min_index + lookback, max_index, size=batch_size)
else:
if i + batch_size >= max_index:
i = min_index + lookback
rows = np.arange(i, min(i + batch_size, max_index))
i += len(rows)
samples = np.zeros((len(rows), lookback // step, data.shape[-1]))
targets = np.zeros((len(rows), ))
for j, row in enumerate(rows):
indices = range(rows[j] - lookback, rows[j], step)
samples[j] = data[indices]