本文介绍统计类算法(esd、ttest和nsigma)的参数调优方法。
背景信息
统计类算法(esd、ttest和nsigma)可以根据历史数据为每一个数据点计算异常分数anomalyScore。算法的输入参数(如esd.alpha、ttest.alpha和nsigma.n)会决定判断阈值threshold。当anomalyScore的值大于threshold的值时,当前数据点异常;anomalyScore的值小于threshold的取值时,当前数据点正常。
对于esd和ttest算法,esd.alpha和ttest.alpha越大,检测算法越灵敏,可以检测出更多的异常点。反之,esd.alpha和ttest.alpha越小,检测算法越不灵敏,可以检测出的异常更少。而对于nsigma算法,当nsigma.n值越小时,检测算法越灵敏,可以检测出更多的异常点。反之,nsigma.n越大,检测算法越不灵敏,可以检测出的异常更少。
统计类算法的适用场景及参数说明,请参见时序异常检测。
参数设置
- 如果您希望检测结果中无任何异常被遗漏,请参考以下方法设置参数,提高算法的灵敏度:
- 对于esd算法,请设置较大的esd.alpha值,如设置
esd.alpha=0.3
。 - 对于ttest算法,请设置较大的ttest.alpha值,如设置
ttest.alpha=0.2
。 - 对于nsigma算法,请设置较小的nsigma.n值,如设置
nsigma.n=1
。
重要 如果检测参数的值设置得过大,可能会导致异常点过多,不符合业务预期。 - 对于esd算法,请设置较大的esd.alpha值,如设置
- 如果您只想关注较严重的异常,请参考以下方法设置参数,降低算法的灵敏度:
- 对于esd算法,请设置较小的esd.alpha值,如设置
esd.alpha=0.05
。 - 对于ttest算法,请设置较小的ttest.alpha值,如设置
ttest.alpha=0.01
。 - 对于nsigma算法,请设置较大nsigma.n值,如设置
nsigma.n=5
。
重要 如果检测参数的值设置得过小,可能只会报出严重的异常,即检测结果可能存在遗漏,不符合业务预期。 - 对于esd算法,请设置较小的esd.alpha值,如设置
- 您也可以根据实际数据分布,参考以下常见场景来设置参数。常见场景及优化方法,请参见常见场景。
常见场景
检出的异常点太少或太多
优化方法:
通过调整算法的敏感度,降低或升高判断阈值。
- esd/ttest算法:上调alpha使算法更敏感(即降低判断阈值),检测出更多的异常点;反之可以减少检测出的异常点的数量。示例如下:参数说明:
//将alpha上调至0.2,使算法更敏感,检测出更多异常点 SELECT xx, anomaly_detect(mean_duration, 'esd', 'alpha=0.2') as res FROM xxx SAMPLE BY 0; SELECT xx, anomaly_detect(mean_duration, 'ttest', 'alpha=0.2') as res FROM xxx SAMPLE BY 0;
alpha:esd/ttest算法异常检测的敏感程度。取值范围为(0, 1)。esd算法中alpha参数的默认值为0.1,ttest算法中alpha参数的默认值为0.05。
- nsigma算法:下调n使算法更敏感,检测出更多的异常点;反之可以减少检测出的异常点的数量。示例如下:参数说明:
//调整n至2,使算法更敏感,检测出更多异常点 SELECT xx, anomaly_detect(mean_duration, 'nsigma', 'n=2') as res FROM xxx SAMPLE BY 0
n:nsigma算法异常检测的阈值。nsigma算法中n参数的默认值为3,使用时需满足
n≠0
。
特定数据点检测结果调整
通过调整参数alpha或n,使特定数据点不触发异常警告。
以下时序异常检测结果表为例,res列为数据点的检测结果。可以观察到,mean_duration分别为13622.6和8651.6的两条记录被检测为异常。
+----------------------------+----------------+-------+
| time | mean_duration | res |
+----------------------------+----------------+-------+
| 2022-04-11T13:00:00+08:00 | 0 | false |
| 2022-04-11T14:00:00+08:00 | 0 | false |
| 2022-04-11T15:00:00+08:00 | 0 | false |
| 2022-04-11T16:00:00+08:00 | 0 | false |
| 2022-04-11T17:00:00+08:00 | 1136.3 | false |
|* 2022-04-11T18:00:00+08:00 | 13622.6 | true |
|* 2022-04-11T19:00:00+08:00 | 8651.6 | true |
| 2022-04-11T20:00:00+08:00 | 2735.46 | false |
| 2022-04-11T21:00:00+08:00 | 1496.683 | false |
| 2022-04-11T22:00:00+08:00 | 991.3175 | false |
+----------------------------+----------------+-------+
如果想让mean_duration为8651.6的数据点不触发异常警告,可按照以下步骤进行调优。
优化方法:
- 在算法参数中加条件
verbose=true
条件,打开verbose模式。SELECT xx, anomaly_detect(mean_duration, 'esd', 'verbose=true') as res FROM xxx SAMPLE BY 0
返回结果:+----------------------------+---------------+-------------+---------------------+--------------------+-----------------------+ | time | mean_duration | res$anomaly | res$anomalyScore | res$threshold | res$detectedDirection | +----------------------------+---------------+-------------+---------------------+--------------------+-----------------------+ | 2022-04-11T13:00:00+08:00 | 0 | false | 0 | 1.6447834844273468 | NONE | | 2022-04-11T14:00:00+08:00 | 0 | false | 0 | 1.6447834844273468 | NONE | | 2022-04-11T15:00:00+08:00 | 0 | false | 0 | 1.6447834844273468 | NONE | | 2022-04-11T16:00:00+08:00 | 0 | false | 0 | 1.6447834844273468 | NONE | | 2022-04-11T17:00:00+08:00 | 3136.3 | false | 0.6917962785972575 | 1.6447834844273468 | NONE | |* 2022-04-11T18:00:00+08:00 | 13622.6 | true | 3.0136653345953954 | 1.6447834844273468 | UP | |* 2022-04-11T19:00:00+08:00 | 8651.6 | true | 1.7122438285577357 | 1.6447834844273468 | UP | | 2022-04-11T20:00:00+08:00 | 6735.46 | false | 1.252994967798293 | 1.6447834844273468 | NONE | | 2022-04-11T21:00:00+08:00 | 1496.683 | false | 0 | 1.6447834844273468 | NONE | | 2022-04-11T22:00:00+08:00 | 1691.3175 | false | 0 | 1.6447834844273468 | NONE | +----------------------------+---------------+-------------+---------------------+--------------------+-----------------------+
时间为
2022-04-11T18:00:00+08:00
与2022-04-11T19:00:00+08:00
的两个记录满足了anomalyScore > threshold
的条件,因此被判定为异常。为了将2022-04-11T19:00:00+08:00
调整为正常点,则需通过调整alpha的值,将res$threshold调整至(1.71, 3.01)区间内。 - 将alpha从默认值0.1调整至0.05,降低算法的敏感度。
SELECT xx, anomaly_detect(mean_duration, 'esd', 'alpha=0.05, verbose=true') as res FROM xxx SAMPLE BY 0
返回结果:+----------------------------+---------------+-------------+---------------------+--------------------+-----------------------+ | time | mean_duration | res$anomaly | res$anomalyScore | res$threshold | res$detectedDirection | +----------------------------+---------------+-------------+---------------------+--------------------+-----------------------+ | 2022-04-11T13:00:00+08:00 | 0 | false | 0 | 1.9598247370788646 | NONE | | 2022-04-11T14:00:00+08:00 | 0 | false | 0 | 1.9598247370788646 | NONE | | 2022-04-11T15:00:00+08:00 | 0 | false | 0 | 1.9598247370788646 | NONE | | 2022-04-11T16:00:00+08:00 | 0 | false | 0 | 1.9598247370788646 | NONE | | 2022-04-11T17:00:00+08:00 | 3136.3 | false | 0.6917962785972575 | 1.9598247370788646 | NONE | |* 2022-04-11T18:00:00+08:00 | 13622.6 | true | 3.0136653345953954 | 1.9598247370788646 | UP | | 2022-04-11T19:00:00+08:00 | 8651.6 | false | 1.7122438285577357 | 1.9598247370788646 | NONE | | 2022-04-11T20:00:00+08:00 | 6735.46 | false | 1.252565839324602 | 1.9598247370788646 | NONE | | 2022-04-11T21:00:00+08:00 | 1496.683 | false | 0 | 1.9598247370788646 | NONE | | 2022-04-11T22:00:00+08:00 | 1691.3175 | false | 0 | 1.9598247370788646 | NONE | +----------------------------+---------------+-------------+---------------------+--------------------+-----------------------+
此时可观察到res$threshold列的值已变为
1.9598247370788646
,2022-04-11T18:00:00+08:00
对应记录依然会被识别为异常,而2022-04-11T19:00:00+08:00
对应的记录不再被识别为异常。
数据点增多后误报减少
数据点较少时,算法不稳定,可能会误报很多异常。当数据点相对较多后,误报才会减少,检测结果趋于正常。
优化方法:增大warmupCount参数的值。例如warmupCount=100
,表示算法在处理前100个数据点时,只会将其用于调整模型,不会报出异常。
脏数据导致变化幅度小的异常无法被检出
表中混入了脏数据,例如严重偏大的数据,可能会导致后续幅度变化较小的异常无法被检出。
reset_state=true
条件将模型重置,重新建立模型,示例如下:SELECT xx, anomaly_detect(mean_duration, 'esd', 'reset_state=true') as res FROM xxx WHERE time >= xxxx SAMPLE BY 0
代码改进后变化幅度小的异常无法被检出
业务代码改进后监控数据的波动变小,可能会导致一些变化幅度较小的异常无法被检出。
SELECT xx, anomaly_detect(mean_duration, 'esd', 'lenHistoryWindow=1000, reset_state=true') as res FROM xxx SAMPLE BY 0
此时算法只会参考最近1000个点的数据分布,为当前数据点计算anomalyScore。