关于算法:R语言基于递归神经网络RNN的温度时间序列预测

37次阅读

共计 7829 个字符,预计需要花费 20 分钟才能阅读完成。

原文链接:http://tecdat.cn/?p=20335 

在本文中,咱们将介绍三种进步循环神经网络性能和泛化能力的高级技术。咱们演示无关温度预测问题的三个概念,咱们应用建筑物屋顶上的传感器的工夫数据序列。

概述

在本文中,咱们将介绍三种进步循环神经网络性能和泛化能力的高级技术。在最初,您将理解无关将循环网络与 Keras 一起应用的大部分常识。您能够拜访来自建筑物屋顶上的传感器的工夫数据序列,例如温度,气压和湿度,这些数据点可用于预测最初一个数据点之后 24 小时的温度。这是一个相当具备挑战性的问题,它阐明了应用工夫序列时遇到的许多常见艰难。

咱们将介绍以下技术:

  •  _删除_层 / 每层的单位数(模型) 如 L1 或 L2 正则化所述, 适度简单的模型更有可能适度_拟合_,能够应用删除来抵制反复图层的过拟合。
  • _重叠循环层_ —这减少了网络的示意能力(以更高的计算负荷为代价)。
  • _双向循环层_ —这些_层_以不同的形式向循环网络提供雷同的信息,从而进步准确性。

温度预测问题

在本节的所有示例中,您将应用生物地球化学研究所的气象站记录的 天气工夫序列数据集。

在此数据集中,几年中每 10 分钟记录 14 个不同的量(例如空气温度,大气压力,湿度,风向等)。原始数据可追溯到 2003 年,但此示例仅限于 2009-2016 年的数据。该数据集非常适合学习应用数字工夫序列。您将应用它来构建一个模型,该模型将最近的一些数据(几天的数据点)作为输出,并预测将来 24 小时的气温。

下载并解压缩数据,如下所示:

 unzip(
  "climate.csv.zip",
  exdir = "~/Downloads/climate"
)

咱们看一下数据。

library(tibble)
library(readr)

glimpse(data)

这是温度(摄氏度)随工夫变动的曲线图。在此图上,您能够分明地看到温度的年度周期。

 ggplot(data, aes(x = 1:nrow(data), y = `degC`)) + geom_line()

这是温度数据的前 10 天变动图。因为数据每 10 分钟记录一次,因而您每天可取得 144 个数据点。

ggplot(data[1:1440,], aes(y = `degC`)) + geom_line()

如果您依据过来几个月的数据来尝试预测下个月的平均温度,因为数据的年度周期性牢靠,因而问题很容易解决。然而从几天的数据来看,温度更加凌乱。这个工夫序列每天都能够预测吗?

筹备数据

问题的确切表白如下:给定的数据能够追溯到 lookback 工夫步长(一个工夫步长为 10 分钟)并在每个steps 工夫步短处进行采样,您能够预测该delay 工夫步长中的温度 吗?应用以下参数值:

  • lookback = 1440 —察看将追溯到 10 天。
  • steps = 6 —观测将在每小时一个数据点进行采样。
  • delay = 144 —指标将是将来的 24 小时。

首先,您须要做两件事:

  • 将数据预处理为神经网络能够应用格局。数据曾经是数字了,因而您无需进行任何向量化。然而数据中的每个工夫序列的度量尺度都不同(例如,温度通常在 -20 至 +30 之间,但以毫巴为单位的大气压约为 1,000)。您将独立地标准化每个工夫序列。
  • 编写一个生成器函数,该函数将获取以后的浮点数据数组,并生成来自最近的过来以及未来的指标温度的成批数据。因为数据集中的样本是高度冗余的(样本 _N_ 和样本 _N_  + 1 将具备大多数雷同的工夫步长),因而显式调配每个样本会很节约。相同,您将应用原始数据即时生成样本。

生成器函数是一种非凡类型的函数,能够重复调用该函数以取得一系列值。

例如,sequence_generator() 上面的函数返回一个生成器函数,该 函数产生有限的数字序列:

 gen <- sequence_generator(10)
gen()

[1] 10

gen()

[1] 11

生成器的以后状态value 是在函数内部定义的 变量。superassignment(<<-)用于从函数外部更新此状态。

生成器函数能够通过返回值 NULL 来批示实现。

首先,将先前读取的 R 数据帧转换为浮点值矩阵(咱们抛弃蕴含文本工夫戳记的第一列):

data <- data.matrix(data[,-1])

而后,您能够通过减去每个工夫序列的平均值并除以标准差来预处理数据。您将应用前 200,000 个工夫步作为训练数据,因而仅在这部分数据上计算均值和标准差以进行标准化。

train_data <- data[1:200000,]
data <- scale(data, center = mean, scale = std)

您将应用的数据生成器的代码如下。它产生一个 list  (samples, targets),其中 samples 是一批输出数据,并且 targets 是指标温度的对应数组。它采纳以下参数:

  • data —原始的浮点数据数组。
  • lookback —是_输出数据应该_包含多少个_工夫_步。
  • delay —指标应该在将来多少步。
  • min_index 和 max_index —data 数组中的索引,用于定义从中提取工夫步长。保留一部分数据用于验证和另一部分用于测试。
  • shuffle —随机整顿样本还是按工夫程序绘制样本。
  • batch_size —每批样品数。
  • step —采样数据的时间段(以工夫为单位)。您将其设置为 6,以便每小时绘制一个数据点。

当初,让咱们应用 abstract generator 函数实例化三个生成器:一个用于训练,一个用于验证以及一个用于测试。每个人都将查看原始数据的不同时间段:训练生成器查看前 200,000 个工夫步,验证生成器查看随后的 100,000 个工夫步,而测试生成器查看其余的工夫步。

lookback <- 1440
step <- 6


# 为了查看整个验证集,须要从 valu gen 中提取多少步骤
val_steps <- (300000 - 200001 - lookback) / batch_size

# 为了查看整个测试集,须要从 testu gen 中提取多少步骤
test_steps <- (nrow(data) - 300001 - lookback) / batch_size

常识性的非机器学习基准

在开始应用黑盒深度学习模型解决温度预测问题之前,让咱们尝试一种简略的常识性办法。它将用作健全性查看,并将建设一个基线,您必须超过它能力证实机器学习模型的有用性。当您要解决尚无已知解决方案的新问题时,此类常识性基准可能会很有用。一个经典的例子是不均衡的分类工作,其中某些类比其余类更为常见。如果您的数据集蕴含 90%的 A 类实例和 10%的 B 类实例,则分类工作的常识性办法是在提供新样本时始终预测“A”。此类分类器的总体准确度为 90%,因而,任何基于学习的办法都应超过 90%的分数,以证实其有用性。

在这种状况下,能够平安地假设温度工夫序列是间断的(今天的温度可能会靠近明天的温度)。因而,常识性的办法是始终预测从当初开始 24 小时的温度将等于当初的温度。咱们应用均匀绝对误差(MAE)指标评估这种办法:

mean(abs(preds - targets))

评估循环。

 for (step in 1:val_steps) {preds <- samples[,dim(samples)[[2]],2]
    mae <- mean(abs(preds - targets))
    batch_maes <- c(batch_maes, mae)
  }
  print(mean(batch_maes)) 

MAE 为 0.29。因为温度数据已标准化为以 0 为核心并且标准偏差为 1。它的均匀绝对误差为 0.29 x temperature_std 摄氏度:2.57˚C。

celsius_mae <- 0.29 * std[[2]]

那是一个相当大的均匀绝对误差。

根本的机器学习办法

就像在尝试机器学习办法之前建设常识性基准很有用一样,在钻研简单且计算量大的模型之前,尝试简略的机器学习模型也很有用。

上面的清单显示了一个全连贯的模型,该模型首先将数据展平,而后在两个密集层中运行它。请留神,最初一个致密层上短少激活函数,这对于回归问题是很典型的。您将 MAE 用作损失函数。因为您评估的数据与通常办法完全相同,而且度量规范完全相同,因而后果能够间接比拟。

model_sequential() %>% 
  layer_flatten(input_shape = c(lookback / step, dim(data)[-1])) %>% 

history <- model %>% fit_generator(
  train_gen,
  steps_per_epoch = 500,
  epochs = 20,
  validation_data = val_gen,
  validation_steps = val_steps
)

让咱们显示验证和训练的损失曲线。

某些验证损失靠近无学习基准,但不牢靠。这首先显示了具备此基准的长处:事实证明,要实现这一指标并不容易。您的常识蕴含很多机器学习模型无法访问的有价值的信息。

您可能想晓得,如果存在一个简略的,性能良好的模型,为什么您正在训练的模型找不到并对其进行改良?因为这种简略的解决方案不是您的训练设置所须要的。您要在其中寻找解决方案的模型的空间曾经相当简单。当您正在寻找具备两层网络空间的简单模型解决方案时,即便在技术上是假如简略,性能良好的基准模型也可能无奈学习。通常,这是机器学习的一个相当大的局限性:除非对学习算法进行硬编码来寻找特定类型的简略模型,

基准模型

第一种全连贯的办法成果不好,但这并不意味着机器学习不适用于此问题。先前的办法首先使工夫序列平坦化,从而从输出数据中删除了工夫概念。咱们将尝试一个递归序列解决模型 - 它应该非常适合此类序列数据,因为与第一种办法不同,正是因为它利用了数据点的工夫程序。

您将应用 Chung 等人开发的 GRU 层。在 2014 年。GRU 层应用与 LSTM 雷同的原理工作,然而它们有所简化,因而运行起来更高效。在机器学习中到处都能够看到计算复杂度和效率之间的折衷。

model_sequential() %>% 
  layer_gru(units = 32, input_shape = list(NULL, dim(data)[[-1]])) %>% 
  layer_dense(units = 1)

 model %>% fit_generator(
  train_gen,
  steps_per_epoch = 500,
  epochs = 20, 

后果如下图所示。您能够超过基线模型,证实了机器学习的价值以及循环网络的优越性。

验证 MAE 转化为非标准化后的均匀绝对误差为 2.35˚C。

抛弃(dropout)反抗适度拟合

从训练和验证曲线能够显著看出该模型是过拟合的:训练和验证损失在通过几个期间后开始呈现较大差别。您曾经相熟了应答这种景象的经典技术:抛弃(dropout),它随机将图层的输出单元清零,以便突破该图层所裸露的训练数据中的偶尔相关性。然而,如何在循环网络中正确利用 dropout 并不是一个简略的问题。道在递归层之前利用 dropout 会妨碍学习,而不是帮忙进行正则化。2015 年,Yarin Gal 作为其博士学位论文的一部分  在贝叶斯深度学习中,确定了应用递归网络进行 dropout 的正确办法:应在每个工夫步上利用雷同的 dropout 模式,而不是随工夫步长随机变动的 dropout 模式。

Yarin Gal 应用 Keras 进行了钻研,并帮忙将这种模型间接构建到 Keras 循环层中。Keras 中的每个循环图层都有两个与 dropout 相干的参数:dropout,一个浮点数,用于指定图层输出单元的 dropout 率;以及 recurrent_dropout,用于指定循环单元的 dropout 率。因为应用失落 dropout 进行正则化的网络始终须要更长的工夫能力齐全收敛,因而您须要两倍的工夫训练网络。

model_sequential() %>% 
  layer_gru(units = 32, dropout = 0.2, recurrent_dropout = 0.2, 

下图显示了后果。在前 20 个期间中,您不再适度拟合。然而,只管您的评估分数较为稳固,但您的最佳分数并没有比以前低很多。

重叠循环图层

因为您不再须要思考适度拟合的问题,而是仿佛遇到了性能瓶颈,所以您应该思考减少网络的容量。回忆一下通用机器学习工作流程的形容:在过拟合成为次要阻碍之前,最好减少网络容量,这通常是个好主见(假如您曾经采取了根本步骤来加重过拟合的状况,例如应用抛弃)。只有您的拟合度不会太差,就很可能会呈现容量有余的状况。

通常,通过减少层中的单元数或增加更多层来减少网络容量。递归层重叠是构建性能更弱小的递归网络的经典办法:例如,以后为 Google Translate 算法提供能源的是七个大型 LSTM 层的重叠。

为了在 Keras 中将递归层重叠在一起,所有中间层都应返回其残缺的输入序列(3D 张量),而不是最初一个工夫步的输入。

model_sequential() %>% 
  layer_gru(units = 32, 
            dropout = 0.1, 
            recurrent_dropout = 0.5,
            return_sequences = TRUE,
            input_shape = list(NULL, dim(data)[[-1]])) %>% 
  layer_gru(units = 64, activation = "relu",
            dropout = 0.1,
            recurrent_dropout = 0.5) %>% 

下图显示了后果。您能够看到,增加的图层的确改善了后果,只管成果不显著。您能够得出两个论断:

  • 因为不须要适度拟合的问题,所以能够平安地减少图层大小以寻求验证损失的改善。然而,这具备不可疏忽的计算成本。
  • 增加层并没有很大的帮忙,因而此时您可能会看到网络容量减少带来的收益递加。

应用双向 RNN

本节介绍的最初一种技术称为 _双向 RNN_。双向 RNN 是常见的 RNN 变体,在某些工作上能够提供比惯例 RNN 更高的性能。它在自然语言解决中常常应用 - 您能够将其称为用于深度语言解决的深度学习“瑞士军刀”。

RNN 特地依赖于程序或工夫的:它们按程序解决输出序列的工夫步长,重新排列工夫步长能够齐全扭转 RNN 从序列中提取的示意模式。这正是它们在序列问题(例如温度预测问题)上体现良好的起因。双向 RNN 利用 RNN 的序列敏感性:它蕴含应用两个惯例 RNN(例如 layer_gru 和 layer_lstm),每个 RNN 都沿一个方向(按工夫程序)解决输出序列,而后合并它们的示意模式。通过双向解决序列,双向 RNN 能够捕捉被单向 RNN 疏忽的模式。

值得注意的是,本节中的 RNN 层已按工夫程序解决了序列。训练与本节第一个试验中应用雷同的单 GRU 层网络,您将取得如下所示的后果。

结果表明在这种状况下,按工夫程序进行的解决至关重要。因为:底层的 GRU 层通常更容易记住最近的过来,天然地,较新的天气数据点比旧数据点对问题的预测能力强。因而,该层的工夫程序版本必将胜过逆序版本。对于包含自然语言在内的许多其余问题,状况并非如此:从直觉上讲,单词在了解句子中的重要性通常并不取决于其在句子中的地位。让咱们在 LSTM IMDB 示例中尝试雷同的技巧。

# 作为特色思考的单词数量
max_features <- 10000  



c(c(x_train, y_train), c(x_test, y_test)) %<-% imdb

# 反转序列
x_train <- lapply(x_train, rev)
x_test <- lapply(x_test, rev) 


model <- keras_model_sequential() %>% 
  layer_embedding(input_dim = max_features, output_dim = 128) %>% 
  layer_lstm(units = 32) %>% 

您取得的性能简直与按工夫顺序排列的 LSTM 雷同。值得注意的是,在这样的文本数据集上,逆序解决与按工夫程序解决一样无效,这证实了以下假如:只管单词程序  在了解语言中_的确很_重要,_但_ 您应用的程序并不重要。重要的是,通过逆向序列训练的 RNN 将学习与原始序列训练的 RNN 不同的表达方式。在机器学习中,_不同_ _的示意_ 总是值得开发的:它们提供了一个新的视角来查看您的数据,捕捉了其余办法脱漏的数据方面,因而能够帮忙进步工作的性能。

双向 RNN 利用此思维来改良按工夫顺序排列的 RNN 的性能。

在 Keras 中实例化双向 RNN。让咱们在 IMDB 情绪剖析工作上尝试一下。

model <- keras_model_sequential() %>% 
  layer_embedding(input_dim = max_features, output_dim = 32) %>% 
  bidirectional(layer_lstm(units = 32)


model %>% compile(
  optimizer = "rmsprop",
  loss = "binary_crossentropy", 

它的性能比您在上一节中尝试过的惯例 LSTM 稍好,达到了 89%以上的验证精度。它仿佛也能够更快地过拟合,这并不奇怪,因为双向层的参数是按工夫顺序排列的 LSTM 的两倍。通过一些正则化,双向办法可能会在此工作上表现出色。

当初让咱们在温度预测工作上尝试雷同的办法。

model_sequential() %>% 
  bidirectional(layer_gru(units = 32), input_shape = list(NULL, dim(data)[[-1]])

model %>% fit_generator(
  train_gen,
  steps_per_epoch = 500,
  epochs = 40, 

这和惯例的 layer_gru 一样好。起因很容易了解:所有预测能力都必须来自网络中按工夫顺序排列的局部,因为家喻户晓,按工夫顺序排列的局部在此工作上的体现严重不足,在这种状况下,最近的样本比过来的样本重要得多。

更进一步

为了进步温度预测问题的性能,您能够尝试其余许多办法:

  • 调整重叠设置中每个循环图层的单位数。
  • 调整RMSprop 优化器应用的学习率。
  • 尝试应用 layer_lstm 代替 layer_gru
  • 尝试在循环层的顶部应用更大的紧密连接的回归变量:即,更大的密集层,甚至一叠密集层。
  • 不要遗记最终在测试集上运行性能最佳的模型(就验证 MAE 而言),否则,您将开发适度拟合验证集的构造。

咱们能够提供一些准则,倡议在给定问题上可能起作用或不起作用的因素,然而最终,每个问题都是惟一的;您必须凭教训评估不同的策略。以后没有实践能够提前精确地告诉您应该如何最佳地解决问题。您必须迭代。


最受欢迎的见解

1. 用于 NLP 的 Python:应用 Keras 的多标签文本 LSTM 神经网络分类

2.Python 中利用长短期记忆模型 LSTM 进行工夫序列预测剖析 – 预测电力耗费数据

3.python 在 Keras 中应用 LSTM 解决序列问题

4.Python 中用 PyTorch 机器学习分类预测银行客户散失模型

5.R 语言多元 Copula GARCH 模型工夫序列预测

6. 在 r 语言中应用 GAM(狭义相加模型)进行电力负荷工夫序列剖析

7.R 语言中 ARMA,ARIMA(Box-Jenkins),SARIMA 和 ARIMAX 模型用于预测工夫序列数

8.R 语言预计时变 VAR 模型工夫序列的实证钻研剖析案例

9. 用狭义加性模型 GAM 进行工夫序列剖析

正文完
 0