Update 03-ad.md

This commit is contained in:
Haojun Liao 2024-11-12 16:47:10 +08:00 committed by GitHub
parent f99c55d8fd
commit f77e16301c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 36 additions and 42 deletions

View File

@ -3,80 +3,74 @@ title: "异常检测"
sidebar_label: "异常检测"
---
### 核心方法输入与输出约定
### 输入约定
`execute` 是算法处理的核心方法。框架调用该方法之前,在对象属性参数 `self.list` 中已经设置完毕用于异常检测的时间序列数据。
`execute` 是算法处理的核心方法。调用该方法的时候,`self.list` 已经设置好输入数组。
### 输出约定
`execute` 方法执行完成后的返回值是长度与 `self.list` 相同的数组,数组位置 -1 的标识异常值点。
> 例如:对于输入测量值序列 [2, 2, 2, 2, 100] 假设 100 是异常点,那么方法返回的结果数组则为 [1, 1, 1, 1, -1]。
异常检测输出结果
`execute` 的返回值是长度与 `self.list` 相同的数组,数组位置为 -1 的即为异常值点。例如:输入数组是 [2, 2, 2, 2, 100] 如果 100 是异常点,那么返回值是 [1, 1, 1, 1, -1]。
预测输出结果
## 示例代码
### 示例代码
下面我们开发一个示例异常检测算法,在异常检测中,将输入时间序列值的最后一个值设置为异常值,并返回结果。
```python
import numpy as np
from service import AbstractAnomalyDetectionService
# 算法实现类名称 需要以下划线 "_" 开始,并以 Service 结束,如下 _IqrService 是 IQR 异常检测算法的实现类。
class _IqrService(AbstractAnomalyDetectionService):
""" IQR algorithm 定义类,从 AbstractAnomalyDetectionService 继承,并实现 AbstractAnomalyDetectionService 类的抽象函数 """
# 算法实现类名称 需要以下划线 "_" 开始,并以 Service 结束
class _MyAnomalyDetectionService(AbstractAnomalyDetectionService):
""" 定义类,从 AbstractAnomalyDetectionService 继承,并实现 AbstractAnomalyDetectionService 类的抽象方法 """
# 定义算法调用关键词全小写ASCII码(必须添加)
name = 'iqr'
# 定义算法调用关键词全小写ASCII码
name = 'myad'
# 该算法的描述信息(建议添加)
desc = """found the anomaly data according to the inter-quartile range"""
# 该算法的描述信息(建议添加)
desc = """return the last value as the anomaly data"""
def __init__(self):
"""类初始化方法"""
super().__init__()
def execute(self):
""" execute 是算法实现逻辑的核心实现,直接修改该实现即可 """
""" 算法逻辑的核心实现"""
# self.list 是输入数值列list 类型,例如:[1,2,3,4,5]。设置 self.list 的方法在父类中已经进行了定义。实现自己的算法,修改该文件即可,以下代码使用自己的实现替换即可。
#lower = np.quantile(self.list, 0.25)
#upper = np.quantile(self.list, 0.75)
"""创建一个长度为 len(self.list),全部值为 1 的结果数组,然后将最后一个值设置为 -1表示最后一个值是异常值"""
res = [1] * len(self.list)
res[-1] = -1
#min_val = lower - 1.5 * (upper - lower)
#max_val = upper + 1.5 * (upper - lower)
#threshold = [min_val, max_val]
# 返回值是与输入数值列长度相同的数据列,异常值对应位置是 -1。例如上述输入数据列返回数值列是 [1, 1, 1, 1, -1],表示 [5] 是异常值。
return [-1 if k < threshold[0] or k > threshold[1] else 1 for k in self.list]
"""返回结果数组"""
return res
def set_params(self, params):
"""该算法无需任何输入参数,直接重载父类该函数,不处理算法参数设置逻辑"""
"""该算法无需任何输入参数,直接重载父类该函数,不处理算法参数设置逻辑"""
pass
```
将该文件保存在 `./taosanalytics/algo/ad/` 目录下,然后重启 taosanode 服务。然后就可以通过 SQL 语句调用该检测算法。
## 单元测试
```SQL
--- 对 col 列进行异常检测,通过指定 algo 参数为 myad 来调用新添加的异常检测类
SELECT COUNT(*) FROM foo ANOMALY_DETECTION(col, 'algo=myad')
```
在测试文件目录中的 anomaly_test.py 中增加单元测试用例。
### 单元测试
在测试目录`taosanalytics/test`中的 anomaly_test.py 中增加单元测试用例或添加新的测试文件。框架中使用了 Python Unit test 包。
```python
def test_iqr(self):
""" 测试 _IqrService 类 """
s = loader.get_service("iqr")
def test_myad(self):
""" 测试 _IqrService 类 """
s = loader.get_service("myad")
# 设置需要进行检测的输入数据
s.set_input_list(AnomalyDetectionTest.input_list)
# 测试 set_params 的处理逻辑
try:
s.set_params({"k": 2})
except ValueError as e:
self.assertEqual(1, 0)
r = s.execute()
# 绘制异常检测结果
draw_ad_results(AnomalyDetectionTest.input_list, r, "iqr")
# 检查结果
# 最后一个点是异常点
self.assertEqual(r[-1], -1)
self.assertEqual(len(r), len(AnomalyDetectionTest.input_list))
```