用TensorFlow和QuestDB进行时间序列预测的教程

700 阅读13分钟

使用TensorFlow和QuestDB的时间序列预测

本文介绍了如何使用TensorFlow和QuestDB建立一个使用时间序列数据来预测趋势和事件的应用程序的简单指南。

时间序列预测的机器学习

机器学习正在风靡全球,以类似人类的精确度执行许多任务。在医疗领域,现在有了智能助手,可以在一段时间内检查你的健康状况。在金融领域,有一些工具能够以合理的准确度预测你的投资回报。在网络营销方面,有产品推荐器,可以根据你的购买历史建议特定的产品和品牌。

在这些领域中的每一个,都可以用不同类型的数据来训练机器学习模型。其中,时间序列数据被用于训练机器学习算法,其中时间是关键的组成部分。

时间序列数据很复杂,涉及与时间有关的特征,超出了传统机器学习算法(如回归、分类和聚类)的范围。值得庆幸的是,我们有机器学习模型可以用于时间序列的预测。由于时间的可变性,由时间序列预测产生的预测可能并不完全精确,但它们确实提供了合理的近似值,适用于各种领域。让我们考虑几个使用案例:

  • 预测性维护。如今,IoT(物联网)、AI(人工智能)和集成系统被嵌入到电子、机械和其他类型的设备中,使它们变得智能。这些物联网设备有传感器来跟踪相关的数值,而人工智能(时间序列预测是其中的一个组成部分)被用来分析这些数据,并对设备可能需要维护的大致时间做出预测。

  • 异常检测。检测系统功能中的罕见事件和观察的过程。识别这些事件可能相当具有挑战性,但时间序列预测通过提供能够连续监测事物的智能元素来帮助。网络安全、健康监测和金融科技中的欺诈检测是利用时间序列分析进行异常检测的系统的几个例子。

  • 物联网数据。 物联网现在正成为我们经济的一个具体支柱。物联网设备有能力及时存储数据,并在其他设备之间进行交流,以进行分析和预测。这方面的一个例子是温度预测,不同的物联网设备被用来定期存储温度数据,而预测则被用来进行与天气有关的预测和决策。

  • 自动缩放的决策。 通过时间序列预测,企业可以更好地监测一段时间内对其产品或解决方案的需求,并及时预测未来的需求,以相应地扩展其服务。

  • 交易。 每天股市开盘和收盘时,都要对几秒钟内的波动进行记录。各种数据库和文件存储系统被用来存储所有这些信息,然后可以使用不同的时间序列预测算法来对即将到来的一天、一周、甚至一个月进行价格预测。

在这篇文章中,我们将建立和训练一个简单的机器学习模型,使用TensorFlowQuestDB的时间序列数据来预测趋势和事件。

TensorFlow和QuestDB

时间序列预测可以通过不同的方式进行,包括使用各种机器学习算法,如ARIMAETS简单指数平滑递归神经网络(RNN)。RNN是一种深度学习方法,本身有多种变化,如LSTMGRU。这些RNN在神经网络的各层之间有反馈回路。这使得它们成为时间序列预测的理想选择,因为网络可以 "记住 "以前的数据。通过使用谷歌的TensorFlow库,这些深度学习算法的实现变得更加容易,该库支持各种神经网络和深度学习算法。

任何算法的核心都是数据,这对于时间序列预测来说也不例外。与传统数据库相比,时间序列数据库(TSDBs)为存储和分析时间序列数据提供了更多的功能。在本教程中,我选择的TSDBs是 QuestDB,这是一个开源的时间序列数据库,重点是快速的性能和易用性。

实施预测性数据分析

现在你对时间序列数据和时间序列分析有了更深的认识,让我们通过建立一个应用程序,利用这些数据来预测趋势,深入到一个实际的实现中。本教程将使用美元对印度卢比的历史汇率数据集,你可以在这里下载Excel格式的数据。请确保你选择1999-2022年的时间跨度。这个数据集包含三栏:

  1. 日期: 代表汇率的日期的时间成分。
  2. 美元: 美元的价格,以美元计(常数1.0)。
  3. INR: 在特定日期以INR表示的美元价格。

正如你所读到的,时间序列预测有许多不同的选择(例如,ARIMA,ETS,简单指数平滑,RNN,LSTM,GRU,等等)。本文将重点介绍深度学习的解决方案--使用神经网络来完成时间序列预测。对少量数据使用RNN会导致一个叫做梯度消失的问题。因为这个原因,LSTMs和GRU被引入。由于其结构简单,GRU是你在本教程中要使用的少量数据的最佳选择。

让我们开始吧!

安装TensorFlow

TensorFlow可以通过Python包管理器(PIP)轻松安装。请确保使用Python 3.6以获得与TensorFlow 1.15(以及更高版本)的最佳兼容性。如果你的系统中安装了Anaconda,你可以使用Anaconda提示。对于正常的Python安装,你可以使用默认的命令提示符并编写以下命令来安装TensorFlow。

pip install tensorflow

注意:如果你使用的是macOS,并得到一个pip错误,请尝试运行代替pip install tensorflow-macos

现在我们需要安装一些依赖项,除非你在本地已经有了它们。

pip install jupyter pandas numpy scikit-learn matplotlib openpyxl

安装QuestDB

要在任何操作系统平台上安装QuestDB,你需要:

  1. 安装Docker

  2. 拉出QuestDB Docker镜像并创建一个Docker容器。打开你的命令提示符,编写以下命令。

docker run -p 9000:9000 -p 8812:8812 questdb/questdb

这里,9000是QuestDB将运行的端口,8812端口是用于Postgres线程协议。

  1. 打开另一个终端,运行以下命令以检查QuestDB是否正在运行。
docker ps

或者,你可以浏览localhost:9000,QuestDB应该可以在那里访问。

导入你的依赖项

现在,你的依赖已经安装完毕,现在是时候开始用TensorFlow和QuestDB实现时间序列预测了。如果你想克隆该项目并在你自己的Jupyter笔记本中跟随,这里有GitHub repo的链接

我们通过运行来启动我们的本地jupyter环境。

jupyter notebook

首先,我们导入以下依赖项。

## import dependencies
import numpy as np
import pandas as pd

## deep learning dependencies
'''
In case you are using python version > 3.6
you should import model dependencies from
tensorflow directly instead of keras
eg. from tensorflow.keras.optimizers import *
'''
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import *
from keras.optimizers import *

## QuestDB dependencies
import io
import requests
import urllib.parse as par

## timestamp dependencies
from datetime import datetime

## visualisation dependencies
import matplotlib.pyplot as plt
%matplotlib inline

读取数据集

一旦你导入了所有的计算、深度学习和可视化的依赖,你就可以继续读取我们之前下载的数据集。

# read dataset using pandas library
df = pd.read_excel('Excelrates.xlsx')
## check first few rows of the dataset
df.head()

由于你要读取的数据集是一个Excel文件,你将不得不使用pandas库提供的read_excel() 函数。一旦数据集被读取,你可以在head() 函数的帮助下检查其前几行。你的数据集应该看起来像这样。

创建QuestDB表

现在你已经看到了你的数据集,但Excel在存储大量数据方面的能力有限。因此,你将使用QuestDB来存储时间序列数据。要做到这一点,首先要确保QuestDB Docker容器正在运行并可以访问。

## create table query
q = '''create table excel_rates (
           Date timestamp,
           USD int,
           INR double)'''
## connect to QuestDB URL and execute the query
r = requests.get("http://localhost:9000/exec?query=" + q)

## print the status code once executed the table creation query
print(r.status_code)

在QuestDB中创建表的过程与在任何其他数据库如SQL、Oracle、NoSQL等中创建表的过程相同。只需提供表名、列名和它们各自的数据类型。然后,连接到QuestDB运行的端口(在本例中是9000端口),使用Python的请求模块执行查询。如果查询执行成功,它将返回状态代码200;如果不成功,你将收到状态代码400

向QuestDB插入数据

一旦你创建了表,你需要在其中存储你的数据。使用下面的代码来这样做:

## variables for tracking successful execution of queries
success = 0
fail = 0

## iterate over each row and store it in the QuestDB table
for i, row in df.iterrows():
    date = row['Date']
    ## convert date to datetime format to store in DB
    date = "'"+date.strftime('%Y-%m-%dT%H:%M:%S.%fZ')+"'"
    usd = row['USD']
    inr = row['INR']
        query = f'insert into excel_rates values({date}, {usd}, {inr})'
    r = requests.get("http://localhost:9000/exec?query=" + query)
    if r.status_code == 200:
        success += 1
    else:
        fail += 1

## check if the execution is successful or not
if fail > 0:
    print("Rows Failed: " + str(fail))
if success > 0:
    print("Rows inserted: " + str(success))

要在QuestDB表中存储数据,您需要使用插入查询。如上所示,遍历数据框中的每一行,并在数据库中插入Date、USD和INR列。如果所有行都成功插入,你将收到代码200;如果其中任何一行失败,你将收到代码400

注意: 错误代码400可能是由于数据类型不匹配而返回。对于DateTime,请确保你的日期是用单引号括起来的。

从QuestDB中选择数据

从数据库中读取数据,而不是直接从文件中读取数据,其好处之一是我们可以轻松地运行过滤器或聚合的查询。为了本教程的目的,我们将不读取整个数据集(超过17000行),而只选择三年,代表约2200行。请自由评论过滤器,以比较当我们用更大的数据集进行训练时,我们的模型是否预测的更好。

## select data from QuestDB
r = requests.get("http://localhost:9000/exp?query=select * from excel_rates where Date in ('2022') or Date in ('2021') or Date in ('2020')")
rawData = r.text

## convert Bytes to CSV format and read using pandas library
df = pd.read_csv(io.StringIO(rawData), parse_dates=['Date'])
df.columns

这里,为了从QuestDB检索数据,你需要使用select 查询。select查询的输出是一个代表数据的字节数组。一旦数据被检索出来,你可以使用pandasread_csv() 函数来读取它。

预处理数据

在本教程的这一点上,你已经创建了表,将数据插入到表中,并从表中读取了数据。现在,是时候做一些时间序列预测的预处理了。

首先,你可以去掉美元列,因为它包含所有的'1'值,因此,它不会以任何方式对预测做出贡献。要做到这一点,请使用以下代码。

## drop USD column from the dataframe
df = df.drop('USD', axis=1)
## convert Date column to datetime format
df['Date'] = pd.to_datetime(df["Date"])
## set Date as index
indexed_df = df.set_index(["Date"], drop=True)
indexed_df.head()

为了看到INR的值是如何随时间变化的,你可以用这段代码在时间和INR之间绘制一条曲线。

## plot dataframe
indexed_df.plot()

时间序列预测是一种监督方法,这意味着它使用输入特征和标签来进行预测。到现在为止,你只有Date作为一个索引和一个列(INR)作为一个特征。为了创建标签,你需要将每个INR值移1,使INR成为输入特征,而移位后的值将成为输出特征/标签。你还需要从这些列中删除NaN值,使其适合训练。使用下面的代码来完成这一切。

## shift INR values by 1
shifted_df= indexed_df.shift()
## merge INR and Shifter INR values
concat_df = [indexed_df, shifted_df]
data = pd.concat(concat_df,axis=1)
## Replace NaNs with 0
data.fillna(0, inplace=True)
data.head()

接下来,你需要将数据分成两个不同的类别--训练和测试。

## convert data to numpy array
data = np.array(data)
## you can take last 500 data points as test set
train , test = data[0:-500], data[-500:]

由于数据中存在多样性(数值在很大范围内变化),你需要对数据进行一些缩放或归一化处理。为了这个目的,你将使用MinMaxScaler

## Scale
scaler = MinMaxScaler()
train_scaled = scaler.fit_transform(train)
test_scaled = scaler.transform(test)

## train data
y_train = train_scaled[:,-1]
X_train = train_scaled[:,0:-1]
X_train = X_train.reshape(len(X_train),1,1)

## test data
y_test = test_scaled[:,-1]
X_test = test_scaled[:,0:-1]

创建模型

现在,预处理已经完成,是时候为时间序列预测训练你的深度学习(GRU)模型了。使用这段代码来完成。

## GRU Model
model = Sequential()
## GRU layer
model.add(GRU(75, input_shape=(1,1)))
## output layer
model.add(Dense(1))
optimizer = Adam(lr=1e-3)
model.compile(loss='mean_squared_error', optimizer=optimizer, metrics=['accuracy'])
model.fit(X_train, y_train, epochs=100, batch_size=20, shuffle=False)

上面,你把你的模型定义为顺序性的--意思是你以后要追加的任何层都会按顺序添加到前面的层中。然后,定义了一个有75个神经元的GRU层,并添加了一个密集(全连接)层,作为输出层。由于你正在创建一个深度学习模型,你还添加了一个优化器和一个损失函数。在这种情况下,"Adam " 对GRU很有效,而由于你要处理的是数字数据,平均误差将起到作用。最后,在输入数据上拟合模型。

一旦你执行上述代码,你的模型训练就会开始。它应该看起来像这样。

一旦模型准备好了,你就需要在测试集上测试它,以检查其准确性。

## make predictions for test set
X_test = X_test.reshape(500,1,1)
y_pred = model.predict(X_test)

## visualise results
plt.plot(y_pred, label = 'predictions')
plt.plot(y_test, label = 'actual')
plt.legend()

正如你所看到的,预测值是实际值的近似值,这表明该模型的表现足够好。由于测试数据有很多点,所以图中出现了聚类;为了更仔细地观察这些数值,你也可以只将一百个数值可视化。

## visualize results
plt.plot(y_pred[:100], label = 'predictions')
plt.plot(y_test[:100], label = 'actual')
plt.legend()

现在,你的时间序列预测模型已经准备好了,你可以用它来对即将到来的日期进行预测。整个项目的代码笔记本可以在这里找到。

总结

在本教程中,你学到了如何使用深度学习框架、TensorFlow和QuestDB进行时间序列预测。随着现在越来越多的电子和机械设备的智能化,手动处理它们已经不再是一种选择。为了有效地实现这些机器的自动化维护,你需要有合适的工具来存储和处理机器产生的数据。

传统的数据库在这方面不是一个好的选择,因为它们更专注于处理和写入事务中的数据。另一方面,时间序列数据库是专门为存储不同时间间隔的观察结果而设计的。它们还提供了帮助处理时间序列的功能和工具,正如你在本教程中看到的那样。