AI能力(AINode)
AI能力(AINode)
AINode 是 IoTDB 在ConfigNode、DataNode后提供的第三种内生节点,该节点通过与 IoTDB 集群的 DataNode、ConfigNode 的交互,扩展了对时间序列进行机器学习分析的能力,支持从外部引入已有机器学习模型进行注册,并使用注册的模型在指定时序数据上通过简单 SQL 语句完成时序分析任务的过程,将模型的创建、管理及推理融合在数据库引擎中。目前已提供常见时序分析场景(例如预测与异常检测)的机器学习算法或自研模型。
系统架构如下图所示:
三种节点的职责如下:
- ConfigNode:负责保存和管理模型的元信息;负责分布式节点管理。
- DataNode:负责接收并解析用户的 SQL请求;负责存储时间序列数据;负责数据的预处理计算。
- AINode:负责模型文件的导入创建以及模型推理。
优势特点
与单独构建机器学习服务相比,具有以下优势:
简单易用:无需使用 Python 或 Java 编程,使用 SQL 语句即可完成机器学习模型管理与推理的完整流程。如创建模型可使用CREATE MODEL语句、使用模型进行推理可使用CALL INFERENCE(...)语句等,使用更加简单便捷。
避免数据迁移:使用 IoTDB 原生机器学习可以将存储在 IoTDB 中的数据直接应用于机器学习模型的推理,无需将数据移动到单独的机器学习服务平台,从而加速数据处理、提高安全性并降低成本。
- 内置先进算法:支持业内领先机器学习分析算法,覆盖典型时序分析任务,为时序数据库赋能原生数据分析能力。如:
- 时间序列预测(Time Series Forecasting):从过去时间序列中学习变化模式;从而根据给定过去时间的观测值,输出未来序列最可能的预测。
- 时序异常检测(Anomaly Detection for Time Series):在给定的时间序列数据中检测和识别异常值,帮助发现时间序列中的异常行为。
- 时间序列标注(Time Series Annotation):为每个数据点或特定时间段添加额外的信息或标记,例如事件发生、异常点、趋势变化等,以便更好地理解和分析数据。
基本概念
- 模型(Model):机器学习模型,以时序数据作为输入,输出分析任务的结果或决策。模型是AINode 的基本管理单元,支持模型的增(注册)、删、查、用(推理)。
- 创建(Create): 将外部设计或训练好的模型文件或算法加载到MLNode中,由IoTDB统一管理与使用。
- 推理(Inference):使用创建的模型在指定时序数据上完成该模型适用的时序分析任务的过程。
- 内置能力(Built-in):AINode 自带常见时序分析场景(例如预测与异常检测)的机器学习算法或自研模型。
安装部署
AINode 的部署可参考文档 部署指导 章节。
使用指导
AINode 对时序数据相关的深度学习模型提供了模型创建及删除的流程,内置模型无需创建及删除,可直接使用,并且在完成推理后创建的内置模型实例将自动销毁。
注册模型
通过指定模型输入输出的向量维度,可以注册训练好的深度学习模型,从而用于模型推理。
符合以下内容的模型可以注册到AINode中:
- AINode 支持的PyTorch 2.1.0、 2.2.0版本训练的模型,需避免使用2.2.0版本以上的特性。
- AINode支持使用PyTorch JIT存储的模型,模型文件需要包含模型的参数和结构。
- 模型输入序列可以包含一列或多列,若有多列,需要和模型能力、模型配置文件对应。
- 模型的输入输出维度必须在
config.yaml
配置文件中明确定义。使用模型时,必须严格按照config.yaml
配置文件中定义的输入输出维度。如果输入输出列数不匹配配置文件,将会导致错误。
下方为模型注册的SQL语法定义。
create model <model_name> using uri <uri>
SQL中参数的具体含义如下:
model_name:模型的全局唯一标识,不可重复。模型名称具备以下约束:
- 允许出现标识符 [ 0-9 a-z A-Z _ ] (字母,数字,下划线)
- 长度限制为2-64字符
- 大小写敏感
uri:模型注册文件的资源路径,路径下应包含模型权重model.pt文件和模型的元数据描述文件config.yaml
模型权重文件:深度学习模型训练完成后得到的权重文件,目前支持pytorch训练得到的.pt文件
yaml元数据描述文件:模型注册时需要提供的与模型结构有关的参数,其中必须包含模型的输入输出维度用于模型推理:
参数名 参数描述 示例 input_shape 模型输入的行列,用于模型推理 [96,2] output_shape 模型输出的行列,用于模型推理 [48,2] 除了模型推理外,还可以指定模型输入输出的数据类型:
参数名 参数描述 示例 input_type 模型输入的数据类型 ['float32','float32'] output_type 模型输出的数据类型 ['float32','float32'] 除此之外,可以额外指定备注信息用于在模型管理时进行展示
参数名 参数描述 示例 attributes 可选,用户自行设定的模型备注信息,用于模型展示 'model_type': 'dlinear','kernel_size': '25'
除了本地模型文件的注册,还可以通过URI来指定远程资源路径来进行注册,使用开源的模型仓库(例如HuggingFace)。
示例
在当前的example文件夹下,包含model.pt和config.yaml文件,model.pt为训练得到,config.yaml的内容如下:
configs:
# 必选项
input_shape: [96, 2] # 表示模型接收的数据为96行x2列
output_shape: [48, 2] # 表示模型输出的数据为48行x2列
# 可选项 默认为全部float32,列数为shape对应的列数
input_type: ["int64","int64"] #输入对应的数据类型,需要与输入列数匹配
output_type: ["text","int64"] #输出对应的数据类型,需要与输出列数匹配
attributes: # 可选项 为用户自定义的备注信息
'model_type': 'dlinear'
'kernel_size': '25'
指定该文件夹作为加载路径就可以注册该模型
IoTDB> create model dlinear_example using uri "file://./example"
也可以从huggingFace上下载对应的模型文件进行注册
IoTDB> create model dlinear_example using uri "https://huggingface.com/IoTDBML/dlinear/"
SQL执行后会异步进行注册的流程,可以通过模型展示查看模型的注册状态(见模型展示章节),注册成功的耗时主要受到模型文件大小的影响。
模型注册完成后,就可以通过使用正常查询的方式调用具体函数,进行模型推理。
查看模型
注册成功的模型可以通过show models指令查询模型的具体信息。其SQL定义如下:
show models
show models <model_name>
除了直接展示所有模型的信息外,可以指定model id来查看某一具体模型的信息。模型展示的结果中包含如下信息:
ModelId | State | Configs | Attributes |
---|---|---|---|
模型唯一标识 | 模型注册状态(LOADING,ACTIVE,DROPPING) | InputShape, outputShapeInputTypes, outputTypes | 模型备注信息 |
其中,State用于展示当前模型注册的状态,包含以下三个阶段
- LOADING:已经在configNode中添加对应的模型元信息,正将模型文件传输到AINode节点上
- ACTIVE: 模型已经设置完成,模型处于可用状态
- DROPPING:模型删除中,正在从configNode以及AINode处删除模型相关信息
- UNAVAILABLE: 模型创建失败,可以通过drop model删除创建失败的model_name。
示例
IoTDB> show models
+---------------------+--------------------------+-----------+----------------------------+-----------------------+
| ModelId| ModelType| State| Configs| Notes|
+---------------------+--------------------------+-----------+----------------------------+-----------------------+
| dlinear_example| USER_DEFINED| ACTIVE| inputShape:[96,2]| |
| | | | outputShape:[48,2]| |
| | | | inputDataType:[float,float]| |
| | | |outputDataType:[float,float]| |
| _STLForecaster| BUILT_IN_FORECAST| ACTIVE| |Built-in model in IoTDB|
| _NaiveForecaster| BUILT_IN_FORECAST| ACTIVE| |Built-in model in IoTDB|
| _ARIMA| BUILT_IN_FORECAST| ACTIVE| |Built-in model in IoTDB|
|_ExponentialSmoothing| BUILT_IN_FORECAST| ACTIVE| |Built-in model in IoTDB|
| _GaussianHMM|BUILT_IN_ANOMALY_DETECTION| ACTIVE| |Built-in model in IoTDB|
| _GMMHMM|BUILT_IN_ANOMALY_DETECTION| ACTIVE| |Built-in model in IoTDB|
| _Stray|BUILT_IN_ANOMALY_DETECTION| ACTIVE| |Built-in model in IoTDB|
+---------------------+--------------------------+-----------+------------------------------------------------------------+-----------------------+
我们前面已经注册了对应的模型,可以通过对应的指定查看模型状态,active表明模型注册成功,可用于推理。
删除模型
对于注册成功的模型,用户可以通过SQL进行删除。该操作除了删除configNode上的元信息外,还会删除所有AINode下的相关模型文件。其SQL如下:
drop model <model_name>
需要指定已经成功注册的模型model_name来删除对应的模型。由于模型删除涉及多个节点上的数据删除,操作不会立即完成,此时模型的状态为DROPPING,该状态的模型不能用于模型推理。
使用内置模型推理
SQL语法如下:
call inference(<built_in_model_name>,sql[,<parameterName>=<parameterValue>])
内置模型推理无需注册流程,通过call关键字,调用inference函数就可以使用模型的推理功能,其对应的参数介绍如下:
- built_in_model_name: 内置模型名称
- parameterName:参数名
- parameterValue:参数值
内置模型及参数说明
目前已内置如下机器学习模型,具体参数说明请参考以下链接。
模型 | built_in_model_name | 任务类型 | 参数说明 |
---|---|---|---|
Arima | _Arima | 预测 | Arima参数说明 |
STLForecaster | _STLForecaster | 预测 | STLForecaster参数说明 |
NaiveForecaster | _NaiveForecaster | 预测 | NaiveForecaster参数说明 |
ExponentialSmoothing | _ExponentialSmoothing | 预测 | ExponentialSmoothing参数说明 |
GaussianHMM | _GaussianHMM | 标注 | GaussianHMM参数说明 |
GMMHMM | _GMMHMM | 标注 | GMMHMM参数说明 |
Stray | _Stray | 异常检测 | Stray参数说明 |
示例
下面是使用内置模型推理的一个操作示例,使用内置的Stray模型进行异常检测算法,输入为[144,1]
,输出为[144,1]
,我们通过SQL使用其进行推理。
IoTDB> select * from root.eg.airline
+-----------------------------+------------------+
| Time|root.eg.airline.s0|
+-----------------------------+------------------+
|1949-01-31T00:00:00.000+08:00| 224.0|
|1949-02-28T00:00:00.000+08:00| 118.0|
|1949-03-31T00:00:00.000+08:00| 132.0|
|1949-04-30T00:00:00.000+08:00| 129.0|
......
|1960-09-30T00:00:00.000+08:00| 508.0|
|1960-10-31T00:00:00.000+08:00| 461.0|
|1960-11-30T00:00:00.000+08:00| 390.0|
|1960-12-31T00:00:00.000+08:00| 432.0|
+-----------------------------+------------------+
Total line number = 144
IoTDB> call inference(_Stray, "select s0 from root.eg.airline", k=2)
+-------+
|output0|
+-------+
| 0|
| 0|
| 0|
| 0|
......
| 1|
| 1|
| 0|
| 0|
| 0|
| 0|
+-------+
Total line number = 144
使用深度学习模型推理
SQL语法如下:
call inference(<model_name>,sql[,window=<window_function>])
window_function:
head(window_size)
tail(window_size)
count(window_size,sliding_step)
在完成模型的注册后,通过call关键字,调用inference函数就可以使用模型的推理功能,其对应的参数介绍如下:
- model_name: 对应一个已经注册的模型
- sql:sql查询语句,查询的结果作为模型的输入进行模型推理。查询的结果中行列的维度需要与具体模型config中指定的大小相匹配。(这里的sql不建议使用
SELECT *
子句,因为在IoTDB中,*
并不会对列进行排序,因此列的顺序是未定义的,可以使用SELECT s0,s1
的方式确保列的顺序符合模型输入的预期) - window_function: 推理过程中可以使用的窗口函数,目前提供三种类型的窗口函数用于辅助模型推理:
head(window_size): 获取数据中最前的window_size个点用于模型推理,该窗口可用于数据裁剪
tail(window_size):获取数据中最后的window_size个点用于模型推,该窗口可用于数据裁剪
count(window_size, sliding_step):基于点数的滑动窗口,每个窗口的数据会分别通过模型进行推理,如下图示例所示,window_size为2的窗口函数将输入数据集分为三个窗口,每个窗口分别进行推理运算生成结果。该窗口可用于连续推理
说明1: window可以用来解决sql查询结果和模型的输入行数要求不一致时的问题,对行进行裁剪。需要注意的是,当列数不匹配或是行数直接少于模型需求时,推理无法进行,会返回错误信息。
说明2: 在深度学习应用中,经常将时间戳衍生特征(数据中的时间列)作为生成式任务的协变量,一同输入到模型中以提升模型的效果,但是在模型的输出结果中一般不包含时间列。为了保证实现的通用性,模型推理结果只对应模型的真实输出,如果模型不输出时间列,则结果中不会包含。
示例
下面是使用深度学习模型推理的一个操作示例,针对上面提到的输入为[96,2]
,输出为[48,2]
的dlinear
预测模型,我们通过SQL使用其进行推理。
IoTDB> select s1,s2 from root.**
+-----------------------------+-------------------+-------------------+
| Time| root.eg.etth.s0| root.eg.etth.s1|
+-----------------------------+-------------------+-------------------+
|1990-01-01T00:00:00.000+08:00| 0.7855| 1.611|
|1990-01-02T00:00:00.000+08:00| 0.7818| 1.61|
|1990-01-03T00:00:00.000+08:00| 0.7867| 1.6293|
|1990-01-04T00:00:00.000+08:00| 0.786| 1.637|
|1990-01-05T00:00:00.000+08:00| 0.7849| 1.653|
|1990-01-06T00:00:00.000+08:00| 0.7866| 1.6537|
|1990-01-07T00:00:00.000+08:00| 0.7886| 1.662|
......
|1990-03-31T00:00:00.000+08:00| 0.7585| 1.678|
|1990-04-01T00:00:00.000+08:00| 0.7587| 1.6763|
|1990-04-02T00:00:00.000+08:00| 0.76| 1.6813|
|1990-04-03T00:00:00.000+08:00| 0.7669| 1.684|
|1990-04-04T00:00:00.000+08:00| 0.7645| 1.677|
|1990-04-05T00:00:00.000+08:00| 0.7625| 1.68|
|1990-04-06T00:00:00.000+08:00| 0.7617| 1.6917|
+-----------------------------+-------------------+-------------------+
Total line number = 96
IoTDB> call inference(dlinear_example,"select s0,s1 from root.**")
+--------------------------------------------+-----------------------------+
| _result_0| _result_1|
+--------------------------------------------+-----------------------------+
| 0.726302981376648| 1.6549958229064941|
| 0.7354921698570251| 1.6482787370681763|
| 0.7238251566886902| 1.6278168201446533|
......
| 0.7692174911499023| 1.654654049873352|
| 0.7685555815696716| 1.6625318765640259|
| 0.7856493592262268| 1.6508299350738525|
+--------------------------------------------+-----------------------------+
Total line number = 48
使用tail/head窗口函数的示例
当数据量不定且想要取96行最新数据用于推理时,可以使用对应的窗口函数tail。head函数的用法与其类似,不同点在于其取的是最早的96个点。
IoTDB> select s1,s2 from root.**
+-----------------------------+-------------------+-------------------+
| Time| root.eg.etth.s0| root.eg.etth.s1|
+-----------------------------+-------------------+-------------------+
|1988-01-01T00:00:00.000+08:00| 0.7355| 1.211|
......
|1990-01-01T00:00:00.000+08:00| 0.7855| 1.611|
|1990-01-02T00:00:00.000+08:00| 0.7818| 1.61|
|1990-01-03T00:00:00.000+08:00| 0.7867| 1.6293|
|1990-01-04T00:00:00.000+08:00| 0.786| 1.637|
|1990-01-05T00:00:00.000+08:00| 0.7849| 1.653|
|1990-01-06T00:00:00.000+08:00| 0.7866| 1.6537|
|1990-01-07T00:00:00.000+08:00| 0.7886| 1.662|
......
|1990-03-31T00:00:00.000+08:00| 0.7585| 1.678|
|1990-04-01T00:00:00.000+08:00| 0.7587| 1.6763|
|1990-04-02T00:00:00.000+08:00| 0.76| 1.6813|
|1990-04-03T00:00:00.000+08:00| 0.7669| 1.684|
|1990-04-04T00:00:00.000+08:00| 0.7645| 1.677|
|1990-04-05T00:00:00.000+08:00| 0.7625| 1.68|
|1990-04-06T00:00:00.000+08:00| 0.7617| 1.6917|
+-----------------------------+-------------------+-------------------+
Total line number = 996
IoTDB> call inference(dlinear_example,"select s0,s1 from root.**",window=tail(96))
+--------------------------------------------+-----------------------------+
| _result_0| _result_1|
+--------------------------------------------+-----------------------------+
| 0.726302981376648| 1.6549958229064941|
| 0.7354921698570251| 1.6482787370681763|
| 0.7238251566886902| 1.6278168201446533|
......
| 0.7692174911499023| 1.654654049873352|
| 0.7685555815696716| 1.6625318765640259|
| 0.7856493592262268| 1.6508299350738525|
+--------------------------------------------+-----------------------------+
Total line number = 48
使用count窗口函数的示例
该窗口主要用于计算式任务,当任务对应的模型一次只能处理固定行数据而最终想要的确实多组预测结果时,使用该窗口函数可以使用点数滑动窗口进行连续推理。假设我们现在有一个异常检测模型anomaly_example(input: [24,2], output[1,1]),对每24行数据会生成一个0/1的标签,其使用示例如下:
IoTDB> select s1,s2 from root.**
+-----------------------------+-------------------+-------------------+
| Time| root.eg.etth.s0| root.eg.etth.s1|
+-----------------------------+-------------------+-------------------+
|1990-01-01T00:00:00.000+08:00| 0.7855| 1.611|
|1990-01-02T00:00:00.000+08:00| 0.7818| 1.61|
|1990-01-03T00:00:00.000+08:00| 0.7867| 1.6293|
|1990-01-04T00:00:00.000+08:00| 0.786| 1.637|
|1990-01-05T00:00:00.000+08:00| 0.7849| 1.653|
|1990-01-06T00:00:00.000+08:00| 0.7866| 1.6537|
|1990-01-07T00:00:00.000+08:00| 0.7886| 1.662|
......
|1990-03-31T00:00:00.000+08:00| 0.7585| 1.678|
|1990-04-01T00:00:00.000+08:00| 0.7587| 1.6763|
|1990-04-02T00:00:00.000+08:00| 0.76| 1.6813|
|1990-04-03T00:00:00.000+08:00| 0.7669| 1.684|
|1990-04-04T00:00:00.000+08:00| 0.7645| 1.677|
|1990-04-05T00:00:00.000+08:00| 0.7625| 1.68|
|1990-04-06T00:00:00.000+08:00| 0.7617| 1.6917|
+-----------------------------+-------------------+-------------------+
Total line number = 96
IoTDB> call inference(anomaly_example,"select s0,s1 from root.**",window=count(24,24))
+-------------------------+
| _result_0|
+-------------------------+
| 0|
| 1|
| 1|
| 0|
+-------------------------+
Total line number = 4
其中结果集中每行的标签对应每24行数据为一组,输入该异常检测模型后的输出。
权限管理
使用AINode相关的功能时,可以使用IoTDB本身的鉴权去做一个权限管理,用户只有在具备 USE_MODEL 权限时,才可以使用模型管理的相关功能。当使用推理功能时,用户需要有访问输入模型的SQL对应的源序列的权限。
权限名称 | 权限范围 | 管理员用户(默认ROOT) | 普通用户 | 路径相关 |
---|---|---|---|---|
USE_MODEL | create model / show models / drop model | √ | √ | x |
READ_DATA | call inference | √ | √ | √ |
实际案例
电力负载预测
在部分工业场景下,会存在预测电力负载的需求,预测结果可用于优化电力供应、节约能源和资源、支持规划和扩展以及增强电力系统的可靠性。
我们所使用的 ETTh1 的测试集的数据为ETTh1。
包含间隔1h采集一次的电力数据,每条数据由负载和油温构成,分别为:High UseFul Load, High UseLess Load, Middle UseLess Load, Low UseFul Load, Low UseLess Load, Oil Temperature。
在该数据集上,IoTDB-ML的模型推理功能可以通过以往高中低三种负载的数值和对应时间戳油温的关系,预测未来一段时间内的油温,赋能电网变压器的自动调控和监视。
步骤一:数据导入
用户可以使用tools文件夹中的import-csv.sh
向 IoTDB 中导入 ETT 数据集
bash ./import-csv.sh -h 127.0.0.1 -p 6667 -u root -pw root -f ../../ETTh1.csv
步骤二:模型导入
我们可以在iotdb-cli 中输入以下SQL从 huggingface 上拉取一个已经训练好的模型进行注册,用于后续的推理。
create model dlinear using uri 'https://huggingface.co/hvlgo/dlinear/resolve/main'
该模型基于较为轻量化的深度模型DLinear训练而得,能够以相对快的推理速度尽可能多地捕捉到序列内部的变化趋势和变量间的数据变化关系,相较于其他更深的模型更适用于快速实时预测。
步骤三:模型推理
IoTDB> select s0,s1,s2,s3,s4,s5,s6 from root.eg.etth LIMIT 96
+-----------------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
| Time|root.eg.etth.s0|root.eg.etth.s1|root.eg.etth.s2|root.eg.etth.s3|root.eg.etth.s4|root.eg.etth.s5|root.eg.etth.s6|
+-----------------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
|2017-10-20T00:00:00.000+08:00| 10.449| 3.885| 8.706| 2.025| 2.041| 0.944| 8.864|
|2017-10-20T01:00:00.000+08:00| 11.119| 3.952| 8.813| 2.31| 2.071| 1.005| 8.442|
|2017-10-20T02:00:00.000+08:00| 9.511| 2.88| 7.533| 1.564| 1.949| 0.883| 8.16|
|2017-10-20T03:00:00.000+08:00| 9.645| 2.21| 7.249| 1.066| 1.828| 0.914| 7.949|
......
|2017-10-23T20:00:00.000+08:00| 8.105| 0.938| 4.371| -0.569| 3.533| 1.279| 9.708|
|2017-10-23T21:00:00.000+08:00| 7.167| 1.206| 4.087| -0.462| 3.107| 1.432| 8.723|
|2017-10-23T22:00:00.000+08:00| 7.1| 1.34| 4.015| -0.32| 2.772| 1.31| 8.864|
|2017-10-23T23:00:00.000+08:00| 9.176| 2.746| 7.107| 1.635| 2.65| 1.097| 9.004|
+-----------------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+
Total line number = 96
IoTDB> call inference(dlinear_example, "select s0,s1,s2,s3,s4,s5,s6 from root.eg.etth", window=head(96))
+-----------+----------+----------+------------+---------+----------+----------+
| output0| output1| output2| output3| output4| output5| output6|
+-----------+----------+----------+------------+---------+----------+----------+
| 10.319546| 3.1450553| 7.877341| 1.5723765|2.7303758| 1.1362307| 8.867775|
| 10.443649| 3.3286757| 7.8593454| 1.7675098| 2.560634| 1.1177158| 8.920919|
| 10.883752| 3.2341104| 8.47036| 1.6116762|2.4874182| 1.1760603| 8.798939|
......
| 8.0115595| 1.2995274| 6.9900327|-0.098746896| 3.04923| 1.176214| 9.548782|
| 8.612427| 2.5036244| 5.6790237| 0.66474205|2.8870275| 1.2051733| 9.330128|
| 10.096699| 3.399722| 6.9909| 1.7478468|2.7642853| 1.1119363| 9.541455|
+-----------+----------+----------+------------+---------+----------+----------+
Total line number = 48
我们将对油温的预测的结果和真实结果进行对比,可以得到以下的图像。
图中10/24 00:00之前的数据为输入模型的过去数据,10/24 00:00后的蓝色线条为模型给出的油温预测结果,而红色为数据集中实际的油温数据(用于进行对比)。
可以看到,我们使用了过去96个小时(4天)的六个负载信息和对应时间油温的关系,基于之前学习到的序列间相互关系对未来48个小时(2天)的油温这一数据的可能变化进行了建模,可以看到可视化后预测曲线与实际结果在趋势上保持了较高程度的一致性。
功率预测
变电站需要对电流、电压、功率等数据进行电力监控,用于检测潜在的电网问题、识别电力系统中的故障、有效管理电网负载以及分析电力系统的性能和趋势等。
我们利用某变电站中的电流、电压和功率等数据构成了真实场景下的数据集。该数据集包括变电站近四个月时间跨度,每5 - 6s 采集一次的 A相电压、B相电压、C相电压等数据。
测试集数据内容为data。
在该数据集上,IoTDB-ML的模型推理功能可以通过以往A相电压,B相电压和C相电压的数值和对应时间戳,预测未来一段时间内的C相电压,赋能变电站的监视管理。
步骤一:数据导入
用户可以使用tools文件夹中的import-csv.sh
导入数据集
bash ./import-csv.sh -h 127.0.0.1 -p 6667 -u root -pw root -f ../../data.csv
步骤二:模型导入
我们可以在iotdb-cli 中选择内置模型或已经注册好的模型用于后续的推理。
我们采用内置模型STLForecaster进行预测,STLForecaster 是一个基于 statsmodels 库中 STL 实现的时间序列预测方法。
步骤三:模型推理
IoTDB> select * from root.eg.voltage limit 96
+-----------------------------+------------------+------------------+------------------+
| Time|root.eg.voltage.s0|root.eg.voltage.s1|root.eg.voltage.s2|
+-----------------------------+------------------+------------------+------------------+
|2023-02-14T20:38:32.000+08:00| 2038.0| 2028.0| 2041.0|
|2023-02-14T20:38:38.000+08:00| 2014.0| 2005.0| 2018.0|
|2023-02-14T20:38:44.000+08:00| 2014.0| 2005.0| 2018.0|
......
|2023-02-14T20:47:52.000+08:00| 2024.0| 2016.0| 2027.0|
|2023-02-14T20:47:57.000+08:00| 2024.0| 2016.0| 2027.0|
|2023-02-14T20:48:03.000+08:00| 2024.0| 2016.0| 2027.0|
+-----------------------------+------------------+------------------+------------------+
Total line number = 96
IoTDB> call inference(_STLForecaster, "select s0,s1,s2 from root.eg.voltage", window=head(96),predict_length=48)
+---------+---------+---------+
| output0| output1| output2|
+---------+---------+---------+
|2026.3601|2018.2953|2029.4257|
|2019.1538|2011.4361|2022.0888|
|2025.5074|2017.4522|2028.5199|
......
|2022.2336|2015.0290|2025.1023|
|2015.7241|2008.8975|2018.5085|
|2022.0777|2014.9136|2024.9396|
|2015.5682|2008.7821|2018.3458|
+---------+---------+---------+
Total line number = 48
我们将对C相电压的预测的结果和真实结果进行对比,可以得到以下的图像。
图中 02/14 20:48 之前的数据为输入模型的过去数据, 02/14 20:48 后的蓝色线条为模型给出的C相电压预测结果,而红色为数据集中实际的C相电压数据(用于进行对比)。
可以看到,我们使用了过去10分钟的电压的数据,基于之前学习到的序列间相互关系对未来5分钟的C相电压这一数据的可能变化进行了建模,可以看到可视化后预测曲线与实际结果在趋势上保持了一定的同步性。
异常检测
在民航交通运输业,存在着对乘机旅客数量进行异常检测的需求。异常检测的结果可用于指导调整航班的调度,以使得企业获得更大效益。
Airline Passengers一个时间序列数据集,该数据集记录了1949年至1960年期间国际航空乘客数量,间隔一个月进行一次采样。该数据集共含一条时间序列。数据集为airline。
在该数据集上,IoTDB-ML的模型推理功能可以通过捕捉序列的变化规律以对序列时间点进行异常检测,赋能交通运输业。
步骤一:数据导入
用户可以使用tools文件夹中的import-csv.sh
导入数据集
bash ./import-csv.sh -h 127.0.0.1 -p 6667 -u root -pw root -f ../../data.csv
步骤二:模型推理
IoTDB内置有部分可以直接使用的机器学习算法,使用其中的异常检测算法进行预测的样例如下:
IoTDB> select * from root.eg.airline
+-----------------------------+------------------+
| Time|root.eg.airline.s0|
+-----------------------------+------------------+
|1949-01-31T00:00:00.000+08:00| 224.0|
|1949-02-28T00:00:00.000+08:00| 118.0|
|1949-03-31T00:00:00.000+08:00| 132.0|
|1949-04-30T00:00:00.000+08:00| 129.0|
......
|1960-09-30T00:00:00.000+08:00| 508.0|
|1960-10-31T00:00:00.000+08:00| 461.0|
|1960-11-30T00:00:00.000+08:00| 390.0|
|1960-12-31T00:00:00.000+08:00| 432.0|
+-----------------------------+------------------+
Total line number = 144
IoTDB> call inference(_Stray, "select s0 from root.eg.airline", k=2)
+-------+
|output0|
+-------+
| 0|
| 0|
| 0|
| 0|
......
| 1|
| 1|
| 0|
| 0|
| 0|
| 0|
+-------+
Total line number = 144
我们将检测为异常的结果进行绘制,可以得到以下图像。其中蓝色曲线为原时间序列,用红色点特殊标注的时间点为算法检测为异常的时间点。
可以看到,Stray模型对输入序列变化进行了建模,成功检测出出现异常的时间点。