Condividi tramite


Esercitazione: Rilevare le anomalie nelle vendite di prodotti con ML.NET

Informazioni su come creare un'applicazione di rilevamento anomalie per i dati di vendita dei prodotti. Questa esercitazione crea un'applicazione console .NET usando C# in Visual Studio.

In questa esercitazione si apprenderà come:

  • Carica i dati
  • Creare una trasformazione per il rilevamento delle anomalie di picco
  • Rilevare le anomalie nei picchi con il transform
  • Creare una trasformazione per il rilevamento delle anomalie nei punti di cambiamento
  • Rilevare le anomalie nei punti di cambiamento attraverso la trasformazione

Puoi trovare il codice sorgente per questa esercitazione nel repository dotnet/samples.

Prerequisiti

Nota

Il formato dei dati in product-sales.csv si basa sul set di dati "Shampoo Sales Over a Three Year Period" originariamente originato da DataMarket e fornito da Time Series Data Library (TSDL), creato da Rob Hyndman. Set di dati "Vendite di Shampoo in un Periodo di Tre Anni" concesso in licenza con Licenza Aperta Predefinita di DataMarket.

Creare un'applicazione console

  1. Crea un'applicazione console C# denominata "ProductSalesAnomalyDetection". Fare clic sul pulsante Avanti.

  2. Scegliere .NET 8 come framework da usare. Fare clic sul pulsante Crea.

  3. Creare una directory denominata Data nel progetto per salvare i file del set di dati.

  4. Installare il pacchetto NuGet Microsoft.ML:

    Nota

    In questo esempio viene usata la versione stabile più recente dei pacchetti NuGet menzionati, a meno che non diversamente specificato.

    In Esplora soluzioni, fare clic con il pulsante destro del mouse sul progetto e selezionare Gestisci pacchetti NuGet. Impostare "nuget.org" come origine del pacchetto, selezionare la scheda Sfoglia, cercare Microsoft.ML e selezionare Installa. Selezionare il pulsante OK nella finestra di dialogo Anteprima modifiche e quindi selezionare il pulsante Accetto nella finestra di dialogo accettazione della licenza se si accettano le condizioni di licenza per i pacchetti elencati. Ripeta questi passaggi per Microsoft.ML.TimeSeries.

  5. Aggiungete le direttive using seguenti all'inizio del file Program.cs:

    using Microsoft.ML;
    using ProductSalesAnomalyDetection;
    

Scarica i tuoi dati

  1. Scaricare il set di dati e salvarlo nella cartella dati creata in precedenza:

    • Fare clic con il pulsante destro del mouse su product-sales.csv e selezionare "Salva collegamento (o Destinazione) con nome..."

      Assicurarsi di salvare il file *.csv nella cartella data oppure dopo averlo salvato altrove, spostare il file *.csv nella cartella Data.

  2. In Esplora soluzioni fare clic con il pulsante destro del mouse sul file *.csv e selezionare Proprietà. In Avanzate, cambia l'opzione di Copia nella directory di output in Copia se più recente.

La tabella seguente è un'anteprima dei dati dal file *.csv:

Mese ProductSales
1 gennaio 271
2 gennaio 150.9
..... .....
1 febbraio 199.3
..... .....

Creare classi e definire percorsi

Definire quindi le strutture di dati della classe di input e stima.

Aggiungere una nuova classe al progetto:

  1. Nell'Esplora Soluzioni , fare clic con il pulsante destro del mouse sul progetto e quindi selezionare Aggiungi > Nuovo elemento.

  2. Nella finestra di dialogo Aggiungi nuovo elemento, selezionare Class e modificare il campo Nome in ProductSalesData.cs. Selezionare quindi Aggiungi.

    Il file ProductSalesData.cs viene aperto nell'editor di codice.

  3. Aggiungere la direttiva using seguente all'inizio di ProductSalesData.cs:

    using Microsoft.ML.Data;
    
  4. Rimuovere la definizione di classe esistente e aggiungere il codice seguente, che include due classi ProductSalesData e ProductSalesPrediction, al file 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 specifica una classe di dati di input. L'attributo LoadColumn specifica le colonne (in base all'indice di colonna) nel set di dati da caricare.

    ProductSalesPrediction specifica la classe di dati di stima. Per il rilevamento anomalie, la stima è costituita da un avviso per indicare se è presente un'anomalia, un punteggio non elaborato e un valore p. Più il valore p è più vicino a 0, maggiore è la probabilità che si sia verificata un'anomalia.

  5. Creare due campi globali per contenere il percorso del file del set di dati scaricato di recente e il percorso del file del modello salvato:

    • _dataPath ha il percorso del set di dati usato per addestrare il modello.
    • _docsize ha il numero di record nel file del set di dati. Userai _docSize per calcolare pvalueHistoryLength.
  6. Aggiungere il codice seguente alla riga immediatamente sotto le direttive using per specificare tali percorsi:

    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;
    

Inizializzare le variabili

  1. Sostituire la riga Console.WriteLine("Hello World!") con il codice seguente per dichiarare e inizializzare la variabile mlContext:

    MLContext mlContext = new MLContext();
    

    La classe MLContext è un punto di partenza per tutte le operazioni di ML.NET e l'inizializzazione di mlContext crea un nuovo ambiente ML.NET che può essere condiviso tra gli oggetti flusso di lavoro di creazione del modello. È simile, concettualmente, a DBContext in Entity Framework.

Carica i dati

I dati in ML.NET sono rappresentati come interfaccia IDataView . IDataView è un modo flessibile ed efficiente di descrivere i dati tabulari (numerici e di testo). I dati possono essere caricati da un file di testo o da altre origini ,ad esempio da un database SQL o da file di log, a un oggetto IDataView.

  1. Aggiungere il codice seguente dopo aver creato la variabile mlContext:

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

    Il LoadFromTextFile() definisce lo schema dei dati e legge il file. Accetta le variabili del percorso dei dati e restituisce un IDataView.

Rilevamento anomalie delle serie temporali

Il rilevamento anomalie contrassegna eventi o comportamenti imprevisti o insoliti. Fornisce indizi su dove cercare i problemi e ti aiuta a rispondere alla domanda "È strano?".

Esempio del rilevamento anomalie

Il rilevamento delle anomalie è il processo di individuazione degli outlier nei dati delle serie temporali; punti su una serie temporale di input specificata dove il comportamento non è quello atteso o risulta "strano".

Il rilevamento anomalie può essere utile in molti modi. Per esempio:

Se hai un'auto, potresti voler sapere: è normale la lettura del misuratore dell'olio o ho una perdita? Se si monitora il consumo energetico, si vuole sapere: Si verifica un'interruzione?

È possibile rilevare due tipi di anomalie delle serie temporali:

  • picchi indicano picchi temporanei di comportamento anomalo nel sistema.

  • Punti di modifica indicano l'inizio delle modifiche persistenti nel sistema nel corso del tempo.

In ML.NET, gli algoritmi IID Spike Detection o IID Change Point Detection sono adatti per set di dati indipendenti e distribuiti in modo identico. Presuppongono che i dati di input siano una sequenza di punti dati campionati in modo indipendente da una distribuzione fissa.

A differenza dei modelli nelle altre esercitazioni, le trasformazioni di rilevamento delle anomalie delle serie temporali operano direttamente sui dati di input. Il metodo IEstimator.Fit() non richiede dati di training per produrre la trasformazione. È tuttavia necessario lo schema dei dati, il quale è fornito da una visualizzazione dei dati generata da un elenco vuoto di ProductSalesData.

Verranno analizzati gli stessi dati sulle vendite dei prodotti per rilevare picchi e punti di modifica. Il processo di compilazione e training del modello è lo stesso per il rilevamento dei picchi e il rilevamento dei punti di modifica; la differenza principale è l'algoritmo di rilevamento specifico usato.

Rilevamento dei picchi

L'obiettivo del rilevamento dei picchi è identificare picchi improvvisi ma temporanei che differiscono significativamente dalla maggior parte dei valori dei dati delle serie temporali. È importante rilevare tempestivamente questi elementi rari, eventi o osservazioni sospetti per ridurli al minimo. L'approccio seguente può essere usato per rilevare diverse anomalie, ad esempio interruzioni, attacchi informatici o contenuti Web virali. L'immagine seguente è un esempio di picchi in un set di dati time series:

Screenshot che mostra due rilevamenti di picchi.

Aggiungere il metodo CreateEmptyDataView()

Aggiungere il metodo seguente 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);
}

Il CreateEmptyDataView() produce un oggetto visualizzazione dati vuoto con lo schema corretto da utilizzare come input per il metodo IEstimator.Fit().

Creare il metodo DetectSpike()

Metodo DetectSpike():

  • Crea la trasformazione dall' *estimator*.
  • Rileva i picchi in base ai dati cronologici sulle vendite.
  • Visualizza i risultati.
  1. Creare il metodo DetectSpike() nella parte inferiore del file Program.cs usando il codice seguente:

    DetectSpike(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Usare il IidSpikeEstimator per addestrare il modello per il rilevamento dei picchi. Aggiungerlo al metodo DetectSpike() con il codice seguente:

    var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, pvalueHistoryLength: docSize / 4);
    
  3. Creare la trasformazione per il rilevamento dei picchi aggiungendo il codice seguente come nuova riga di codice nel metodo DetectSpike():

    Suggerimento

    I parametri confidence e pvalueHistoryLength influiscono sulla modalità di rilevamento dei picchi. confidence determina la sensibilità del modello ai picchi. Minore è la fiducia, più è probabile che l'algoritmo rilevi picchi "più piccoli". Il parametro pvalueHistoryLength definisce il numero di punti dati in una finestra scorrevole. Il valore di questo parametro è in genere una percentuale dell'intero set di dati. Più è basso il pvalueHistoryLength, più velocemente il modello dimentica i picchi di grandi dimensioni precedenti.

    ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Aggiungere la riga di codice seguente per trasformare i dati productSales come riga successiva nel metodo DetectSpike():

    IDataView transformedData = iidSpikeTransform.Transform(productSales);
    

    Il codice precedente usa il metodo transform() per eseguire stime per più righe di input di un set di dati.

  5. Converti il transformedData in un IEnumerable fortemente tipizzato per facilitare la visualizzazione utilizzando il metodo CreateEnumerable() con il seguente codice:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Creare una riga di intestazione di visualizzazione usando il codice Console.WriteLine() seguente:

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

    Nei risultati del rilevamento dei picchi verranno visualizzate le informazioni seguenti:

    • Alert indica un avviso di picco per un determinato punto dati.
    • Score è il valore ProductSales per un determinato punto di dati nell'insieme di dati.
    • P-Value "P" indica la probabilità. Più il valore p è più vicino a 0, maggiore è la probabilità che il punto dati sia un'anomalia.
  7. Usate il codice seguente per scorrere il predictionsIEnumerable e mostrare i risultati:

    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. Aggiungi la chiamata al metodo DetectSpike() sotto la chiamata al metodo LoadFromTextFile().

    DetectSpike(mlContext, _docsize, dataView);
    

Risultati del rilevamento dei picchi

I risultati dovrebbero essere simili ai seguenti. Durante l'elaborazione, vengono visualizzati i messaggi. Puoi vedere avvisi o messaggi di elaborazione. Alcuni dei messaggi sono stati rimossi dai risultati seguenti per maggiore chiarezza.

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

Rilevamento dei punti di cambiamento

Change points sono modifiche persistenti in una distribuzione del flusso di eventi di serie temporali di valori, ad esempio cambiamenti di livello e tendenze. Queste modifiche persistenti durano molto più a lungo di spikes e potrebbero indicare eventi irreversibili. Change points non sono in genere visibili a occhio nudo, ma possono essere rilevati nei dati usando approcci come nel metodo seguente. L'immagine seguente è un esempio di rilevamento dei punti di modifica:

Screenshot che mostra un rilevamento dei punti di cambiamento.

Creare il metodo DetectChangepoint()

Il metodo DetectChangepoint() esegue le attività seguenti:

  • Crea la trasformata dall'estimatore.
  • Rileva i punti di modifica in base ai dati cronologici delle vendite.
  • Visualizza i risultati.
  1. Creare il metodo DetectChangepoint(), subito dopo la dichiarazione del metodo DetectSpike(), usando il codice seguente:

    void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Creare il iidChangePointEstimator nel metodo DetectChangepoint() con il codice seguente:

    var iidChangePointEstimator = mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, changeHistoryLength: docSize / 4);
    
  3. Come in precedenza, creare la trasformazione dallo strumento di stima aggiungendo la riga di codice seguente nel metodo DetectChangePoint():

    Suggerimento

    Il rilevamento dei punti di modifica si verifica con un lieve ritardo perché il modello deve assicurarsi che la deviazione corrente sia una modifica persistente e non solo alcuni picchi casuali prima di creare un avviso. La quantità di questo ritardo è uguale al parametro changeHistoryLength. Aumentando il valore di questo parametro, gli avvisi di rilevamento delle modifiche riguardano cambiamenti più persistenti, ma a scapito di un ritardo più lungo.

    var iidChangePointTransform = iidChangePointEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Usare il metodo Transform() per trasformare i dati aggiungendo il codice seguente a DetectChangePoint():

    IDataView transformedData = iidChangePointTransform.Transform(productSales);
    
  5. Come fatto in precedenza, converte il transformedData in un IEnumerable fortemente tipizzato per facilitare la visualizzazione usando il metodo CreateEnumerable()con il codice seguente.

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Creare un'intestazione di visualizzazione con il codice seguente come riga successiva nel metodo DetectChangePoint():

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

    Nei risultati del rilevamento dei punti di modifica verranno visualizzate le informazioni seguenti:

    • Alert indica un avviso di punto di cambiamento per un punto dati specifico.
    • Score è il valore ProductSales per un determinato punto dati nel dataset.
    • P-Value "P" indica la probabilità. Più il valore P è più vicino a 0, maggiore è la probabilità che il punto dati sia un'anomalia.
    • Martingale value viene usato per identificare quanto "strano" sia un punto dati, in base alla sequenza di valori di P.
  7. Scorrere il predictionsIEnumerable e visualizzare i risultati con il codice seguente:

    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. Aggiungere la chiamata seguente al metodo DetectChangepoint()dopo la chiamata al metodo DetectSpike():

    DetectChangepoint(mlContext, _docsize, dataView);
    

Risultati del rilevamento dei punti di modifica

I risultati dovrebbero essere simili ai seguenti. Durante l'elaborazione, vengono visualizzati i messaggi. Potresti vedere avvisi o messaggi di elaborazione. Alcuni messaggi sono stati rimossi dai risultati seguenti per maggiore chiarezza.

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

Felicitazioni! Hai ora costruito con successo modelli di apprendimento automatico per rilevare picchi e anomalie dei punti di cambiamento nei dati di vendita.

È possibile trovare il codice sorgente di questo tutorial nel repository dotnet/samples .

In questa esercitazione si è appreso come:

  • Carica i dati
  • Allenare il modello per il rilevamento delle anomalie di picco
  • Rilevare le anomalie dei picchi con il modello sottoposto a training
  • Eseguire il training del modello per il rilevamento delle anomalie nei punti di cambiamento
  • Rilevare le anomalie dei punti di cambiamento con la modalità addestrata

Passaggi successivi

Consulta il repository GitHub degli esempi di apprendimento automatico per esplorare un esempio di rilevamento delle anomalie nei dati stagionali.