Учебник. Изучите основы многопараметрического обнаружения аномалий за один час

Детектор аномалий с поддержкой многопараметрического обнаружение аномалий (MVAD) — это усовершенствованное средство на основе ИИ для неконтролируемого обнаружения аномалий в группе метрик.

Вот общая последовательность действий по использованию MVAD.

  1. Создание в Azure ресурса "Детектор аномалий" с поддержкой MVAD.
  2. Подготовка данных.
  3. Обучение модели MVAD.
  4. Запрос состояния модели.
  5. Выявление аномалий с помощью обученной модели MVAD.
  6. Получение и интерпретация результатов вывода.

В этом руководстве вы выполните следующие действия.

  • Узнаете, как подготовить данные в правильном формате.
  • Узнаете, как обучить модель и получить выводы, используя MVAD.
  • Узнаете, какие входные параметры использовать и как интерпретировать полученные результаты вывода.

1. Создание в Azure ресурса "Детектор аномалий" с поддержкой MVAD

Примечание

На этапе предварительной версии решение MVAD доступно не во всех регионах. Сделайте закладку страницы What's new in Anomaly Detector (Новые возможности Детектора аномалий), чтобы следить за развертыванием MVAD в регионах. Вы также можете сообщить о проблеме на GitHub или связаться с нами по адресу AnomalyDetector@microsoft.com, чтобы получить сведения о конкретном регионе.

2. Подготовка данных

Затем необходимо подготовить данные для обучения (и данные вывода).

Схема входных данных

MVAD выявляет аномалии из группы метрик. Мы называем каждую метрику переменной или временным рядом.

  • Вы можете скачать пример файла данных от Майкрософт, чтобы проверить принятую схему: https://aka.ms/AnomalyDetector/MVADSampleData

  • Каждая переменная должна содержать два и только два поля: timestamp и value, и они должны храниться в файле с разделителями-запятыми (CSV).

  • Имена столбцов CSV-файла должны быть в точности timestamp и value с учетом регистра.

  • Значения timestamp должны соответствовать стандарту ISO 8601. Значение value может быть целым или десятичным числом с любым количеством десятичных разрядов. Хороший пример содержимого CSV-файла:

    TIMESTAMP value
    2019-04-01T00:00:00Z 5
    2019-04-01T00:01:00Z 3,6
    2019-04-01T00:02:00Z 4
    ... ...

    Примечание

    Если метки времени содержат часы, минуты и (или) секунды, перед вызовом API убедитесь, что они правильно округлены.

    Например, если предполагается, что частота данных будет одной точкой данных каждые 30 секунд, но при этом отображаются такие метки времени, как "12:00:01" и "12:00:28", это явно говорит о том, что следует предварительно обработать метки времени до новых значений, например "12:00:00" и "12:00:30".

    Дополнительные сведения см. в разделе Округление метки времени в документе с рекомендациями.

  • Имя CSV-файла будет использоваться в качестве имени переменной и должно быть уникальным. Примеры: temperature.csv и humidity.csv.

  • Переменные для обучения и переменные для вывода должны быть согласованными. Например, если вы используете series_1, series_2, series_3, series_4 и series_5 для обучения, необходимо предоставить точно такие же переменные для вывода.

  • CSV-файлы должны быть сжаты в ZIP-файл и переданы в контейнер BLOB-объектов Azure. ZIP-файл может иметь любое имя на ваше усмотрение.

Структура папок

Распространенной ошибкой при подготовке данных являются дополнительные папки в ZIP-файле. Например, предположим, что имя ZIP-файла — series.zip. Тогда после распаковки файлов в новую папку ./series правильный путь к CSV-файлам будет ./series/series_1.csv, а неправильный путь — ./series/foo/bar/series_1.csv.

Правильный пример дерева каталогов после распаковки ZIP-файла в Windows

.
└── series
    ├── series_1.csv
    ├── series_2.csv
    ├── series_3.csv
    ├── series_4.csv
    └── series_5.csv

Неправильный пример дерева каталогов после распаковки ZIP-файла в Windows

.
└── series
    └── series
        ├── series_1.csv
        ├── series_2.csv
        ├── series_3.csv
        ├── series_4.csv
        └── series_5.csv

Средства для архивирования и передачи данных

В этом разделе мы поделимся некоторыми средствами и примерами кода, которые можно копировать, редактировать и добавлять в логику своего собственного приложения, использующего входные данные MVAD.

Сжатие CSV-файлов в *nix

zip -j series.zip series/*.csv

Сжатие CSV-файлов в Windows

  • Перейдите в папку со всеми CSV-файлами.
  • Выберите все необходимые CSV-файлы.
  • Щелкните один из этих файлов правой кнопкой мыши и выберите команду Send to.
  • Выберите из раскрывающегося списка Compressed (zipped) folder.
  • При необходимости переименуйте ZIP-файл.

Архивирование кода Python и отправка данных в Хранилище BLOB-объектов Azure

Вы можете ознакомиться с этим документом, чтобы узнать, как передать файл в хранилище BLOB-объектов Azure.

Или же можно использовать приведенный ниже пример кода, который выполнит архивацию и передачу за вас. Вы можете скопировать и сохранить приведенный в этом разделе фрагмент кода Python как файл с расширением .py (например zipAndUpload.py) и запустить его с помощью командных строк, как показано ниже.

  • python zipAndUpload.py -s "foo\bar" -z test123.zip -c {azure blob connection string} -n container_xxx

    Эта команда сжимает все CSV-файлы в foo\bar в один ZIP-файл с именем test123.zip и передает файл test123.zip в контейнер с именем container_xxx в вашем хранилище BLOB-объектов.

  • python zipAndUpload.py -s "foo\bar" -z test123.zip -c {azure blob connection string} -n container_xxx -r

    Эта команда работает аналогично приведенной выше, но еще и удаляет ZIP-файл test123.zip после успешной передачи.

Аргументы:

  • --source-folder, -s — путь к исходной папке, содержащей CSV-файлы
  • --zipfile-name, -z — имя ZIP-файла
  • --connection-string, -c — строка подключения к хранилищу BLOB-объектов
  • --container-name, -n — имя контейнера
  • --remove-zipfile, -r — удаление ZIP-файла
import os
import argparse
import shutil
import sys

from azure.storage.blob import BlobClient
import zipfile


class ZipError(Exception):
    pass


class UploadError(Exception):
    pass


def zip_file(root, name):
    try:
        z = zipfile.ZipFile(name, "w", zipfile.ZIP_DEFLATED)
        for f in os.listdir(root):
            if f.endswith("csv"):
                z.write(os.path.join(root, f), f)
        z.close()
        print("Compress files success!")
    except Exception as ex:
        raise ZipError(repr(ex))


def upload_to_blob(file, conn_str, cont_name, blob_name):
    try:
        blob_client = BlobClient.from_connection_string(conn_str, container_name=cont_name, blob_name=blob_name)
        with open(file, "rb") as f:
            blob_client.upload_blob(f, overwrite=True)
        print("Upload Success!")
    except Exception as ex:
        raise UploadError(repr(ex))


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--source-folder", "-s", type=str, required=True, help="path to source folder")
    parser.add_argument("--zipfile-name", "-z", type=str, required=True, help="name of the zip file")
    parser.add_argument("--connection-string", "-c", type=str, help="connection string")
    parser.add_argument("--container-name", "-n", type=str, help="container name")
    parser.add_argument("--remove-zipfile", "-r", action="store_true", help="whether delete the zip file after uploading")
    args = parser.parse_args()

    try:
        zip_file(args.source_folder, args.zipfile_name)
        upload_to_blob(args.zipfile_name, args.connection_string, args.container_name, args.zipfile_name)
    except ZipError as ex:
        print(f"Failed to compress files. {repr(ex)}")
        sys.exit(-1)
    except UploadError as ex:
        print(f"Failed to upload files. {repr(ex)}")
        sys.exit(-1)
    except Exception as ex:
        print(f"Exception encountered. {repr(ex)}")

    try:
        if args.remove_zipfile:
            os.remove(args.zipfile_name)
    except Exception as ex:
        print(f"Failed to delete the zip file. {repr(ex)}")

3. Обучение модели MVAD

Вот пример текста запроса и кода Python для обучения модели MVAD.

// Sample Request Body
{
    "slidingWindow": 200,
    "alignPolicy": {
        "alignMode": "Outer",
        "fillNAMethod": "Linear", 
        "paddingValue": 0
    },
    // This could be your own ZIP file of training data stored on Azure Blob and a SAS url could be used here
    "source": "https://aka.ms/AnomalyDetector/MVADSampleData", 
    "startTime": "2021-01-01T00:00:00Z", 
    "endTime": "2021-01-02T12:00:00Z", 
    "displayName": "Contoso model"
}
# Sample Code in Python
########### Python 3.x #############
import http.client, urllib.request, urllib.parse, urllib.error, base64

headers = {
    # Request headers
    'Content-Type': 'application/json',
    'Ocp-Apim-Subscription-Key': '{API key}',
}

params = urllib.parse.urlencode({})

try:
    conn = http.client.HTTPSConnection('{endpoint}')
    conn.request("POST", "/anomalydetector/v1.1-preview/multivariate/models?%s" % params, "{request body}", headers)
    response = conn.getresponse()
    data = response.read()
    print(data)
    conn.close()
except Exception as e:
    print("[Errno {0}] {1}".format(e.errno, e.strerror))

####################################

Код отклика 201 показывает, что запрос был успешным.

Входные параметры

Необходимые параметры

Эти три параметра необходимы для обучения и вывода запросов API.

  • source — ссылка на ZIP-файл, расположенный в Хранилище BLOB-объектов Azure с подписанными URL-адресами (SAS).
  • startTime — время начала данных, используемых для обучения или вывода. Если оно находится раньше самой ранней метки времени в данных, то в качестве начальной точки будет использоваться эта самая ранняя метка.
  • endTime — время окончания данных, используемых для обучения или вывода, которое должно быть позже или равно startTime. Если значение endTime находится позже самой поздней метки времени в данных, то в качестве конечной точки будет использоваться эта самая поздняя метка. Если endTime и startTime равны, это означает вывод одной точки данных, которая часто используется в сценариях потоковой передачи.

Необязательные параметры для API обучения

Другие параметры для API обучения являются необязательными.

  • slidingWindow — количество точек данных, используемых для определения аномалий. Целое число между 28 и 2880. Значение по умолчанию — 300. Если параметр slidingWindow имеет значение k для обучения модели, то, чтобы получить допустимые результаты, из исходного файла во время вывода должно быть доступно по меньшей мере k точек.

    Многопараметрическое обнаружение аномалий (MVAD) принимает сегмент точек данных, а затем определяет, является ли следующая точка данных аномалией. Длина сегмента равна slidingWindow. При выборе значения slidingWindow необходимо учитывать два аспекта.

    1. Свойства данных: их частота выборки и то, являются ли они периодическими. Если данные являются периодическими, можно задать длину в 1–3 цикла в качестве slidingWindow. Если данные имеют высокую частоту (меньшую степень детализации), например на уровне минут или секунд, можно задать относительно более высокое значение slidingWindow.
    2. Компромисс между временем обучения и вывода и потенциальным влиянием на производительность. Большее значение slidingWindow может привести к более длительному времени обучения и вывода. Увеличенные значения slidingWindow не гарантируют рост точности. При небольшом значении slidingWindow может оказаться, что модели трудно прийти к оптимальному решению. Например,трудно обнаружить аномалии, если slidingWindow содержит всего две точки.
  • alignMode — выравнивание нескольких переменных (временного ряда) по меткам времени. Для этого параметра доступно два варианта: Inner и Outer, по умолчанию используется Outer.

    Этот параметр крайне важен при неправильном выравнивании последовательностей меток времени у переменных. Перед дальнейшей обработкой модель должна выровнять переменные по одной последовательности меток времени.

    Inner означает, что модель сообщит результаты обнаружения только для меток времени, у которых каждая переменная имеет значение, т. е. для пересечения всех переменных. Outer означает, что модель сообщит результаты обнаружения для меток времени, у которых любая переменная имеет значение, т. е. для объединения всех переменных.

    Ниже приведен пример, поясняющий различные значения alignModel.

    Переменная 1

    TIMESTAMP value
    01.11.2020 1
    02.11.2020 2
    04.11.2020 4
    05.11.2020 5

    Переменная 2

    TIMESTAMP value
    01.11.2020 1
    02.11.2020 2
    03.11.2020 3
    04.11.2020 4

    Объединение двух переменных типа Inner

    TIMESTAMP Переменная 1 Переменная 2
    01.11.2020 1 1
    02.11.2020 2 2
    04.11.2020 4 4

    Объединение двух переменных типа Outer

    TIMESTAMP Переменная 1 Переменная 2
    01.11.2020 1 1
    02.11.2020 2 2
    03.11.2020 nan 3
    04.11.2020 4 4
    05.11.2020 5 nan
  • fillNAMethod — заполнение nan в объединенной таблице. В объединенной таблице могут отсутствовать значения, и они должны обрабатываться должным образом. Мы предоставляем несколько методов для их заполнения. Это Linear, Previous, Subsequent, Zero и Fixed, по умолчанию используется значение Linear.

    Параметр Метод
    Linear Заполняет значения nan с помощью линейной интерполяции.
    Previous Распространяет последнее действительное значение для заполнения пропусков. Пример: [1, 2, nan, 3, nan, 4] -> [1, 2, 2, 3, 3, 4].
    Subsequent Использует следующее действительное значение для заполнения пропусков. Пример: [1, 2, nan, 3, nan, 4] -> [1, 2, 3, 3, 4, 4].
    Zero Вставляет нули вместо значений nan.
    Fixed Вставляет вместо значений nan заданное действительное значение, которое должно быть указано в paddingValue.
  • paddingValue — значение заполнения используется для заполнения nan, когда fillNAMethod имеет значение Fixed и должен быть указан в данном случае. В иных случаях он является необязательным.

  • displayName — это необязательный параметр, который используется для идентификации моделей. Например, с его помощью можно пометить параметры, источники данных и любые другие метаданные модели и ее входных данных. Значение по умолчанию — пустая строка.

4. Получение состояния модели

Так как API обучения является асинхронным, вы не получите состояние модели сразу после вызова API обучения. Однако вы можете запросить состояние модели либо с помощью ключа API, в котором значатся все модели, либо с помощью идентификатора модели, в котором указаны сведения о конкретной модели.

Сведения обо всех моделях

На этой странице приведена информация об URL-адресе и заголовках запроса. Обратите внимание, что возвращаются только 10 моделей, упорядоченных по времени обновления, но вы можете посмотреть и другие модели, задав параметры $skip и $top в URL-адресе запроса. Например, при таком URL-адресе запроса https://{endpoint}/anomalydetector/v1.1-preview/multivariate/models?$skip=10&$top=20 пропускаются 10 новейших моделей и возвращаются следующие 20.

Пример ответа:

{
    "models": [
         {
             "createdTime":"2020-12-01T09:43:45Z",
             "displayName":"DevOps-Test",
             "lastUpdatedTime":"2020-12-01T09:46:13Z",
             "modelId":"b4c1616c-33b9-11eb-824e-0242ac110002",
             "status":"READY",
             "variablesCount":18
         },
         {
             "createdTime":"2020-12-01T09:43:30Z",
             "displayName":"DevOps-Test",
             "lastUpdatedTime":"2020-12-01T09:45:10Z",
             "modelId":"ab9d3e30-33b9-11eb-a3f4-0242ac110002",
             "status":"READY",
             "variablesCount":18
         }
    ],
    "currentCount": 1,
    "maxCount": 50, 
    "nextLink": "<link to more models>"
}

Ответ содержит 4 поля: models, currentCount, maxCount и nextLink.

  • Поле models содержит время создания, время последнего обновления, идентификатор модели, отображаемое имя, число переменных и состояние каждой модели.
  • Поле currentCount указывает количество обученных многопараметрических моделей.
  • Поле maxCount — это максимальное число моделей, поддерживаемых этим ресурсом "Детектор аномалий".
  • Поле nextLink можно использовать, чтобы получить сведения о дополнительных моделях.

Сведения о модели по е идентификатору

На этой странице описан URL-адрес запроса для получения сведений о модели по ее идентификатору. Ответ выглядит следующим образом:

{
        "modelId": "45aad126-aafd-11ea-b8fb-d89ef3400c5f",
        "createdTime": "2020-06-30T00:00:00Z",
        "lastUpdatedTime": "2020-06-30T00:00:00Z",
        "modelInfo": {
          "slidingWindow": 300,
          "alignPolicy": {
            "alignMode": "Outer",
            "fillNAMethod": "Linear",
            "paddingValue": 0
          },
          "source": "<TRAINING_ZIP_FILE_LOCATED_IN_AZURE_BLOB_STORAGE_WITH_SAS>",
          "startTime": "2019-04-01T00:00:00Z",
          "endTime": "2019-04-02T00:00:00Z",
          "displayName": "Devops-MultiAD",
          "status": "READY",
          "errors": [],
          "diagnosticsInfo": {
            "modelState": {
              "epochIds": [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
              "trainLosses": [0.6291328072547913, 0.1671326905488968, 0.12354248017072678, 0.1025966405868533, 
                              0.0958492755889896, 0.09069952368736267,0.08686016499996185, 0.0860302299260931,
                              0.0828735455870684, 0.08235538005828857],
              "validationLosses": [1.9232804775238037, 1.0645641088485718, 0.6031560301780701, 0.5302737951278687, 
                                   0.4698025286197664, 0.4395163357257843, 0.4182931482799006, 0.4057914316654053, 
                                   0.4056498706340729, 0.3849248886108984],
              "latenciesInSeconds": [0.3398594856262207, 0.3659665584564209, 0.37360644340515137, 
                                     0.3513407707214355, 0.3370304107666056, 0.31876277923583984, 
                                     0.3283309936523475, 0.3503587245941162, 0.30800247192382812,
                                     0.3327946662902832]
            },
            "variableStates": [
              {
                "variable": "ad_input",
                "filledNARatio": 0,
                "effectiveCount": 1441,
                "startTime": "2019-04-01T00:00:00Z",
                "endTime": "2019-04-02T00:00:00Z",
                "errors": []
              },
              {
                "variable": "ad_ontimer_output",
                "filledNARatio": 0,
                "effectiveCount": 1441,
                "startTime": "2019-04-01T00:00:00Z",
                "endTime": "2019-04-02T00:00:00Z",
                "errors": []
              },
              // More variables
            ]
          }
        }
      }

Вы получите более подробные сведения о запрашиваемой модели. Ответ содержит метаданные о модели, параметры обучения и данные диагностики. Данные диагностики полезны при отладке и трассировке процесса обучения.

  • Свойство epochIds указывает, сколько эпох модель обучалась из общего количества в 100 эпох. Например, для модели в состоянии обучения свойство epochId может иметь значение [10, 20, 30, 40, 50]. Это означает, что модель прошла 50 эпох обучения и ей осталось еще столько же.
  • Функции trainLosses и validationLosses используются, чтобы определить, проходит ли оптимизация ожидаемым образом — в таком случае эти два значения потерь должны постепенно уменьшаться.
  • Свойство latenciesInSeconds указывает, сколько времени затрачено на каждую эпоху. Данные записываются каждые 10 эпох. В данном примере 10-я эпоха занимает примерно 0,34 секунды. Это помогает оценить время завершения обучения.
  • variableStates содержит краткую информацию о каждой переменной. Это список, упорядоченный по параметру filledNARatio в порядке убывания. Он показывает, сколько точек данных используется для каждой переменной, а параметр filledNARatio показывает, сколько точек отсутствует. Обычно значение filledNARatio должно быть как можно меньше. Слишком большое количество отсутствующих точек данных снижает точность модели.
  • Ошибки, возникающие при обработке данных, отображаются в поле errors.

5. Вывод с помощью MVAD

Чтобы получить вывод, укажите источник BLOB-объекта для ZIP-файла, содержащего данные вывода, время начала и время окончания.

Вывод также асинхронный, поэтому результаты возвращаются не сразу. Обратите внимание: необходимо сохранить в переменной ссылку на результат в заголовке ответа, который содержит свойство resultId, чтобы вы знали, где потом искать результаты.

Сбои обычно вызваны проблемами, связанными с самой моделью или данными. Если модель не готова или ссылка на данные недопустима, выполнить вывод невозможно. Убедитесь, что данные обучения и данные вывода согласуются между собой. Это означает, что они содержат одни и те же переменные, только с разными метками времени. Если количество переменных или их набор отличаются, на этапе проверки данных будут происходить ошибки. А поскольку проверка данных отложенная, вы получите сообщение об ошибке только при запросе результатов.

6. Получение результатов вывода

Для получения результатов нужно resultId. resultId содержится в заголовке ответа на запрос о выводе. На этой странице содержатся инструкции по выполнению запросов о результатах вывода.

Ответ выглядит следующим образом:

 {
        "resultId": "663884e6-b117-11ea-b3de-0242ac130004",
        "summary": {
          "status": "READY",
          "errors": [],
          "variableStates": [
            {
              "variable": "ad_input",
              "filledNARatio": 0,
              "effectiveCount": 26,
              "startTime": "2019-04-01T00:00:00Z",
              "endTime": "2019-04-01T00:25:00Z",
              "errors": []
            },
            {
              "variable": "ad_ontimer_output",
              "filledNARatio": 0,
              "effectiveCount": 26,
              "startTime": "2019-04-01T00:00:00Z",
              "endTime": "2019-04-01T00:25:00Z",
              "errors": []
            },
            // more variables
          ],
          "setupInfo": {
            "source": "https://aka.ms/AnomalyDetector/MVADSampleData",
            "startTime": "2019-04-01T00:15:00Z",
            "endTime": "2019-04-01T00:40:00Z"
          }
        },
        "results": [
          {
            "timestamp": "2019-04-01T00:15:00Z",
            "errors": [
              {
                "code": "InsufficientHistoricalData",
                "message": "historical data is not enough."
              }
            ]
          },
          // more results
          {
            "timestamp": "2019-04-01T00:20:00Z",
            "value": {
              "contributors": [],
              "isAnomaly": false,
              "severity": 0,
              "score": 0.17805261260751692
            }
          },
          // more results
          {
            "timestamp": "2019-04-01T00:27:00Z",
            "value": {
              "contributors": [
                {
                  "contributionScore": 0.0007775013367514271,
                  "variable": "ad_ontimer_output"
                },
                {
                  "contributionScore": 0.0007989604079048129,
                  "variable": "ad_series_init"
                },
                {
                  "contributionScore": 0.0008900927229851369,
                  "variable": "ingestion"
                },
                {
                  "contributionScore": 0.008068144477478554,
                  "variable": "cpu"
                },
                {
                  "contributionScore": 0.008222036467507165,
                  "variable": "data_in_speed"
                },
                {
                  "contributionScore": 0.008674941549594993,
                  "variable": "ad_input"
                },
                {
                  "contributionScore": 0.02232242629793674,
                  "variable": "ad_output"
                },
                {
                  "contributionScore": 0.1583773213660846,
                  "variable": "flink_last_ckpt_duration"
                },
                {
                  "contributionScore": 0.9816531517495176,
                  "variable": "data_out_speed"
                }
              ],
              "isAnomaly": true,
              "severity": 0.42135109874230336,
              "score": 1.213510987423033
            }
          },
          // more results
        ]
      }

Ответ содержит сведения о состоянии результата, о переменных, а также параметры и результаты вывода.

  • Свойство variableStates предоставляет сведения о каждой переменной в запросе на вывод.
  • setupInfo — это текст запроса, отправленного для получения этого вывода.
  • results — это результаты обнаружения. Есть три распространенных типа результатов обнаружения.
    1. Код ошибки InsufficientHistoricalData. Обычно это происходит только с несколькими первыми метками времени, так как модель делает выводы по принципу "окна" и нуждается в исторических данных для принятия решения. Для нескольких первых меток времени данных журнала недостаточно, поэтому на их основании невозможно сделать вывод. В этом случае сообщение об ошибке можно проигнорировать.
    2. Результат "isAnomaly": false указывает, что в текущей метке времени нет аномалий.
      • severity обозначает относительную степень серьезности аномалии и в случае обычных данных значение этого параметра всегда равно 0.
      • score — это необработанные выходные данные модели, на основании которых модель принимает решение. Значение может быть ненулевым даже для обычных точек данных.
    3. "isAnomaly": true указывает на наличие аномалии в текущей метке времени.
      • severity обозначает относительную степень серьезности аномалии и в случае аномальных данных значение этого параметра всегда больше 0.
      • score — это необработанные выходные данные модели, на основании которых модель принимает решение. severity — это значение, производное от score. У каждой точки данных есть score.
      • contributors — это список, содержащий показатель вклада каждой переменной. Чем выше этот показатель, тем выше вероятность, что в этой переменной заключается первопричина. Этот список часто используют для интерпретации аномалий, а также для диагностики первопричин.

Примечание

Распространенная ошибка — считать аномалиями все точки данных со значением isAnomaly=true. Так можно получить слишком много ложноположительных результатов. Необходимо использовать как isAnomaly, так и severity (или score), чтобы отсеять незначительные аномалии, а также (при необходимости) использовать группирование для проверки длительности аномалий, чтобы исключить случайный шум. Сведения о различиях между severity и score см. в разделе Вопросы и ответы рекомендаций.

Дальнейшие действия