本文介绍统计类算法(esd、ttest和nsigma)的参数调优方法。

背景信息

统计类算法(esd、ttest和nsigma)可以根据历史数据为每一个数据点计算异常分数anomalyScore。算法的输入参数(如esd.alphattest.alphansigma.n)会决定判断阈值threshold。当anomalyScore的值大于threshold的值时,当前数据点异常;anomalyScore的值小于threshold的取值时,当前数据点正常。

对于esd和ttest算法,esd.alphattest.alpha越大,检测算法越灵敏,可以检测出更多的异常点。反之,esd.alphattest.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.alpha=0.05
    • 对于ttest算法,请设置较小的ttest.alpha值,如设置ttest.alpha=0.01
    • 对于nsigma算法,请设置较大nsigma.n值,如设置nsigma.n=5
    重要 如果检测参数的值设置得过小,可能只会报出严重的异常,即检测结果可能存在遗漏,不符合业务预期。
  • 您也可以根据实际数据分布,参考以下常见场景来设置参数。常见场景及优化方法,请参见常见场景

常见场景

检出的异常点太少或太多

优化方法:

通过调整算法的敏感度,降低或升高判断阈值。

  • 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

特定数据点检测结果调整

通过调整参数alphan,使特定数据点不触发异常警告。

以下时序异常检测结果表为例,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_duration8651.6的数据点不触发异常警告,可按照以下步骤进行调优。

优化方法:

  1. 在算法参数中加条件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:002022-04-11T19:00:00+08:00的两个记录满足了anomalyScore > threshold的条件,因此被判定为异常。为了将2022-04-11T19:00:00+08:00调整为正常点,则需通过调整alpha的值,将res$threshold调整至(1.71, 3.01)区间内。

  2. 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.95982473707886462022-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

代码改进后变化幅度小的异常无法被检出

业务代码改进后监控数据的波动变小,可能会导致一些变化幅度较小的异常无法被检出。

优化方法:随着新数据的不断加入,算法会自动更新模型,漏报逐渐减少。如果您想立即调整检测效果,此时不建议通过调整参数alpha来控制算法敏感度,建议重置模型并调整参数lenHistoryWindow,示例如下:
SELECT xx, anomaly_detect(mean_duration, 'esd', 'lenHistoryWindow=1000, reset_state=true') as res FROM xxx SAMPLE BY 0

此时算法只会参考最近1000个点的数据分布,为当前数据点计算anomalyScore。