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 självstudien skapar ett .NET Core-konsolprogram med C# i Visual Studio.
I den här guiden får du lära dig att:
- Läsa in data
- Skapa en transformering för toppavvikelseidentifiering
- Identifiera toppavvikelser med transformen
- Skapa en transformering för avvikelseidentifiering för ändringspunkt
- Identifiera avvikelser i ändringspunkter med transformen
Du hittar källkoden för den här självstudien på lagringsplatsen dotnet/samples .
Krav
Visual Studio 2022 med arbetsbelastningen ".NET Desktop Development" installerad.
Anteckning
Dataformatet i product-sales.csv
baseras på datauppsättningen "Shampoo Sales Over a Three Year Period" som ursprungligen hämtades från DataMarket och tillhandahålls av Time Series Data Library (TSDL), skapad av Rob Hyndman.
"Shampoo Sales Over a Three Year Period" Dataset Licensed under DataMarket Default Open License.
Skapa ett konsolprogram
Skapa ett C# -konsolprogram med namnet "ProductSalesAnomalyDetection". Klicka på knappen Nästa.
Välj .NET 6 som ramverk att använda. Klicka på knappen Skapa.
Skapa en katalog med namnet Data i projektet för att spara datamängdsfilerna.
Installera Microsoft.ML NuGet-paketet:
Anteckning
I det här exemplet används den senaste stabila versionen av De NuGet-paket som nämns om inget annat anges.
I Solution Explorer högerklickar du på projektet och väljer Hantera NuGet-paket. Välj "nuget.org" som paketkälla, välj fliken Bläddra, sök efter Microsoft.ML och välj knappen Installera . Välj knappen OK i dialogrutan Förhandsgranska ändringar och välj sedan knappen Jag accepterar i dialogrutan Godkännande av licens 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
-instruktioner överst i filen Program.cs :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 i mappen Data eller när du har sparat den någon annanstans, flytta filen *.csv till mappen Data .
I Solution Explorer högerklickar du på filen *.csv och väljer Egenskaper. Under Avancerat ändrar du värdet för Kopiera till utdatakatalog till Kopiera om nyare.
Följande tabell är en dataförhandsgranskning från din *.csv-fil:
Månad | ProductSales |
---|---|
1 jan | 271 |
2 jan | 150.9 |
..... | ..... |
1-feb | 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:
I Solution Explorer högerklickar du på projektet och väljer sedan Lägg till > nytt objekt.
I dialogrutan Lägg till nytt objekt väljer du Klass och ändrar fältet Namn till ProductSalesData.cs. Välj sedan knappen Lägg till .
Filen ProductSalesData.cs öppnas i kodredigeraren.
Lägg till följande
using
-instruktion ö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 datauppsättningen 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 ett p-värde. Ju närmare p-värdet är 0, desto troligare är det att en avvikelse har inträffat.Skapa två globala fält för att lagra sökvägen till den nyligen nedladdade datauppsättningsfilen 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 datauppsättningsfilen. Du använder_docSize
för att beräknapvalueHistoryLength
.
Lägg till följande kod på raden precis under using-instruktionerna 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 raden
Console.WriteLine("Hello World!")
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 begreppsmässigtDBContext
i Entity Framework.
Läsa in data
Data i ML.NET representeras som ett IDataView-gränssnitt. IDataView
är ett flexibelt och effektivt sätt att beskriva tabelldata (numeriska data 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 var du ska leta efter problem och hjälper dig att svara på frågan "Är det här konstigt?".
Avvikelseidentifiering är processen att identifiera extremvärden för tidsseriedata. punkter i 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 denna oljemätare läser normalt, eller har jag en läcka? Om du övervakar energiförbrukning vill du veta: Finns det ett avbrott?
Det finns två typer av time series-avvikelser som kan identifieras:
Toppar indikerar tillfälliga ökningar av avvikande beteende i systemet.
Ändringspunkter anger början på beständiga ändringar över tid i systemet.
I ML.NET passar algoritmerna för IID-toppidentifiering eller IID-ändringspunktsidentifiering för oberoende och identiskt distribuerade datauppsättningar. De förutsätter att dina indata är en sekvens med datapunkter som samplas oberoende av en stationär fördelning.
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 skapa transformen. Det behöver dock dataschemat, som tillhandahålls av en datavy som genereras från en tom lista med ProductSalesData
.
Du analyserar samma produktförsäljningsdata för att identifiera toppar och ändringspunkter. Processen för att skapa och träna modell är densamma för identifiering av toppar och identifiering av ändringspunkter. den största skillnaden är den specifika identifieringsalgoritm som används.
Toppidentifiering
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 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 IEstimator.Fit()
metoden.
Skapa metoden DetectSpike()
Metoden DetectSpike()
:
- Skapar transformen från beräknaren.
- Identifierar toppar baserat på historiska försäljningsdata.
- Visar resultatet.
DetectSpike()
Skapa metoden 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 toppidentifiering. Lägg till den i
DetectSpike()
metoden med följande kod:var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, pvalueHistoryLength: docSize / 4);
Skapa transformeringen för toppidentifiering genom att lägga till följande som nästa kodrad i
DetectSpike()
metoden :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 det att algoritmen identifierar "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 iDetectSpike()
metoden: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 huvudrad 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 toppidentifieringen:
Alert
anger en toppavisering för en viss datapunkt.Score
är värdetProductSales
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 troligare ä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
DetectSpike()
till metoden under anropetLoadFromTextFile()
till metoden :DetectSpike(mlContext, _docsize, dataView);
Resultat av toppidentifiering
Resultatet bör se ut ungefär så här. Under bearbetningen visas meddelanden. Du kan se varningar eller bearbeta meddelanden. Några 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ömdistribution av värden, till exempel nivåändringar och trender. Dessa beständiga ändringar varar mycket längre än spikes
och kan tyda på oåterkalleliga 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 transformen från beräknaren.
- Identifierar ändringspunkter baserat på historiska försäljningsdata.
- Visar resultatet.
DetectChangepoint()
Skapa metoden, precis efter metoddeklarationenDetectSpike()
, med hjälp av följande kod:void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales) { }
Skapa iidChangePointEstimator i
DetectChangepoint()
metoden med följande kod:var iidChangePointEstimator = mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, changeHistoryLength: docSize / 4);
Som du gjorde tidigare skapar du transformen från beräkningsobjektet genom att lägga till följande kodrad i
DetectChangePoint()
metoden :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 aviserar ändringsidentifiering vid mer beständiga ändringar, men kompromissen skulle vara en längre fördröjning.var iidChangePointTransform = iidChangePointEstimator.Fit(CreateEmptyDataView(mlContext));
Transform()
Använd metoden för att transformera data genom att lägga till följande kod iDetectChangePoint()
:IDataView transformedData = iidChangePointTransform.Transform(productSales);
Precis som tidigare konverterar du
transformedData
till en starkt typadIEnumerable
för enklare visning med hjälp avCreateEnumerable()
metoden 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
DetectChangePoint()
metoden :Console.WriteLine("Alert\tScore\tP-Value\tMartingale value");
Du visar följande information i dina resultat för identifiering av ändringspunkter:
Alert
anger en ändringspunktsavisering för en viss datapunkt.Score
är värdetProductSales
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 troligare ä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
DetectChangepoint()
metoden efter anropetDetectSpike()
till metoden :DetectChangepoint(mlContext, _docsize, dataView);
Resultat av ändringspunktsidentifiering
Resultatet bör se ut ungefär så här. 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 försäljningspunkter.
Du hittar källkoden för den här självstudien på lagringsplatsen dotnet/samples .
I den här självstudiekursen lärde du dig att:
- Läsa in data
- Träna modellen för toppavvikelseidentifiering
- Identifiera toppavvikelser med den tränade modellen
- Träna modellen för avvikelseidentifiering för ändringspunkt
- Identifiera avvikelser i ändringspunkter med tränat läge
Nästa steg
Titta på GitHub-lagringsplatsen machine learning-exempel för att utforska ett exempel på avvikelseidentifiering av säsongsdata.
Feedback
https://aka.ms/ContentUserFeedback.
Kommer snart: Under hela 2024 kommer vi att fasa ut GitHub-problem som feedbackmekanism för innehåll och ersätta det med ett nytt feedbacksystem. Mer information finns i:Skicka och visa feedback för