Compartir a través de


Tutorial: Detección de anomalías en las ventas de productos con ML.NET

Obtenga información sobre cómo crear una aplicación de detección de anomalías para los datos de ventas de productos. En este tutorial se crea una aplicación de consola de .NET mediante C# en Visual Studio.

En este tutorial, aprenderá a:

  • Carga de los datos
  • Creación de una transformación para la detección de anomalías de picos
  • Detectar anomalías en picos mediante la transformación
  • Creación de una transformación para la detección de anomalías de punto de cambio
  • Detección de anomalías de punto de cambio con la transformación

Puede encontrar el código fuente de este tutorial en el repositorio dotnet/samples .

Prerrequisitos

Nota:

El formato de datos de product-sales.csv se basa en el conjunto de datos "Shampoo Sales Over a Three Year Period" originalmente procedente de DataMarket y proporcionado por Time Series Data Library (TSDL), creado por Rob Hyndman. Conjunto de datos "Ventas de champú durante un período de tres años" con licencia bajo la licencia predeterminada de acceso abierto de DataMarket.

Creación de una aplicación de consola

  1. Cree una aplicación de consola de C# denominada "ProductSalesAnomalyDetection". Haga clic en el botón Siguiente .

  2. Elija .NET 8 como marco de trabajo que se va a usar. Haga clic en el botón Crear.

  3. Cree un directorio denominado Data en el proyecto para guardar los archivos del conjunto de datos.

  4. Instale el paquete NuGet de Microsoft.ML:

    Nota:

    En este ejemplo se usa la versión estable más reciente de los paquetes NuGet mencionados a menos que se indique lo contrario.

    En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes NuGet. Elija "nuget.org" como origen del paquete, seleccione la pestaña Examinar, busque Microsoft.ML y seleccione Instalar. Seleccione el botón Aceptar en el cuadro de diálogo Vista previa de cambios y, a continuación, seleccione el botón Acepto en el cuadro de diálogo Aceptación de licencia si está de acuerdo con los términos de licencia de los paquetes enumerados. Repita estos pasos para Microsoft.ML.TimeSeries.

  5. Agregue las siguientes using directivas en la parte superior del archivo Program.cs :

    using Microsoft.ML;
    using ProductSalesAnomalyDetection;
    

Descarga tus datos

  1. Descargue el conjunto de datos y guárdelo en la carpeta Datos que creó anteriormente:

    • Haga clic con el botón derecho en product-sales.csv y seleccione "Guardar vínculo (o Destino) Como..."

      Asegúrese de guardar el archivo *.csv en la carpeta Datos o después de guardarlo en otro lugar, mueva el archivo *.csv a la carpeta Datos .

  2. En el Explorador de soluciones, haga clic con el botón derecho en el archivo *.csv y seleccione Propiedades. En Avanzado, cambie el valor de Copiar al directorio de salida a Copiar si es más reciente.

La tabla siguiente es una vista previa de datos del archivo *.csv:

Mes ProductSales
1-Enero 271
2-Ene 150.9
..... .....
1-Febrero 199.3
..... .....

Creación de clases y definición de rutas de acceso

A continuación, defina las estructuras de datos de la clase de entrada y predicción.

Agregue una nueva clase al proyecto:

  1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Agregar > nuevo elemento.

  2. En el cuadro de diálogo Agregar nuevo elemento, seleccione Clase y cambie el campo Nombre a ProductSalesData.cs. A continuación, seleccione Agregar.

    El archivo ProductSalesData.cs se abre en el editor de código.

  3. Agregue la siguiente using directiva a la parte superior de ProductSalesData.cs:

    using Microsoft.ML.Data;
    
  4. Quite la definición de clase existente y agregue el código siguiente, que tiene dos clases ProductSalesData y ProductSalesPrediction, al archivo ProductSalesData.cs :

    public class ProductSalesData
    {
        [LoadColumn(0)]
        public string? Month;
    
        [LoadColumn(1)]
        public float numSales;
    }
    
    public class ProductSalesPrediction
    {
        //vector to hold alert,score,p-value values
        [VectorType(3)]
        public double[]? Prediction { get; set; }
    }
    

    ProductSalesData especifica una clase de datos de entrada. El atributo LoadColumn especifica qué columnas (por índice de columna) del conjunto de datos se deben cargar.

    ProductSalesPrediction especifica la clase de datos de predicción. Para la detección de anomalías, la predicción consta de una alerta para indicar si hay una anomalía, una puntuación sin procesar y un valor p. Cuanto más cerca se acerque el valor p a 0, más probable es que se haya producido una anomalía.

  5. Cree dos campos globales para contener la ruta de acceso del archivo del conjunto de datos descargado recientemente y la ruta de acceso del archivo del modelo guardada:

    • _dataPath tiene la ruta de acceso al conjunto de datos usado para entrenar el modelo.
    • _docsize contiene la cantidad de registros en el archivo del conjunto de datos. Usará _docSize para calcular pvalueHistoryLength.
  6. Agregue el código siguiente a la línea justo debajo de las using directivas para especificar esas rutas de acceso:

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "product-sales.csv");
    //assign the Number of records in dataset file to constant variable
    const int _docsize = 36;
    

Inicialización de variables

  1. Reemplace la Console.WriteLine("Hello World!") línea por el código siguiente para declarar e inicializar la mlContext variable:

    MLContext mlContext = new MLContext();
    

    La clase MLContext es un punto de partida para todas las operaciones de ML.NET e inicializar mlContext crea un nuevo entorno de ML.NET que se puede compartir entre los objetos de flujo de trabajo de creación de modelos. Es similar, conceptualmente, a DBContext en Entity Framework.

Carga de los datos

Los datos de ML.NET se representan como una interfaz IDataView. IDataView es una manera flexible y eficaz de describir datos tabulares (numéricos y texto). Los datos se pueden cargar desde un archivo de texto o desde otros orígenes (por ejemplo, archivos de registro o base de datos SQL) a un IDataView objeto .

  1. Agregue el código siguiente después de crear la mlContext variable:

    IDataView dataView = mlContext.Data.LoadFromTextFile<ProductSalesData>(path: _dataPath, hasHeader: true, separatorChar: ',');
    

    LoadFromTextFile() define el esquema de datos y lee en el archivo. Toma las variables de ruta de acceso de datos y devuelve un IDataView.

Detección de anomalías en una serie temporal

La detección de anomalías marca eventos o comportamientos inesperados o inusuales. Proporciona pistas sobre dónde buscar problemas y le ayuda a responder a la pregunta "¿Es esto raro?".

Ejemplo de la detección de anomalías

La detección de anomalías es el proceso de detección de valores atípicos en datos de series temporales; puntos en una serie temporal de entrada dada donde el comportamiento no es lo esperado o "extraño".

La detección de anomalías puede ser útil de muchas maneras. Por ejemplo:

Si tienes un coche, quizás quieras saber: ¿Este indicador de aceite indica un nivel normal o tengo una fuga? Si está supervisando el consumo de energía, ¿quiere saber: ¿Hay una interrupción?

Hay dos tipos de anomalías de serie temporal que se pueden detectar:

  • Los picos indican ráfagas temporales de comportamiento anómalo en el sistema.

  • Los puntos de cambio indican el principio de los cambios persistentes a lo largo del tiempo en el sistema.

En ML.NET, los algoritmos de detección de picos de IID o detección de puntos de cambio de IID son adecuados para conjuntos de datos independientes y distribuidos de forma idéntica. Asumen que los datos de entrada son una secuencia de puntos de datos que se muestrean independientemente de una distribución fija.

A diferencia de los modelos de los otros tutoriales, el detector de anomalías de series temporales transforma directamente los datos de entrada. El IEstimator.Fit() método no necesita datos de entrenamiento para generar la transformación. Sí necesita el esquema de datos, proporcionado por una vista de datos generada a partir de una lista vacía de ProductSalesData.

Analizará los mismos datos de ventas de productos para detectar picos y puntos de cambio. El proceso de creación y entrenamiento del modelo es el mismo para la detección de picos y la detección de puntos de cambio; la principal diferencia es el algoritmo de detección específico que se usa.

Detección de picos

El objetivo de la detección de picos es identificar ráfagas repentinas pero temporales que difieren significativamente de la mayoría de los valores de datos de serie temporal. Es importante detectar a tiempo estos elementos, eventos u observaciones poco frecuentes y sospechosos para minimizar su impacto. El siguiente enfoque se puede usar para detectar una variedad de anomalías, como interrupciones, ciberataques o contenido web viral. La imagen siguiente es un ejemplo de picos en un conjunto de datos de serie temporal:

Captura de pantalla que muestra dos detecciones de picos.

Agregue el método CreateEmptyDataView()

Agregue el método siguiente a Program.cs:

IDataView CreateEmptyDataView(MLContext mlContext) {
    // Create empty DataView. We just need the schema to call Fit() for the time series transforms
    IEnumerable<ProductSalesData> enumerableData = new List<ProductSalesData>();
    return mlContext.Data.LoadFromEnumerable(enumerableData);
}

CreateEmptyDataView() genera un objeto de vista de datos vacío con el esquema correcto que se va a usar como entrada para el IEstimator.Fit() método .

Creación del método DetectSpike()

El método DetectSpike() realiza las acciones siguientes:

  • Crea la transformación a partir del estimador.
  • Detecta picos en función de los datos históricos de ventas.
  • Muestra los resultados.
  1. Cree el DetectSpike() método en la parte inferior del archivo Program.cs mediante el código siguiente:

    DetectSpike(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Use IidSpikeEstimator para entrenar el modelo para la detección de picos. Agréguelo al DetectSpike() método con el código siguiente:

    var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, pvalueHistoryLength: docSize / 4);
    
  3. Cree la transformación de detección de picos agregando lo siguiente como la siguiente línea de código en el DetectSpike() método :

    Sugerencia

    Los confidence parámetros y pvalueHistoryLength afectan a cómo se detectan los picos. confidence determina la sensibilidad del modelo a los picos. Cuanto menor sea la confianza, más probable es que el algoritmo detecte picos "más pequeños". El pvalueHistoryLength parámetro define el número de puntos de datos en una ventana deslizante. El valor de este parámetro suele ser un porcentaje de todo el conjunto de datos. Cuanto menor sea pvalueHistoryLength, cuanto más rápido se olvide el modelo de picos grandes anteriores.

    ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Agregue la siguiente línea de código para transformar los productSales datos como la línea siguiente en el DetectSpike() método :

    IDataView transformedData = iidSpikeTransform.Transform(productSales);
    

    El código anterior usa el método Transform() para realizar predicciones para varias filas de entrada de un conjunto de datos.

  5. Convierta en transformedData una pantalla fuertemente tipada IEnumerable para facilitar el uso del método CreateEnumerable() con el código siguiente:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Cree una línea de encabezado para mostrar con el código siguiente Console.WriteLine() :

    Console.WriteLine("Alert\tScore\tP-Value");
    

    Mostrará la siguiente información en los resultados de detección de picos:

    • Alert indica una alerta de pico para un punto de datos determinado.
    • Score es el ProductSales valor de un punto de datos determinado en el conjunto de datos.
    • P-Value La "P" significa probabilidad. Cuanto más cerca esté el valor p a 0, más probable es que el punto de datos sea una anomalía.
  7. Utilice el siguiente código para iterar a través de predictionsIEnumerable y mostrar los resultados:

    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}";
    
            if (p.Prediction[0] == 1)
            {
                results += " <-- Spike detected";
            }
    
            Console.WriteLine(results);
        }
    }
    Console.WriteLine("");
    
  8. Agregue la llamada al DetectSpike() método debajo de la llamada al LoadFromTextFile() método :

    DetectSpike(mlContext, _docsize, dataView);
    

Resultados de detección de picos

Los resultados deben ser similares a los siguientes. Durante el procesamiento, se muestran los mensajes. Es posible que vea advertencias o mensajes de procesamiento. Algunos de los mensajes se han quitado de los siguientes resultados para mayor claridad.

Detect temporary changes in pattern
=============== Training the model ===============
=============== End of training process ===============
Alert   Score   P-Value
0       271.00  0.50
0       150.90  0.00
0       188.10  0.41
0       124.30  0.13
0       185.30  0.47
0       173.50  0.47
0       236.80  0.19
0       229.50  0.27
0       197.80  0.48
0       127.90  0.13
1       341.50  0.00 <-- Spike detected
0       190.90  0.48
0       199.30  0.48
0       154.50  0.24
0       215.10  0.42
0       278.30  0.19
0       196.40  0.43
0       292.00  0.17
0       231.00  0.45
0       308.60  0.18
0       294.90  0.19
1       426.60  0.00 <-- Spike detected
0       269.50  0.47
0       347.30  0.21
0       344.70  0.27
0       445.40  0.06
0       320.90  0.49
0       444.30  0.12
0       406.30  0.29
0       442.40  0.21
1       580.50  0.00 <-- Spike detected
0       412.60  0.45
1       687.00  0.01 <-- Spike detected
0       480.30  0.40
0       586.30  0.20
0       651.90  0.14

Detección de puntos de cambio

Change points son cambios persistentes en la distribución de valores de un flujo de eventos de series temporales, como los cambios de nivel y las tendencias. Estos cambios persistentes duran mucho más que spikes y podrían indicar eventos catastróficos. Change points normalmente no son visibles a simple vista, pero se pueden detectar en los datos mediante enfoques como en el método siguiente. La imagen siguiente es un ejemplo de detección de puntos de cambio:

Captura de pantalla que muestra una detección de puntos de cambio.

Crear el método DetectChangepoint()

El DetectChangepoint() método ejecuta las siguientes tareas:

  • Crea la transformación a partir del estimador.
  • Detecta puntos de cambio en función de los datos históricos de ventas.
  • Muestra los resultados.
  1. Cree el DetectChangepoint() método, justo después de la declaración del DetectSpike() método, con el código siguiente:

    void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Cree el iidChangePointEstimator en el método DetectChangepoint() usando el siguiente código:

    var iidChangePointEstimator = mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, changeHistoryLength: docSize / 4);
    
  3. Como hizo anteriormente, cree la transformación a partir del estimador agregando la siguiente línea de código en el DetectChangePoint() método :

    Sugerencia

    La detección de puntos de cambio se produce con un ligero retraso, ya que el modelo debe asegurarse de que la desviación actual es un cambio persistente y no solo algunos picos aleatorios antes de crear una alerta. La cantidad de este retraso es igual al changeHistoryLength parámetro . Al aumentar el valor de este parámetro, las alertas de detección de cambios sobre cambios más persistentes, pero el equilibrio sería un retraso más largo.

    var iidChangePointTransform = iidChangePointEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Use el Transform() método para transformar los datos agregando el código siguiente a DetectChangePoint():

    IDataView transformedData = iidChangePointTransform.Transform(productSales);
    
  5. Como hizo anteriormente, convierta el en transformedData un fuertemente tipado IEnumerable para facilitar la visualización mediante el CreateEnumerable()método con el código siguiente:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Cree un encabezado para mostrar con el código siguiente como línea siguiente en el DetectChangePoint() método :

    Console.WriteLine("Alert\tScore\tP-Value\tMartingale value");
    

    Mostrará la siguiente información en los resultados de detección de puntos de cambio:

    • Alert indica una alerta de punto de cambio para un punto de datos determinado.
    • Score es el ProductSales valor de un punto de datos determinado en el conjunto de datos.
    • P-Value La "P" significa probabilidad. Cuanto más cerca esté el valor P a 0, más probable es que el punto de datos sea una anomalía.
    • Martingale value se usa para identificar cómo es "raro" un punto de datos, en función de la secuencia de valores P.
  7. Itere a través del predictionsIEnumerable y muestren los resultados con el siguiente código:

    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}\t{p.Prediction[3]:F2}";
    
            if (p.Prediction[0] == 1)
            {
                results += " <-- alert is on, predicted changepoint";
            }
            Console.WriteLine(results);
        }
    }
    Console.WriteLine("");
    
  8. Agregue la siguiente llamada al DetectChangepoint()método después de la llamada al DetectSpike() método :

    DetectChangepoint(mlContext, _docsize, dataView);
    

Resultados de detección de puntos de cambio

Los resultados deben ser similares a los siguientes. Durante el procesamiento, se muestran los mensajes. Es posible que vea advertencias o mensajes de procesamiento. Algunos mensajes se han quitado de los siguientes resultados para mayor claridad.

Detect Persistent changes in pattern
=============== Training the model Using Change Point Detection Algorithm===============
=============== End of training process ===============
Alert   Score   P-Value Martingale value
0       271.00  0.50    0.00
0       150.90  0.00    2.33
0       188.10  0.41    2.80
0       124.30  0.13    9.16
0       185.30  0.47    9.77
0       173.50  0.47    10.41
0       236.80  0.19    24.46
0       229.50  0.27    42.38
1       197.80  0.48    44.23 <-- alert is on, predicted changepoint
0       127.90  0.13    145.25
0       341.50  0.00    0.01
0       190.90  0.48    0.01
0       199.30  0.48    0.00
0       154.50  0.24    0.00
0       215.10  0.42    0.00
0       278.30  0.19    0.00
0       196.40  0.43    0.00
0       292.00  0.17    0.01
0       231.00  0.45    0.00
0       308.60  0.18    0.00
0       294.90  0.19    0.00
0       426.60  0.00    0.00
0       269.50  0.47    0.00
0       347.30  0.21    0.00
0       344.70  0.27    0.00
0       445.40  0.06    0.02
0       320.90  0.49    0.01
0       444.30  0.12    0.02
0       406.30  0.29    0.01
0       442.40  0.21    0.01
0       580.50  0.00    0.01
0       412.60  0.45    0.01
0       687.00  0.01    0.12
0       480.30  0.40    0.08
0       586.30  0.20    0.03
0       651.90  0.14    0.09

¡Felicidades! Ahora ha creado exitosamente modelos de aprendizaje automático para detectar picos y anomalías en puntos de cambio en los datos de ventas.

Puede encontrar el código fuente de este tutorial en el repositorio dotnet/samples .

En este tutorial, ha aprendido a:

  • Carga de los datos
  • Entrenar el modelo para la detección de anomalías de espiga
  • Detectar anomalías de picos con el modelo entrenado
  • Entrenamiento del modelo para la detección de anomalías de punto de cambio
  • Detección de anomalías en los puntos de cambio usando el modelo entrenado

Pasos siguientes

Consulte el repositorio de GitHub de ejemplos de Machine Learning para explorar un ejemplo de detección de anomalías de datos estacionales.