Dela via


Självstudie: Identifiera avvikelser i produktförsäljning med ML.NET

Lär dig hur du skapar ett program för avvikelseidentifiering för produktförsäljningsdata. Den här handledningen skapar en .NET-konsolapplikation med hjälp av C# i Visual Studio.

I den här handledningen lär du dig:

  • Läs in data
  • Skapa en omvandling för spik-anomali-detektering
  • Identifiera spikavvikelser med en transformering
  • Skapa en transformation för avvikelsedetektering vid förändringspunkt
  • Identifiera förändringspunktsavvikelser med transform

Du hittar källkoden för den här handledningen på dotnet/samples-repositoryt.

Förutsättningar

Not

Dataformatet i product-sales.csv baseras på datamängden "Shampoo Sales Over a Three Year Period" som ursprungligen kommer från DataMarket och tillhandahålls av Time Series Data Library (TSDL), skapad av Rob Hyndman. Försäljning av schampo under en treårsperiod datasett licensierat under DataMarkets standardöppna licens.

Skapa ett konsolprogram

  1. Skapa ett C# -konsolprogram med namnet "ProductSalesAnomalyDetection". Klicka på knappen Nästa.

  2. Välj .NET 8 som ramverk att använda. Klicka på knappen Skapa.

  3. Skapa en katalog med namnet Data i projektet för att spara dina datamängdsfiler.

  4. Installera Microsoft.ML NuGet-paketet:

    Note

    Det här exemplet använder den senaste stabila versionen av De NuGet-paket som nämns om inget annat anges.

    Högerklicka på projektet i Solution Explorer och välj Hantera NuGet-paket. Välj "nuget.org" som paketkälla, välj fliken Bläddra, sök efter Microsoft.ML och välj Installera. Välj knappen OK i dialogrutan Förhandsgranska ändringar och välj sedan knappen Jag accepterar i dialogrutan Licensgodkännande om du godkänner licensvillkoren för de paket som anges. Upprepa de här stegen för Microsoft.ML.TimeSeries.

  5. Lägg till följande using-direktiv överst i din Program.cs-fil:

    using Microsoft.ML;
    using ProductSalesAnomalyDetection;
    

Ladda ned dina data

  1. Ladda ned datauppsättningen och spara den i mappen Data som du skapade tidigare:

    • Högerklicka på product-sales.csv och välj "Spara länk (eller Mål) som..."

      Se till att du antingen sparar filen *.csv till mappen Data, eller när du har sparat den någon annanstans flyttar du filen *.csv till mappen Data.

  2. Högerklicka på filen *.csv i Solution Explorer och välj Egenskaper. Under Avanceratändrar du värdet på Kopiera till utdatakatalog till Kopiera om nyare.

Följande tabell är en dataförhandsgranskning från din *.csv-fil:

Månad Produktsförsäljning
1 jan 271
2 jan 150.9
..... .....
1 februari 199.3
..... .....

Skapa klasser och definiera sökvägar

Definiera sedan dina indata- och förutsägelseklassdatastrukturer.

Lägg till en ny klass i projektet:

  1. Högerklicka på projektet i Solution Exploreroch välj sedan Lägg till > nytt objekt.

  2. I dialogrutan Lägg till nytt objektväljer du Klass och ändrar fältet Namn till ProductSalesData.cs. Välj sedan Lägg till.

    Filen ProductSalesData.cs öppnas i kodredigeraren.

  3. Lägg till följande using-direktiv överst i ProductSalesData.cs:

    using Microsoft.ML.Data;
    
  4. Ta bort den befintliga klassdefinitionen och lägg till följande kod, som har två klasser ProductSalesData och ProductSalesPredictioni filen 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 anger en indataklass. Attributet LoadColumn anger vilka kolumner (efter kolumnindex) i datamängden som ska läsas in.

    ProductSalesPrediction anger förutsägelsedataklassen. För avvikelseidentifiering består förutsägelsen av en avisering som anger om det finns en avvikelse, en råpoäng och p-värde. Ju närmare p-värdet är 0, desto mer sannolikt har en avvikelse inträffat.

  5. Skapa två globala fält för att lagra den nyligen nedladdade datamängdsfilens sökväg och den sparade modellfilens sökväg:

    • _dataPath har sökvägen till den datauppsättning som används för att träna modellen.
    • _docsize har antalet poster i datamängdsfilen. Du använder _docSize för att beräkna pvalueHistoryLength.
  6. Lägg till följande kod på raden precis under de using direktiven för att ange dessa sökvägar:

    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;
    

Initiera variabler

  1. Ersätt Console.WriteLine("Hello World!") raden med följande kod för att deklarera och initiera variabeln mlContext:

    MLContext mlContext = new MLContext();
    

    Klassen MLContext är en startpunkt för alla ML.NET åtgärder och initiering mlContext skapar en ny ML.NET miljö som kan delas mellan arbetsflödesobjekten för modellskapande. Det liknar konceptuellt DBContext i Entity Framework.

Läs in data

Data i ML.NET representeras som ett IDataView-gränssnitt. IDataView är ett flexibelt och effektivt sätt att beskriva tabelldata (numerisk och text). Data kan läsas in från en textfil eller från andra källor (till exempel SQL-databas eller loggfiler) till ett IDataView objekt.

  1. Lägg till följande kod när du har skapat variabeln mlContext:

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

    LoadFromTextFile() definierar dataschemat och läser i filen. Den tar in datasökvägsvariablerna och returnerar en IDataView.

Avvikelseidentifiering för tidsserier

Avvikelseidentifiering flaggar oväntade eller ovanliga händelser eller beteenden. Det ger ledtrådar där du kan leta efter problem och hjälper dig att svara på frågan "Är det här konstigt?".

Exempel på avvikelseidentifieringen

Avvikelseidentifiering är processen för att identifiera avvikande tidsseriedata. pekar på en viss tidsserie för indata där beteendet inte är vad som förväntades eller "konstigt".

Avvikelseidentifiering kan vara användbart på många olika sätt. Till exempel:

Om du har en bil kanske du vill veta: Är den här oljemätaren normal, eller har jag en läcka? Om du övervakar strömförbrukningen vill du veta: Finns det ett avbrott?

Det finns två typer av avvikelser i tidsserier som kan identifieras:

  • Spikes visar tillfälliga utbrott av avvikande beteende i systemet.

  • Ändringspunkter anger början på beständiga ändringar över tid i systemet.

I ML.NET passar IID Spike Detection- eller IID Change Point Detection-algoritmerna för oberoende och identiskt distribuerade datamängder. De förutsätter att dina indata är en sekvens av datapunkter som samplas oberoende av en stationär distribution.

Till skillnad från modellerna i de andra självstudierna fungerar transformeringar av tidsserieavvikelseidentifiering direkt på indata. Metoden IEstimator.Fit() behöver inte träningsdata för att generera transformeringen. Det behöver dock dataschemat, som tillhandahålls av en datavy som genereras från en tom lista över ProductSalesData.

Du analyserar samma produktförsäljningsdata för att identifiera toppar och ändringspunkter. Processen för att bygga och träna modeller är detsamma för spikdetektion och ändringspunktdetektion; den huvudsakliga skillnaden är den specifika detekteringsalgoritmen som används.

Spikdetektering

Målet med toppidentifiering är att identifiera plötsliga men tillfälliga toppar som skiljer sig avsevärt från majoriteten av tidsseriedatavärdena. Det är viktigt att identifiera dessa misstänkta sällsynta objekt, händelser eller observationer i tid för att deras påverkan ska kunna minimeras. Följande metod kan användas för att identifiera en mängd olika avvikelser, till exempel avbrott, cyberattacker eller viralt webbinnehåll. Följande bild är ett exempel på toppar i en tidsseriedatauppsättning:

Skärmbild som visar två spikdetektioner.

Lägg till metoden CreateEmptyDataView()

Lägg till följande metod i 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() skapar ett tomt datavyobjekt med rätt schema som ska användas som indata till metoden IEstimator.Fit().

Skapa metoden DetectSpike()

Metoden DetectSpike():

  • Skapar transformering från estimatoren.
  • Identifierar toppar baserat på historiska försäljningsdata.
  • Visar resultatet.
  1. Skapa metoden DetectSpike() längst ned i filen Program.cs med hjälp av följande kod:

    DetectSpike(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Använd IidSpikeEstimator för att träna modellen för spikdetektion. Lägg till den i metoden DetectSpike() med följande kod:

    var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, pvalueHistoryLength: docSize / 4);
    
  3. Skapa transformering av toppidentifiering genom att lägga till följande som nästa kodrad i metoden DetectSpike():

    Tips

    Parametrarna confidence och pvalueHistoryLength påverkar hur toppar identifieras. confidence avgör hur känslig din modell är för toppar. Ju lägre konfidens desto mer sannolikt är algoritmen att identifiera "mindre" toppar. Parametern pvalueHistoryLength definierar antalet datapunkter i ett skjutfönster. Värdet för den här parametern är vanligtvis en procentandel av hela datamängden. Ju lägre pvalueHistoryLength, desto snabbare glömmer modellen tidigare stora toppar.

    ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Lägg till följande kodrad för att transformera productSales data som nästa rad i metoden DetectSpike():

    IDataView transformedData = iidSpikeTransform.Transform(productSales);
    

    Den tidigare koden använder metoden Transform() för att göra förutsägelser för flera indatarader i en datauppsättning.

  5. Konvertera din transformedData till ett starkt skrivet IEnumerable för enklare visning med hjälp av metoden CreateEnumerable() med följande kod:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Skapa en rubrikrad för visning med hjälp av följande Console.WriteLine() kod:

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

    Du visar följande information i resultatet av spikdetekteringen:

    • Alert indikerar en toppavisering vid en viss datapunkt.
    • Score är det ProductSales värdet för en viss datapunkt i datauppsättningen.
    • P-Value "P" står för sannolikhet. Ju närmare p-värdet är 0, desto mer sannolikt är datapunkten en avvikelse.
  7. Använd följande kod för att iterera genom predictionsIEnumerable och visa resultatet:

    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. Lägg till anropet till metoden DetectSpike() under anropet till metoden LoadFromTextFile():

    DetectSpike(mlContext, _docsize, dataView);
    

Resultat av spikdetektering

Resultatet bör likna följande. Under bearbetningen visas meddelanden. Du kan se varningar eller bearbeta meddelanden. Vissa av meddelandena har tagits bort från följande resultat för tydlighetens skull.

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

Identifiering av ändringspunkt

Change points är beständiga ändringar i en tidsseriehändelseströmsdistribution av värden, till exempel nivåändringar och trender. Dessa beständiga ändringar varar mycket längre än spikes och kan tyda på katastrofala händelser. Change points är vanligtvis inte synliga för blotta ögat, men kan identifieras i dina data med hjälp av metoder som i följande metod. Följande bild är ett exempel på en identifiering av ändringspunkter:

Skärmbild som visar en identifiering av ändringspunkter.

Skapa metoden DetectChangepoint()

Metoden DetectChangepoint() kör följande uppgifter:

  • Skapar omvandlingen från estimeraren.
  • Identifierar ändringspunkter baserat på historiska försäljningsdata.
  • Visar resultatet.
  1. Skapa DetectChangepoint()-metoden strax efter DetectSpike()-metoddeklarationen med hjälp av följande kod:

    void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Skapa iidChangePointEstimator- i metoden DetectChangepoint() med följande kod:

    var iidChangePointEstimator = mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, changeHistoryLength: docSize / 4);
    
  3. Precis som du gjorde tidigare skapar du transformering från uppskattningen genom att lägga till följande kodrad i metoden DetectChangePoint():

    Tips

    Identifieringen av ändringspunkter sker med en liten fördröjning eftersom modellen måste se till att den aktuella avvikelsen är en beständig ändring och inte bara några slumpmässiga toppar innan en avisering skapas. Den här fördröjningen är lika med parametern changeHistoryLength. Genom att öka värdet för den här parametern ändras detekteringsaviseringar för mer kontinuerliga förändringar, men nackdelen skulle vara en längre fördröjning.

    var iidChangePointTransform = iidChangePointEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Använd metoden Transform() för att transformera data genom att lägga till följande kod i DetectChangePoint():

    IDataView transformedData = iidChangePointTransform.Transform(productSales);
    
  5. Precis som du gjorde tidigare konverterar du transformedData till ett starkt skrivet IEnumerable för enklare visning med hjälp av metoden CreateEnumerable()med följande kod:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Skapa ett visningshuvud med följande kod som nästa rad i metoden DetectChangePoint():

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

    Du visar följande information i resultatet för identifiering av ändringspunkter:

    • Alert anger en ändringspunktsavisering för en viss datapunkt.
    • Score är det ProductSales värdet för en viss datapunkt i datauppsättningen.
    • P-Value "P" står för sannolikhet. Ju närmare P-värdet är 0, desto mer sannolikt är datapunkten en avvikelse.
    • Martingale value används för att identifiera hur "konstig" en datapunkt är, baserat på sekvensen med P-värden.
  7. Iterera genom predictionsIEnumerable och visa resultatet med följande kod:

    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. Lägg till följande anrop till metoden DetectChangepoint()efter anropet till metoden DetectSpike():

    DetectChangepoint(mlContext, _docsize, dataView);
    

Resultat av identifiering av ändringspunkter

Resultatet bör likna följande. Under bearbetningen visas meddelanden. Du kan se varningar eller bearbeta meddelanden. Vissa meddelanden har tagits bort från följande resultat för tydlighetens skull.

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

Grattis! Nu har du skapat maskininlärningsmodeller för att identifiera toppar och avvikelser i ändringspunkter i försäljningsdata.

Du hittar källkoden för den här självstudien på dotnet/samples-lagringsplatsen.

I den här guiden lärde du dig att:

  • Läs in data
  • Träna modellen för spikavvikelsedetektering
  • Identifiera spikavvikelser med den tränade modellen
  • Träna modellen för avvikelseidentifiering för ändringspunkt
  • Identifiera avvikelser för ändringspunkter med tränat läge

Nästa steg

Kolla in GitHub-arkivet för Machine Learning-exempelsamlingen för att utforska ett exempel på säsongsmässig dataavvikelseidentifiering.