# Machine Learning module is triggering alerts when there is no anomaly

**URL:** <https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974>\
**Category:** Elasticsearch\
**Tags:** elastic-stack-machine-learning\
**Created:** [April 29, 2019, 6:23pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974 "2019-04-29T18:23:22Z")\
**Posts on this page:** 8\
**Page:** 2

<div class="post-metadata">

**Author:** ![Josh\_A](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/josh_a/32/42035_2.png) [@Josh\_A](https://discuss.elastic.co/u/Josh_A)\
**Post date:** [May 9, 2019, 8:11pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/21 "2019-05-09T20:11:55Z")

</div>

This all makes a ton of sense, and we'll create a watch that focuses on `result_type:record`, as opposed to the automatically generated watch that I guess focuses on bucket.

I'm still not understanding the anomaly scoring, though.

I understand that a `record` anomaly is created (and scored) for any entity identified by a defector and/or entity. But when you say "the `bucket` level score is the aggregation of all anomalies in that bucket," does that mean that it's simply adding together the anomaly score for all of the anomalies?

If I go back to my April 27th 2019 10:00 example, I see two `record` anomalies, each with an `anomaly_score` of 93.994. But the `bucket` anomaly for the same hour and day has a `max severity` of 59. How do two 93.994's become a 59?

Thanks again for all of your help.

---

<div class="post-metadata">

**Author:** ![richcollier](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/richcollier/32/115035_2.png) [@richcollier](https://discuss.elastic.co/u/richcollier)\
**Post date:** [May 9, 2019, 8:26pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/22 "2019-05-09T20:26:31Z")

</div>

The `bucket` level score isn't a simple sum() or max() or whatever of the constituent individual anomalies in that bucket. It is more like a "joint probability" (the likelihood that those things are unusual _ **together** _).

Although, it can be more intuitive to think of it as "given all the anomalies (and their individual scores) that exist in that bucket, how unusual was that time bucket?" So, it is not just the number, but also the severity. Therefore, a small number of massive anomalous hosts should get a higher bucket score than a larger number of very minor anomalies.

---

<div class="post-metadata">

**Author:** ![Josh\_A](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/josh_a/32/42035_2.png) [@Josh\_A](https://discuss.elastic.co/u/Josh_A)\
**Post date:** [May 13, 2019, 6:11pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/23 "2019-05-13T18:11:25Z")

</div>

Got it. Thanks very much, Rich.

---

<div class="post-metadata">

**Author:** ![Josh\_A](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/josh_a/32/42035_2.png) [@Josh\_A](https://discuss.elastic.co/u/Josh_A)\
**Post date:** [June 3, 2019, 12:57pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/24 "2019-06-03T12:57:01Z")

</div>

Hey Rich - does this look like query logic for a Watcher that will accomplish the goal of triggering on record level anomalies? Thanks!

```
{
  "trigger": {
    "schedule": {
      "interval": "106s"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          ".ml-anomalies-*"
        ],
        "types": [],
        "body": {
          "size": 0,
          "query": {
            "bool": {
              "filter": [
                {
                  "term": {
                    "job_id": "sonicwall-anomalies"
                  }
                },
                {
                  "range": {
                    "timestamp": {
                      "gte": "now-120m"
                    }
                  }
                },
                {
                  "terms": {
                    "result_type": [
                      "record"
                    ]
                  }
                }
              ]
            }
          },
          "aggs": {
            "bucket_results": {
              "filter": {
                "range": {
                  "anomaly_score": {
                    "gte": 90
                  }
                }
              },
              "aggs": {
                "top_bucket_hits": {
                  "top_hits": {
                    "sort": [
                      {
                        "anomaly_score": {
                          "order": "desc"
                        }
                      }
                    ],
                    "_source": {
                      "includes": [
                        "job_id",
                        "result_type",
                        "timestamp",
                        "anomaly_score",
                        "is_interim"
                      ]
                    },
                    "size": 1,
                    "script_fields": {
                      "start": {
                        "script": {
                          "lang": "painless",
                          "inline": "LocalDateTime.ofEpochSecond((doc[\"timestamp\"].date.getMillis()-((doc[\"bucket_span\"].value * 1000)\n * params.padding)) / 1000, 0, ZoneOffset.UTC).toString()+\":00.000Z\"",
                          "params": {
                            "padding": 10
                          }
                        }
                      },
                      "end": {
                        "script": {
                          "lang": "painless",
                          "inline": "LocalDateTime.ofEpochSecond((doc[\"timestamp\"].date.getMillis()+((doc[\"bucket_span\"].value * 1000)\n * params.padding)) / 1000, 0, ZoneOffset.UTC).toString()+\":00.000Z\"",
                          "params": {
                            "padding": 10
                          }
                        }
                      },
                      "timestamp_epoch": {
                        "script": {
                          "lang": "painless",
                          "inline": "doc[\"timestamp\"].date.getMillis()/1000"
                        }
                      },
                      "timestamp_iso8601": {
                        "script": {
                          "lang": "painless",
                          "inline": "doc[\"timestamp\"].date"
                        }
                      },
                      "score": {
                        "script": {
                          "lang": "painless",
                          "inline": "Math.round(doc[\"anomaly_score\"].value)"
                        }
                      }
                    }
                  }
                }
              }
            },
            "influencer_results": {
              "filter": {
                "range": {
                  "influencer_score": {
                    "gte": 3
                  }
                }
              },
              "aggs": {
                "top_influencer_hits": {
                  "top_hits": {
                    "sort": [
                      {
                        "influencer_score": {
                          "order": "desc"
                        }
                      }
                    ],
                    "_source": {
                      "includes": [
                        "result_type",
                        "timestamp",
                        "influencer_field_name",
                        "influencer_field_value",
                        "influencer_score",
                        "isInterim"
                      ]
                    },
                    "size": 3,
                    "script_fields": {
                      "score": {
                        "script": {
                          "lang": "painless",
                          "inline": "Math.round(doc[\"influencer_score\"].value)"
                        }
                      }
                    }
                  }
                }
              }
            },
            "record_results": {
              "filter": {
                "range": {
                  "record_score": {
                    "gte": 3
                  }
                }
              },

```

(continued in next post)

---

<div class="post-metadata">

**Author:** ![Josh\_A](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/josh_a/32/42035_2.png) [@Josh\_A](https://discuss.elastic.co/u/Josh_A)\
**Post date:** [June 3, 2019, 12:57pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/25 "2019-06-03T12:57:12Z")

</div>

```
          "aggs": {
            "top_record_hits": {
              "top_hits": {
                "sort": [
                  {
                    "record_score": {
                      "order": "desc"
                    }
                  }
                ],
                "_source": {
                  "includes": [
                    "result_type",
                    "timestamp",
                    "record_score",
                    "is_interim",
                    "function",
                    "field_name",
                    "by_field_value",
                    "over_field_value",
                    "partition_field_value"
                  ]
                },
                "size": 3,
                "script_fields": {
                  "score": {
                    "script": {
                      "lang": "painless",
                      "inline": "Math.round(doc[\"record_score\"].value)"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
  },
  "condition": {
    "compare": {
      "ctx.payload.aggregations.bucket_results.doc_count": {
        "gt": 0
      }
    }
  },
```

---

<div class="post-metadata">

**Author:** ![richcollier](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/richcollier/32/115035_2.png) [@richcollier](https://discuss.elastic.co/u/richcollier)\
**Post date:** [June 3, 2019, 1:07pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/26 "2019-06-03T13:07:26Z")

</div>

Seems like so - but you'll still need a way to manage the multiple results that you get (because there are likely going to be more than 1 anomaly records returned from each query).

I assume that you'll do something similar to the example I showed in:

> <https://gist.github.com/richcollier/1c2b8161286bdca6c553859f28d3d66d>

---

<div class="post-metadata">

**Author:** ![Josh\_A](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/josh_a/32/42035_2.png) [@Josh\_A](https://discuss.elastic.co/u/Josh_A)\
**Post date:** [June 3, 2019, 1:28pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/27 "2019-06-03T13:28:25Z")

</div>

Great, thanks Rich!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 1, 2019, 1:28pm UTC](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974/28 "2019-07-01T13:28:34Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.

[Previous page](https://discuss.elastic.co/t/machine-learning-module-is-triggering-alerts-when-there-is-no-anomaly/178974.md?page=1)
