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
Visual Studio 2022 med arbetsbelastningen ".NET Desktop Development" installerad.
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
Skapa ett C# -konsolprogram med namnet "ProductSalesAnomalyDetection". Klicka på knappen Nästa.
Välj .NET 8 som ramverk att använda. Klicka på knappen Skapa.
Skapa en katalog med namnet Data i projektet för att spara dina datamängdsfiler.
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.
Lägg till följande
using
-direktiv överst i din Program.cs-fil:using Microsoft.ML; using ProductSalesAnomalyDetection;
Ladda ned dina data
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.
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:
Högerklicka på projektet i Solution Exploreroch välj sedan Lägg till > nytt objekt.
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.
Lägg till följande
using
-direktiv överst i ProductSalesData.cs:using Microsoft.ML.Data;
Ta bort den befintliga klassdefinitionen och lägg till följande kod, som har två klasser
ProductSalesData
ochProductSalesPrediction
i 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.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äknapvalueHistoryLength
.
-
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
Ersätt
Console.WriteLine("Hello World!")
raden med följande kod för att deklarera och initiera variabelnmlContext
: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 konceptuelltDBContext
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.
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?".
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:
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.
Skapa metoden
DetectSpike()
längst ned i filen Program.cs med hjälp av följande kod:DetectSpike(MLContext mlContext, int docSize, IDataView productSales) { }
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);
Skapa transformering av toppidentifiering genom att lägga till följande som nästa kodrad i metoden
DetectSpike()
:Tips
Parametrarna
confidence
ochpvalueHistoryLength
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. ParameternpvalueHistoryLength
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ägrepvalueHistoryLength
, desto snabbare glömmer modellen tidigare stora toppar.ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
Lägg till följande kodrad för att transformera
productSales
data som nästa rad i metodenDetectSpike()
: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.
Konvertera din
transformedData
till ett starkt skrivetIEnumerable
för enklare visning med hjälp av metoden CreateEnumerable() med följande kod:var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
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 detProductSales
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.
-
Använd följande kod för att iterera genom
predictions
IEnumerable
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("");
Lägg till anropet till metoden
DetectSpike()
under anropet till metodenLoadFromTextFile()
: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:
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.
Skapa
DetectChangepoint()
-metoden strax efterDetectSpike()
-metoddeklarationen med hjälp av följande kod:void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales) { }
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);
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));
Använd metoden
Transform()
för att transformera data genom att lägga till följande kod iDetectChangePoint()
:IDataView transformedData = iidChangePointTransform.Transform(productSales);
Precis som du gjorde tidigare konverterar du
transformedData
till ett starkt skrivetIEnumerable
för enklare visning med hjälp av metodenCreateEnumerable()
med följande kod:var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
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 detProductSales
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.
-
Iterera genom
predictions
IEnumerable
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("");
Lägg till följande anrop till metoden
DetectChangepoint()
efter anropet till metodenDetectSpike()
: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.