Tutorial: Información sobre la detección de anomalías multivariante en una hora

Anomaly Detector con detección de anomalías multivariante (MVAD) es una herramienta avanzada de inteligencia artificial para detectar anomalías de un grupo de métricas de forma no supervisada.

En general, puede seguir estos pasos para usar MVAD:

  1. Cree un recurso de Anomaly Detector que admita MVAD en Azure.
  2. Prepare sus datos.
  3. Entrene un modelo MVAD.
  4. Consulte el estado del modelo.
  5. Detecte anomalías con el modelo MVAD entrenado.
  6. Recupere e interprete los resultados de la inferencia.

En este tutorial, hará lo siguiente:

  • Comprender cómo preparar los datos en un formato correcto.
  • Comprender cómo entrenar e inferencia con MVAD.
  • Comprender los parámetros de entrada y cómo interpretar la salida en los resultados de la inferencia.

1. Cree un recurso de Anomaly Detector que admita MVAD.

Nota

Durante la fase de versión preliminar, MVAD solo está disponible en regiones limitadas. Agregue Novedades de Anomaly Detector como marcador para mantenerse al día con los lanzamientos de regiones de MVAD. También puede presentar un problema GitHub o ponerse en contacto con nosotros en AnomalyDetector@microsoft.com para solicitar regiones específicas.

2. Preparación de datos

A continuación, debe preparar los datos de entrenamiento (y los datos de inferencia).

Esquema de datos de entrada

MVAD detecta anomalías en un grupo de métricas; cada métrica se denomina variable o serie temporal.

  • Puede descargar el archivo de datos de ejemplo de Microsoft para comprobar el esquema aceptado desde: https://aka.ms/AnomalyDetector/MVADSampleData

  • Cada variable debe tener dos, y solo dos, campos, timestamp y value, que deben almacenarse en un archivo de valores separados por comas (CSV).

  • Los nombres de columna del archivo CSV deben ser exactamente timestamp y value, y distinguir mayúsculas de minúsculas.

  • Los valores de timestamp deben cumplir la norma ISO 8601; los de value pueden ser números enteros o decimales con cualquier número de posiciones decimales. Un buen ejemplo del contenido de un archivo CSV:

    timestamp value
    2019-04-01T00:00:00Z 5
    2019-04-01T00:01:00Z 3.6
    2019-04-01T00:02:00Z 4
    ... ...

    Nota

    Si las marcas de tiempo tienen horas, minutos o segundos, asegúrese de que se redondeen correctamente antes de llamar a las API.

    Por ejemplo, si se da por hecho que la frecuencia de los datos es un punto de datos cada 30 segundos, pero observa marcas de tiempo como "12:00:01" y "12:00:28", es señal segura de que debe procesar previamente las marcas de tiempo a nuevos valores como "12:00:00" y "12:00:30".

    Para obtener más información, vea la sección "Redondeo de marcas de tiempo" del documento de procedimientos recomendados.

  • El nombre del archivo csv se va a usar como nombre de variable y debe ser único. Por ejemplo, "temperature.csv" y "humidity.csv".

  • Las variables para el entrenamiento y las variables para la inferencia deben ser coherentes. Por ejemplo, si usa series_1, series_2, series_3, series_4 y series_5 para el entrenamiento, debe proporcionar exactamente las mismas variables para la inferencia.

  • Los archivos CSV deben comprimirse en un archivo ZIP y cargarse en un contenedor de blobs de Azure. El archivo ZIP puede tener el nombre que desee.

Estructura de carpetas

Un error común en la preparación de datos son las carpetas adicionales del archivo ZIP. Por ejemplo, imagine que el nombre del archivo ZIP es series.zip. Después de descomprimir los archivos en una nueva carpeta ./series, la ruta de acceso correcta a los archivos CSV es ./series/series_1.csv, y una ruta de acceso incorrecta podría ser ./series/foo/bar/series_1.csv.

Ejemplo correcto del árbol de directorios después de descomprimir el archivo ZIP en Windows

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

Ejemplo incorrecto del árbol de directorios después de descomprimir el archivo ZIP en Windows

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

Herramientas para comprimir y cargar datos

En esta sección, se comparten algunas herramientas y código de ejemplo que puede copiar y editar para agregarlos a su propia lógica de aplicación que se ocupa de los datos de entrada de MVAD.

Compresión de archivos CSV en *nix

zip -j series.zip series/*.csv

Compresión de archivos CSV en Windows

  • Vaya a la carpeta con todos los archivos CSV.
  • Seleccione todos los archivos CSV que necesite.
  • Haga clic con el botón derecho en uno de los archivos CSV y seleccione Send to.
  • Seleccione Compressed (zipped) folder en el menú desplegable.
  • Cambie el nombre del archivo ZIP según sea necesario.

Compresión de código de Python y carga de datos en Azure Blob Storage

Puede consultar este documento para obtener información sobre cómo cargar un archivo en Azure Blob.

O bien, puede hacer referencia al código de ejemplo siguiente que puede realizar la compresión y la carga automáticamente. Puede copiar y guardar el código de Python en esta sección como un archivo .py (por ejemplo, zipAndUpload.py) y ejecutarlo mediante líneas de comandos como estas:

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

    Este comando comprimirá todos los archivos CSV de foo\bar en un único archivo ZIP denominado test123.zip. Cargará test123.zip en el contenedor container_xxx del blob.

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

    Este comando hará lo mismo que lo anterior, pero eliminará el archivo ZIP test123.zip después de cargarlo correctamente.

Argumentos:

  • --source-folder, -s, ruta de acceso a la carpeta de origen que contiene archivos CSV
  • --zipfile-name, -z, nombre del archivo ZIP
  • --connection-string, -c, cadena de conexión al blob
  • --container-name, -n, nombre del contenedor
  • --remove-zipfile, -r, si está activado, quite el archivo 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. Entreno de un modelo MVAD

Este es un cuerpo de solicitud de ejemplo y el código de ejemplo en Python para entrenar un modelo 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))

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

Un código de respuesta de 201 indica una solicitud correcta.

Parámetros de entrada

Parámetros obligatorios

Estos tres parámetros son necesarios en las solicitudes de API de entrenamiento e inferencia:

  • source: vínculo al archivo ZIP que se encuentra en la instancia de Azure Blob Storage con las firmas de acceso compartido (SAS).
  • startTime: hora de inicio de los datos usados para el entrenamiento o la inferencia. Si es anterior a la marca de tiempo más temprana real de los datos, se usará la marca de tiempo más temprana real como punto de partida.
  • endTime: hora final de los datos usados para el entrenamiento o la inferencia, que debe ser posterior o igual a startTime. Si endTime es posterior a la marca de tiempo más reciente real de los datos, se usará la marca de tiempo más reciente real como punto final. Si endTime es igual a startTime, significa la inferencia de un único punto de datos, que se suele usar en escenarios de streaming.

Parámetros opcionales para la API de entrenamiento

Otros parámetros de la API de entrenamiento son opcionales:

  • slidingWindow: cuántos puntos de datos se usan para determinar las anomalías. Número entero entre 28 y 2880. El valor predeterminado es 300. Si slidingWindow es k para el entrenamiento del modelo, deben ser accesibles al menos k puntos desde el archivo de origen durante la inferencia para obtener resultados válidos.

    MVAD toma un segmento de puntos de datos para decidir si el siguiente punto de datos es una anomalía. La longitud del segmento es slidingWindow. Tenga en cuenta dos cosas al elegir el valor de slidingWindow:

    1. Las propiedades de los datos: si son periódicos y la frecuencia de muestreo. Cuando los datos son periódicos, puede establecer una longitud de 1 a 3 ciclos como valor de slidingWindow. Cuando los datos tienen una frecuencia alta (granularidad pequeña), como en el nivel de minutos o segundos, podría establecer un valor relativamente superior para slidingWindow.
    2. El equilibrio entre el tiempo de entrenamiento o inferencia y el posible impacto en el rendimiento. Un valor mayor de slidingWindow puede provocar un tiempo de entrenamiento o inferencia más largo. No hay ninguna garantía de que valores mayores de slidingWindow vayan a dar lugar a mejoras de precisión. Un valor pequeño de slidingWindow puede hacer difícil que el modelo vaya a converger en una solución óptima. Por ejemplo, es difícil detectar anomalías cuando slidingWindow solo tiene dos puntos.
  • alignMode: cómo alinear varias variables (series temporales) en las marcas de tiempo. Hay dos opciones para este parámetro, Inner y Outer, y el valor predeterminado es Outer.

    Este parámetro es fundamental cuando hay una alineación incorrecta entre las secuencias de marcas de tiempo de las variables. El modelo debe alinear las variables en la misma secuencia de marcas de tiempo antes de continuar el procesamiento.

    Inner significa que el modelo solo mostrará los resultados de la detección en las marcas de tiempo en las que todas las variables tienen un valor, por ejemplo, la intersección de todas las variables. Outer significa que el modelo solo mostrará los resultados de la detección en las marcas de tiempo en las que alguna variable tiene un valor, por ejemplo, la unión de todas las variables.

    Este es un ejemplo para explicar los distintos valores de alignModel.

    Variable-1

    timestamp value
    2020-11-01 1
    2020-11-02 2
    2020-11-04 4
    05-11-2020 5

    Variable-2

    timestamp value
    2020-11-01 1
    2020-11-02 2
    2020-11-03 3
    2020-11-04 4

    Combinación Inner de dos variables

    timestamp Variable-1 Variable-2
    2020-11-01 1 1
    2020-11-02 2 2
    2020-11-04 4 4

    Combinación Outer de dos variables

    timestamp Variable-1 Variable-2
    2020-11-01 1 1
    2020-11-02 2 2
    2020-11-03 nan 3
    2020-11-04 4 4
    05-11-2020 5 nan
  • fillNAMethod: cómo rellenar nan en la tabla combinada. Es posible que falten valores en la tabla combinada y se deben controlar adecuadamente. Proporcionamos varios métodos para rellenarlos. Las opciones son Linear, Previous, Subsequent, Zero y Fixed, y el valor predeterminado es Linear.

    Opción Método
    Linear Rellenar los valores nan por interpolación lineal
    Previous Propagar el último valor válido para rellenar los espacios. Ejemplo: [1, 2, nan, 3, nan, 4] -> [1, 2, 2, 3, 3, 4]
    Subsequent Usar el siguiente valor válido para rellenar los espacios. Ejemplo: [1, 2, nan, 3, nan, 4] -> [1, 2, 3, 3, 4, 4]
    Zero Rellenar los valores nan con 0.
    Fixed Rellenar los valores nan con un valor válido especificado que se debe proporcionar en paddingValue.
  • paddingValue: el valor de relleno se usa para rellenar los valores nan cuando fillNAMethod es Fixed y se debe proporcionar en ese caso. En otros casos, es opcional.

  • displayName: parámetro opcional que se usa para identificar los modelos. Por ejemplo, puede usarlo para marcar parámetros, orígenes de datos y cualquier otro metadato sobre el modelo y sus datos de entrada. El valor predeterminado es una cadena vacía.

4. Obtención del estado del modelo

Como la API de entrenamiento es asincrónica, no se obtiene el modelo inmediatamente después de llamar a la API de entrenamiento. Sin embargo, puede consultar el estado de los modelos por clave de API, que enumerará todos los modelos, o por identificador de modelo, que mostrará información sobre el modelo específico.

Enumeración de todos los modelos

Puede consultar esta página para obtener información sobre la dirección URL de solicitud y los encabezados de solicitud. Tenga en cuenta que solo se devuelven 10 modelos ordenados por tiempo de actualización, pero puede visitar otros modelos estableciendo los parámetros $skip y $top en la dirección URL de la solicitud. Por ejemplo, si la dirección URL de la solicitud es https://{endpoint}/anomalydetector/v1.1-preview/multivariate/models?$skip=10&$top=20, omitiremos los 10 modelos más recientes y devolveremos los 20 modelos siguientes.

Una respuesta de ejemplo es:

{
    "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>"
}

La respuesta contiene 4 campos: models, currentCount, maxCount y nextLink.

  • models contiene la hora de creación, la hora de la última actualización, el identificador del modelo, el nombre para mostrar, los recuentos de variables y el estado de cada modelo.
  • currentCount contiene el número de modelos multivariante entrenados.
  • maxCount es el número máximo de modelos admitidos por este recurso de Anomaly Detector.
  • nextLink podría usarse para capturar más modelos.

Obtención de modelos por id. de modelo

En esta página se describe la dirección URL de solicitud para consultar la información del modelo por identificador de modelo. Un cuerpo de respuesta de muestra tiene el siguiente aspecto:

{
        "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
            ]
          }
        }
      }

Recibirá información más detallada sobre el modelo consultado. La respuesta contiene metadatos sobre el modelo, sus parámetros de entrenamiento e información de diagnóstico. La información de diagnóstico es útil para depurar y realizar un seguimiento del progreso del entrenamiento.

  • epochIds indica cuántas épocas se ha entrenado el modelo en un total de 100 épocas. Por ejemplo, si el modelo sigue en estado de entrenamiento, epochId podría ser [10, 20, 30, 40, 50], lo que significa que ha completado su 50.ª época de entrenamiento y está a mitad de camino.
  • trainLosses y validationLosses se usan para comprobar si el progreso de optimización converge en cuyo caso las dos pérdidas deben disminuir gradualmente.
  • latenciesInSeconds contiene el costo de tiempo de cada época y se registra cada 10 épocas. En este ejemplo, la 10.ª época tarda aproximadamente 0,34 segundos. Esto sería útil para calcular el tiempo de finalización del entrenamiento.
  • variableStates resume información sobre cada variable. Es una lista clasificada por filledNARatio en orden descendente. Indica cuántos puntos de datos se usan para cada variable y filledNARatio indica cuántos puntos faltan. Normalmente es necesario reducir filledNARatio tanto como sea posible. Si faltan demasiados puntos de datos, se degradará la precisión del modelo.
  • Los errores durante el procesamiento de datos se incluirán en el campo errors.

5. Inferencia con MVAD

Para realizar la inferencia, basta con proporcionar el origen del blob al archivo ZIP que contiene los datos de inferencia, la hora de inicio y la hora de finalización.

La inferencia también es asincrónica, por lo que los resultados no se devuelven inmediatamente. Tenga en cuenta que debe guardar en una variable el vínculo de los resultados en el encabezado de respuesta que contiene resultId, para que pueda saber dónde obtener los resultados más adelante.

Los errores suelen deberse a problemas de modelo o problemas de datos. No se puede realizar la inferencia si el modelo no está listo o el vínculo de datos no es válido. Asegúrese de que los datos de entrenamiento y los datos de inferencia sean coherentes, lo que significa que deben ser exactamente las mismas variables, pero con marcas de tiempo diferentes. Más variables, menos variables o inferencia con un conjunto diferente de variables no pasarán la fase de comprobación de datos y se producirán errores. La comprobación de datos se aplaza para que reciba un mensaje de error solo cuando consulte los resultados.

6. Obtención de resultados de inferencia

Necesita para resultId obtener resultados. resultId se obtiene del encabezado de respuesta cuando se envía la solicitud de inferencia. Esta página contiene instrucciones para consultar los resultados de la inferencia.

Un cuerpo de respuesta de muestra tiene el siguiente aspecto:

 {
        "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
        ]
      }

La respuesta contiene el estado del resultado, la información de variables, los parámetros de inferencia y los resultados de la inferencia.

  • variableStates muestra la información de cada variable en la solicitud de inferencia.
  • setupInfo es el cuerpo de la solicitud enviado para esta inferencia.
  • results contiene los resultados de la detección. Hay tres tipos típicos de resultados de detección.
    1. Código de error InsufficientHistoricalData. Esto suele ocurrir solo con las primeras marcas de tiempo porque el modelo inferencia los datos de una manera basada en ventanas y necesita datos históricos para tomar una decisión. Para las primeras marcas de tiempo, no hay suficientes datos históricos, por lo que no se puede realizar la inferencia en ellas. En este caso, se puede omitir el mensaje de error.
    2. "isAnomaly": false indica que la marca de tiempo actual no es una anomalía.
      • severity indica la gravedad relativa de la anomalía y para los datos normales siempre es 0.
      • score es la salida sin procesar del modelo en el que el modelo toma una decisión que podría ser distinto de cero incluso para los puntos de datos normales.
    3. "isAnomaly": true indica una anomalía en la marca de tiempo actual.
      • severity indica la gravedad relativa de la anomalía y para los datos normales siempre es mayor que 0.
      • score es la salida sin procesar del modelo en el que el modelo toma una decisión. severity es un valor derivado de score. Cada punto de datos tiene un score.
      • contributors es una lista que contiene la puntuación de contribución de cada variable. Las puntuaciones de contribución más altas indican una mayor posibilidad de la causa principal. Esta lista se usa a menudo para interpretar anomalías, así como para diagnosticar las causas principales.

Nota

Un problema común es tomar todos los puntos de datos con isAnomaly=true como anomalías. Esto puede acabar con demasiados falsos positivos. Debe usar isAnomaly y severity (o score) para averiguar las anomalías que no son graves y (opcionalmente) usar la agrupación para comprobar la duración de las anomalías para suprimir el ruido aleatorio. Consulte las preguntas más frecuentes del documento de procedimientos recomendados para ver la diferencia entre severity y score.

Pasos siguientes