循环神经网络的高级用法_温度预测时间序列问题

循环神经网络的高级用法_温度预测时间序列问题
参考:
https://www.jianshu.com/p/426a7aed953c
在这里插入图片描述

下面是你应该从本节中学到的要点。
‰ 我们在第 4 章学过,遇到新问题时,最好首先为你选择的指标建立一个基于常识的基准。
如果没有需要打败的基准,那么就无法分辨是否取得了真正的进步。
‰ 在尝试计算代价较高的模型之前,先尝试一些简单的模型,以此证明增加计算代价是有
意义的。有时简单模型就是你的最佳选择。
‰ 如果时间顺序对数据很重要,那么循环网络是一种很适合的方法,与那些先将时间数据
展平的模型相比,其性能要更好。
‰ 想要在循环网络中使用 dropout,你应该使用一个不随时间变化的 dropout 掩码与循环
dropout 掩码。这二者都内置于 Keras 的循环层中,所以你只需要使用循环层的 dropout
和 recurrent_dropout 参数即可。
‰ 与单个 RNN 层相比,堆叠 RNN 的表示能力更加强大。但它的计算代价也更高,因此不
一定总是需要。虽然它在机器翻译等复杂问题上很有效,但在较小、较简单的问题上可
能不一定有用

代码清单 6-28 观察耶拿天气数据集的数据
代码清单 6-29 解析数据
代码清单 6-30 绘制温度时间序列
代码清单 6-31 绘制前 10 天的温度时间序列
代码清单 6-32 数据标准化
代码清单 6-33 生成时间序列样本及其目标的生成器
代码清单 6-34 准备训练生成器、验证生成器和测试生成器
6.3.3 一种基于常识的、非机器学习的基准方法
代码清单 6-35 计算符合常识的基准方法的 MAE
代码清单 6-36 将 MAE 转换成摄氏温度误差
代码清单 6-37 训练并评估一个密集连接模型
代码清单 6-38 绘制结果
6.3.5 第一个循环网络基准
代码清单 6-39 训练并评估一个基于 GRU 的模型
6.3.6 使用循环 dropout 来降低过拟合
代码清单 6-40 训练并评估一个使用 dropout 正则化的基于 GRU 的模型
6.3.7 循环层堆叠
代码清单 6-41 训练并评估一个使用 dropout 正则化的堆叠 GRU 模型
代码清单 6-44 训练一个双向 GRU

# 在这个数据集中,每 10 分钟记录 14 个不同的量(比如气温、气压、湿度、风向等),其中
# 包含多年的记录。原始数据可追溯到 2003 年,但本例仅使用 2009—2016 年的数据。这个数据
# 集非常适合用来学习处理数值型时间序列。我们将会用这个数据集来构建模型,输入最近的一
# 些数据(几天的数据点),可以预测 24 小时之后的气温。
# 下载并解压数据,如下所示。
# cd ~/Downloads
# 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
# 来观察一下数据

# 代码清单 6-28 观察耶拿天气数据集的数据
import os
# 加载csv文件

# data_dir = '/home/ubuntu/data/'
data_dir = 'C:\\file\data'
fname = os.path.join(data_dir, 'jena_climate_2009_2016.csv')

f = open(fname)
data = f.read()
f.close()

# 以换行符切分
lines = data.split('\n')
# 将第一行赋予首行
header = lines[0].split(',')
lines = lines[1:]

print(header)
print(len(lines))
print(type(lines))

['"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
<class 'list'>
Let's convert all of these 420,551 lines of data into a Numpy array:

# 接下来,将 420 551 行数据转换成一个 Numpy 数组。
# 代码清单 6-29 解析数据
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
    
#     比如,温度随时间的变化如图 6-18 所示(单位:摄氏度)。在这张图中,你可以清楚地看
# 到温度每年的周期性变化。
# 代码清单 6-30 绘制温度时间序列
# 接下来,将 420 551 行数据转换成一个 Numpy 数组。
# 代码清单 6-29 解析数据
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
    
#     比如,温度随时间的变化如图 6-18 所示(单位:摄氏度)。在这张图中,你可以清楚地看
# 到温度每年的周期性变化。
# 代码清单 6-30 绘制温度时间序列

For instance, here is the plot of temperature (in degrees Celsius) over time:

from matplotlib import pyplot as plt
​
temp = float_data[:, 1]  # temperature (in degrees Celsius)
plt.plot(range(len(temp)), temp)
plt.show()

在这里插入图片描述

# 图 6-19 给出了前 10 天温度数据的图像。因为每 10 分钟记录一个数据,所以每天有 144 个
# 数据点。
# 代码清单 6-31 绘制前 10 天的温度时间序列

plt.plot(range(1440), temp[:1440])
plt.show()

# 在这张图中,你可以看到每天的周期性变化,尤其是最后 4 天特别明显。另外请注意,这
# 10 天一定是来自于很冷的冬季月份。
# 如果你想根据过去几个月的数据来预测下个月的平均温度,那么问题很简单,因为数据具
# 有可靠的年度周期性。但从几天的数据来看,温度看起来更混乱一些。以天作为观察尺度,这
# 个时间序列是可以预测的吗?我们来寻找这个问题的答案

在这里插入图片描述

mean = float_data[:200000].mean(axis=0)
float_data -= mean
std = float_data[:200000].std(axis=0)
float_data /= std

def generator(data, lookback, delay, min_index, max_index,
              shuffle=False, batch_size=128, step=6):
    
#     ‰ data:浮点数数据组成的原始数组,在代码清单 6-32 中将其标准化。
# ‰ lookback:输入数据应该包括过去多少个时间步。
# ‰ delay:目标应该在未来多少个时间步之后。
# ‰ min_index 和 max_index: data 数组中的索引,用于界定需要抽取哪些时间步。这有
# 助于保存一部分数据用于验证、另一部分用于测试。
# ‰ shuffle:是打乱样本,还是按顺序抽取样本。
# ‰ batch_size:每个批量的样本数。
# ‰ step:数据采样的周期(单位:时间步)

    if max_index is None:
        max_index = len(data) - delay - 1
    i = min_index + lookback
    while 1:
        if shuffle:
            
            rows = np.random.randint(
                min_index + lookback, max_index, size=batch_size)
            
#             numpy.random.randint(low, high=None, size=None, dtype='l'):
# 生成一个整数或N维整数数组,取数范围:若high不为None时,取[low,high)之间随机整数,否则取值[0,low)之间随机整数。
        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]
            targets[j] = data[rows[j] + delay][1]
        yield samples, targets


# 下面,我们使用这个抽象的 generator 函数来实例化三个生成器:一个用于训练,一个用6.3 循环神经网络的高级用法  177
# 1 2 3 4 5 6 7 8 9
# 于验证,还有一个用于测试。每个生成器分别读取原始数据的不同时间段:训练生成器读取前
# 200 000 个时间步,验证生成器读取随后的 100 000 个时间步,测试生成器读取剩下的时间步。
# 代码清单 6-34 准备训练生成器、验证生成器和测试生成器

lookback = 1440
step = 6
delay = 144
batch_size = 128

train_gen = generator(float_data,
                      lookback=lookback,
                      delay=delay,
                      min_index=0,
                      max_index=200000,
                      shuffle=True,
                      step=step, 
                      batch_size=batch_size)
val_gen = generator(float_data,
                    lookback=lookback,
                    delay=delay,
                    min_index=200001,
                    max_index=300000,
                    step=step,
                    batch_size=batch_size)
test_gen = generator(float_data,
                     lookback=lookback,
                     delay=delay,
                     min_index=300001,
                     max_index=None,
                     step=step,
                     batch_size=batch_size)

# This is how many steps to draw from `val_gen`
# in order to see the whole validation set:
# 为了查看整个验证集,需要
# 从 val_gen 中抽取多少次
val_steps = (300000 - 200001 - lookback) // batch_size

# This is how many steps to draw from `test_gen`
# in order to see the whole test set:
test_steps = (len(float_data) - 300001 - lookback) // batch_size
# 为了查看整个测试集,需要从
# test_gen 中抽取多少次

# 6.3.3 一种基于常识的、非机器学习的基准方法
# 开始使用黑盒深度学习模型解决温度预测问题之前,我们先尝试一种基于常识的简单方法。
# 它可以作为合理性检查,还可以建立一个基准,更高级的机器学习模型需要打败这个基准才能
# 表现出其有效性。面对一个尚没有已知解决方案的新问题时,这种基于常识的基准方法很有用。
# 一个经典的例子就是不平衡的分类任务,其中某些类别比其他类别更常见。如果数据集中包含
# 90% 的类别 A 实例和 10% 的类别 B 实例,那么分类任务的一种基于常识的方法就是对新样本
# 始终预测类别“A”。这种分类器的总体精度为 90%,因此任何基于学习的方法在精度高于 90%
# 时才能证明其有效性。有时候,这样基本的基准方法可能很难打败。
# 为了查看整个验证集,需要
# 从 val_gen 中抽取多少次
# 为了查看整个测试集,需要从
# test_gen 中抽取多少次178  第 6 章 深度学习用于文本和序列
# 本例中,我们可以放心地假设,温度时间序列是连续的(明天的温度很可能接近今天的温
# 度),并且具有每天的周期性变化。因此,一种基于常识的方法就是始终预测 24 小时后的温度
# 等于现在的温度。我们使用平均绝对误差(MAE)指标来评估这种方法
# 求平均值
np.mean(np.abs(preds - targets))


# 下面是评估的循环代码。
# 代码清单 6-35 计算符合常识的基准方法的 MAEdef evaluate_naive_method():
    batch_maes = []
    for step in range(val_steps):
        samples, targets = next(val_gen)
        preds = samples[:, -1, 1]
        mae = np.mean(np.abs(preds - targets))
        batch_maes.append(mae)
    print(np.mean(batch_maes))
    
evaluate_naive_method()
0.2897359729905486
# 得到的 MAE 为 0.29。因为温度数据被标准化成均值为 0、标准差为 1,所以无法直接对这
# 个值进行解释。它转化成温度的平均绝对误差为 0.29×temperature_std 摄氏度,即 2.57℃。
# 代码清单 6-36 将 MAE 转换成摄氏温度误差
celsius_mae = 0.29 * std[1]
print(celsius_mae)
# 这个平均绝对误差还是相当大的。接下来的任务是利用深度学习知识来改进结果
2.5672247338393395
It yields a MAE of 0.29. Since our temperature data has been normalized to be centered on 0 and have a standard deviation of one, this number is not immediately interpretable. It translates to an average absolute error of 0.29 * temperature_std degrees Celsius, i.e. 2.57˚C. That's a fairly large average absolute error -- now the game is to leverage our knowledge of deep learning to do better.


# 6.3.4 一种基本的机器学习方法
# 在尝试机器学习方法之前,建立一个基于常识的基准方法是很有用的;同样,在开始研究
# 复杂且计算代价很高的模型(比如 RNN)之前,尝试使用简单且计算代价低的机器学习模型也
# 是很有用的,比如小型的密集连接网络。这可以保证进一步增加问题的复杂度是合理的,并且
# 会带来真正的好处。
# 代码清单 6-37 给出了一个密集连接模型,首先将数据展平,然后通过两个 Dense 层并运行。
# 注意,最后一个 Dense 层没有使用激活函数,这对于回归问题是很常见的。我们使用 MAE 作
# 为损失。评估数据和评估指标都与常识方法完全相同,所以可以直接比较两种方法的结果。
# 代码清单 6-37 训练并评估一个密集连接模型

from keras.models import Sequential
from keras import layers
from keras.optimizers import RMSprop
# 代码清单 6-37 给出了一个密集连接模型,首先将数据展平,然后通过两个 Dense 层并运行。
model = Sequential()
model.add(layers.Flatten(input_shape=(lookback // step, float_data.shape[-1])))
model.add(layers.Dense(32, activation='r
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值