Python时序预测教程

导航到

本文最初发布在The New Stack,并在此获得许可转载。

生活在快速变化的社会中,所有系统的状态也会随之快速变化,这导致运营中的不一致性。但如果你能预见这些不一致性,如果能窥见未来呢?这就是时序数据能帮到你的地方。

时序数据是指一组数据点,描述了特定系统在各个时间点的状态。时间间隔取决于特定的系统,但通常,数据是根据每条记录的日期和/或时间来排列的。这意味着系统的时序数据是它随时间变化的详细记录。每个数据点都可以通过其时间戳唯一识别。有人可能认为所有数据都是时序数据;然而,并非所有记录都以这种方式记录,以至于系统随时间变化的细节得到保持。

为了保持系统的变化,你需要时序预测,这是利用可用的时序记录来预测系统在未来的状态。因此,从遥远的过去到昨天的系统记录,预测今天和明天的系统状态的过程就是时序预测。你可以使用时序预测来预测天气或股价。它还帮助在更多工业环境中进行预测性维护,以及预测能源资源的合理管理。

在本教程中,你将了解更多关于使用InfluxDB进行时序预测的知识,以及如何构建一个时序预测器来窥见未来。

理解时序预测

如前所述,时序预测是使用特定系统过去的存储时间戳记录来预测未来会发生什么的过程。

注意,在开发过程中,过去和未来的概念使用得更加灵活。给定一个特定的参考点,所有在该参考点之前记录的数据点都在过去,而所有在该参考点之后记录的数据点被称为未来

使用过去来预测未来可能听起来有些棘手,因为人们可能会问:“在没有目标列的情况下,如何将数据进行特征和目标的分割?” 首先,定义一个窗口。这个窗口本质上指的是你需要回溯多长时间才能做出预测。这有助于设置一个截止点,超过这个截止点,数据点对预测的影响可以忽略不计。使用这个窗口,你可以滑动数据集来生成训练数据。

假设你有一家公司年度销售数据,窗口为六十天:1月1日至2月29日。这六十天将用于预测3月1日的销售(假设是闰年)。接下来,你会使用1月2日至3月1日的数据进行预测3月2日的销售。这样逐步进行,直到你考虑11月1日至12月30日来预测12月31日的销售。

除了销售,时间序列预测还可以用来预测天气。有了关于温度、相对湿度和其他天气相关参数的历史信息,可以预测未来的天气。

时间序列预测还被用来预测各种组织的股票价格,基于它们的历史数据。同样,使用时间序列预测可以预测从传统货币到加密货币的各种货币的价格。

在更工业化的端,有了各种机械设备工作状态的数据,可以预测未来的状态,这有助于提前识别故障,以便在零件损坏并停止运营之前进行维护。这被称为预测性维护

在能源效率领域,有了关于家庭或特定家庭电力消耗的信息,配电公司可以高效地供电,确保在特定时间需要更多电力的人能得到足够的电力。这些信息也可以被组织和家庭用来了解他们的电力消耗趋势,并实施规定以节省成本。

时间序列预测和其他形式的时间序列数据分析的使用案例层出不穷,这就是为什么理解如何有效地使用时间序列预测非常重要。

使用InfluxDB实现时间序列预测

为了演示如何有效地进行时间序列预测,本教程包括使用InfluxDB进行数据准备和建模过程的操作指南。为了保持上下文,将要解决的问题示例与预测一个家庭基于十五分钟时间间隔测量的能源消耗数据相关。

设置InfluxDB

要设置InfluxDB,请访问InfluxDB OSS文档并点击开始按钮。这是InfluxDB的开源版本,可以在本地服务器上设置。按照安装InfluxDB页面上的说明(在这种情况下,Windows)安装并启动InfluxDB OSS。

InfluxDB OSS install

此时,您应该在本地服务器上运行了InfluxDB。将此本地服务器的URL输入浏览器中,以访问InfluxDB界面。然后输入您的用户名、密码、组织机构和桶名称以完成InfluxDB的设置。完成设置后,您将进入InfluxDB OSS主页

InfluxDB OSS dashboard home page

另一个无需在您的计算机上设置任何内容即可开始使用InfluxDB的选项是使用免费的InfluxDB云实例

将数据加载到InfluxDB

在设置好InfluxDB后,现在您需要将数据加载到数据库中。首先,从此Kaggle页面下载CSV数据。

在直接将CSV文件上传到InfluxDB之前,必须对其进行标注。由于此CSV文件未标注,将使用InfluxDB Python客户端将数据写入数据库。这将让您了解数据如何流式传输到InfluxDB。

接下来,导航到“API令牌”选项卡,如果尚无API令牌,请点击“生成API令牌”按钮。然后点击新创建的令牌名称以查看和复制所有访问权限的API令牌,如下所示。此令牌将用于从客户端验证对InfluxDB的连接

InfluxDB OSS generate API token

知道了API令牌、桶和组织后,导航到您首选的代码编辑器,为该项目创建一个文件夹。然后将之前下载的CSV文件转移到父文件夹中的新data/目录中。

使用以下Windows命令创建并激活名为.venv的Python虚拟环境

python -m venv .venv
.venv\Scripts\activate.bat

接下来,安装本教程所需的所有库,并将API令牌设置为环境变量

pip install pandas influxdb-client matplotlib
pip install fbprophet

完成这些后,创建一个脚本并导入必要的库

import os

from datetime import datetime

import pandas as pd

from influxdb_client import InfluxDBClient, Point, WritePrecision

from influxdb_client.client.write_api import SYNCHRONOUS

token = os.getenv("INFLUX_TOKEN")

organization = "forecasting"

bucket = "energy_consumption"

在此,您安装了os模块以加载环境变量,pandas库以加载CSV文件,以及InfluxDB方法以简化写入过程。接下来,将API令牌、组织和桶名称加载到相应命名的变量中。

现在您需要创建InfluxDB客户端并实例化write_API

PORT = 8086

client = InfluxDBClient(url=f"http://127.0.0.1:{PORT}", token=token, org=organization)

write_api = client.write_api(write_options=SYNCHRONOUS)

df = pd.read_csv('data/D202.csv')

在前面的代码中,您定义了InfluxDB服务器运行的PORT号。然后通过传入运行服务器URL、API令牌和组织名称作为参数来实例化InfluxDB客户端。

接下来,使用先前定义的client实例调用write_API方法。最后,在这个片段中,您使用read_csv方法将CSV文件加载为Pandas DataFrame。这是数据集的样貌

view of data set

for index, row in df.iterrows():

    print(index, end=' ')

    stamp = datetime.strptime(f"{row['DATE']}, {row['START TIME']}", 

                                "%m/%d/%Y, %H:%M")

    p = Point(row["TYPE"])\
        .time(stamp, WritePrecision.NS)\
        .field("usage(KWh)", row["USAGE"])\
        .tag("cost", row["COST"])

    write_api.write(bucket=bucket, org=organization, record=p)

此片段包含实际的写入步骤。在此,您遍历Pandas DataFrame并打印索引以跟踪进度。接下来,将起始时间转换为日期时间对象。然后使用此起始时间定义该数据点的时字段。

使用先前导入的InfluxDB点对象来配置上传数据的行。每个点实例应有一个时间、字段和一个或多个标签。其中时间指的是该数据点记录的时间。字段是千瓦时(kWh)的能耗数据,而成本被视为标签。

最后,在循环的每次迭代中,调用写入API将数据点写入数据库中的桶。

从InfluxDB读取数据

接下来,您必须将存储在InfluxDB上的数据读取到Python环境中进行训练

query_api = client.query_api()

query = f'from(bucket:"{bucket}")' \
        ' |> range(start:2016-10-22T00:00:00Z, stop:2018-10-24T23:45:00Z)'\
        ' |> filter(fn: (r) => r._measurement == "Electric usage")' \
        ' |> filter(fn: (r) => r._field == "usage(KWh)")'

在这里,你再次调用InfluxDB客户端实例,但这次,你选择查询API,因为你的目标是读取数据库。然后你创建查询。InfluxDB使用一种称为Flux的脚本语言,它易于使用。[Flux](https://docs.influxdb.org.cn/flux/v0.x/)。在Python中,你将Flux查询写入字符串。在这个查询字符串中,你指定要读取的存储桶。接下来,你定义你想要查询的时间范围。最后,你声明过滤器来选择包含在测量和字段属性中的指定信息的数据点。在这种情况下,是"Electric usage"测量和"usage(KWh)"字段。

result = query_api.query(org=organization, query=query)

data = {'y': [], 'ds': []}

for table in result:

    for record in table.records:

        data['y'].append(record.get_value())

        data['ds'].append(record.get_time())

    print("here")

df = pd.DataFrame(data=data)

df.to_csv('data/Processed_D202.csv', index=False)

在这个片段中,你使用query_api.query方法和组织来解析查询。然后你创建存储来保存结果并遍历查询结果。当你迭代时,你将结果收集在之前定义的存储中,在这种情况下是一个Python字典。完成此操作后,将处理后的数据保存为CSV文件在data/目录下。

使用Prophet进行预测

从InfluxDB加载数据后,下一步是构建预测模型。Facebook创建并发布了一个名为[Prophet](https://facebook.github.io/prophet/)的库,这是一个适用于Python和R的时间序列预测的库,名称恰当且性能出色。[Prophet](https://influxdb.org.cn/blog/forecasting-with-fb-prophet-and-influxdb/)旨在处理异常值,各种变化(季节性、月度、日度等)以及任何给定时间序列中的缺失数据。它还提供了帮助调整模型以获得更好性能的参数。

Prophet模型的输入是一个包含两列的DataFrame,即ydsy代表感兴趣的变量(能源使用),而ds指的是datetime属性。正如你所看到的,前一个部分中的DataFrame列并不是随机命名的。

要开始,导入Prophet库和其他数据处理和可视化库

import fbprophet

import matplotlib.pyplot as plt

import pandas as pd

df = pd.read_csv('data/Processed_D202.csv')

df['ds'] = pd.to_datetime(df['ds']).dt.tz_localize(None)

df_copy = df.set_index('ds')

导入所需的库后,将处理后的数据读入数据框,将时间戳列转换为Datetime对象并移除时区,以避免绘图时出错。然后创建一个包含时间戳列作为索引的数据框副本

df_copy.plot(kind='line', 
                        xlabel='Datetime', 
                        ylabel='Energy Consumption (KWh)', 
                        )

plt.title('Household Energy Consumption over Time', fontweight='bold', fontsize=20)

plt.show()

在这里,你使用创建的DataFrame副本来可视化数据,如下所示。你可以看到,能源消耗在年底和下一年初有所增加,这是季节性变化,任何训练有素的模型都应该能够识别出来。

plot of energy consumption

energy_prophet = fbprophet.Prophet(changepoint_prior_scale=0.0005)

energy_prophet.fit(df)

energy_forecast = energy_prophet.make_future_dataframe(periods=365, freq='D')

energy_forecast = energy_prophet.predict(energy_forecast)

energy_prophet.plot(energy_forecast, xlabel = 'Date', ylabel = 'Energy Usage (KWh)') # 0.0005

plt.title('Household Energy Usage')

plt.show()

接下来,实例化Prophet模型并将其拟合到数据中。在实例化Prophet时,你传递changepoint_prior_scale参数来控制预测器的灵活性。然后,你创建一个用于Prophet预测的测试数据框。这个DataFrame基于输入数据的最后一天构建,间隔与输入数据相同。然后使用.predict方法将其解析到模型中进行预测。最后,你绘制结果以查看预测与训练数据如何匹配。值得注意的是,changepoint_prior_scale参数的较小值导致了更好的预测。

Forecast results

forecast results

在这里,你可以看到预测值大致遵循前几年发生的变化趋势。你还可以查看预测的组成部分趋势,以了解能源消耗如何在一日、一周或一年内变化。

energy_prophet.plot_components(energy_forecast)

Forecast components Forecast components

有了这样的信息,你就可以做出关于能源分配或能源消耗管理的重大决策。

结论

在本教程中,您学习了时间序列数据的重要性以及预测方法。您还学习了如何通过Python客户端与InfluxDB交互,以及如何使用Prophet构建预测器。

InfluxData创建了InfluxDB,这是一个高效的时间序列数据库,您可以将其用作系统解决方案来管理应用中的时间序列数据并执行分析。今天试试InfluxDB

作者简介:福布斯是Josplay的Python开发者,擅长处理数据和构建智能系统。他还是一名工艺工程师和技术作家。

fortune Adekogbe