Självstudie: Identifiera avvikelser i tidsserier med ML.NET

Lär dig hur du skapar ett program för avvikelseidentifiering för tidsseriedata. Den här handledningen skapar en .NET-konsolapplikation med C# i Visual Studio 2019.

I den här handledningen kommer du lära dig att:

  • Läs in data
  • Identifiera period för en tidsserie
  • Identifiera avvikelse för en periodisk tidsserie

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

Förutsättningar

Skapa ett konsolprogram

  1. Skapa ett C# -konsolprogram med namnet "PhoneCallsAnomalyDetection". Välj Nästa.

  2. Välj .NET 8 som målramverk. Välj Skapa.

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

  4. Installera Microsoft.ML NuGet-paketet version 1.5.2:

    1. Högerklicka på projektet i Solution Explorer och välj Hantera NuGet-paket.
    2. Välj "nuget.org" som paketkälla.
    3. Välj fliken Bläddra.
    4. Sök efter Microsoft.ML.
    5. Välj Microsoft.ML i listan med paket och välj version 1.5.2 i listrutan Version.
    6. Välj knappen Installera.
    7. 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 version 1.5.2.

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

    using Microsoft.ML;
    using Microsoft.ML.TimeSeries;
    using PhoneCallsAnomalyDetection;
    

Ladda ned dina data

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

    Högerklicka på phone-calls.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:

tidsstämpel värde
2018/9/3 36.69670857
2018/9/4 35.74160571
..... .....
2018/10/3 34.49893429
... ....

Den här filen representerar en tidsserie. Varje rad i filen är en datapunkt. Varje datapunkt har två attribut, nämligen timestamp och value, för att representera antalet telefonsamtal varje dag. Antalet telefonsamtal omvandlas till minskad känslighet.

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 PhoneCallsData.cs. Välj sedan Lägg till.

    Filen PhoneCallsData.cs öppnas i kodredigeraren.

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

    using Microsoft.ML.Data;
    
  4. Ta bort den befintliga klassdefinitionen och lägg till följande kod, som har två klasser PhoneCallsData och PhoneCallsPredictioni filen PhoneCallsData.cs:

    public class PhoneCallsData
    {
        [LoadColumn(0)]
        public string? timestamp;
    
        [LoadColumn(1)]
        public double value;
    }
    
    public class PhoneCallsPrediction
    {
        // Vector to hold anomaly detection results, including isAnomaly, anomalyScore,
        // magnitude, expectedValue, boundaryUnits, upperBoundary and lowerBoundary.
        [VectorType(7)]
        public double[]? Prediction { get; set; }
    }
    

    PhoneCallsData anger en klass för inmatningsdata. Attributet LoadColumn anger vilka kolumner (efter kolumnindex) i datamängden som ska läsas in. Den har två attribut timestamp och value som motsvarar samma attribut i datafilen.

    PhoneCallsPrediction anger förutsägelsedataklassen. För SR-CNN detektor beror förutsägelsen på identifieringsläge angett. I det här exemplet väljer du AnomalyAndMargin läge. Utdata innehåller sju kolumner. I de flesta fall är IsAnomaly, ExpectedValue, UpperBoundaryoch LowerBoundary tillräckligt informativa. De talar om för dig om en punkt är en avvikelse, det förväntade värdet för punkten och den nedre och övre gränsregionen för punkten.

  5. Lägg till följande kod på raden precis under de using direktiven för att ange sökvägen till datafilen:

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "phone-calls.csv");
    

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 under skapandet av variabeln mlContext:

    IDataView dataView = mlContext.Data.LoadFromTextFile<PhoneCallsData>(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 i tidsserier ä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". Dessa avvikelser tyder vanligtvis på vissa händelser av intresse i problemdomänen: en cyberattack på användarkonton, strömavbrott, avbrott i RPS på en server, minnesläcka osv.

För att hitta avvikelse i tidsserier bör du först bestämma perioden för serien. Sedan kan tidsserierna delas upp i flera komponenter som Y = T + S + R, där Y är den ursprungliga serien, T är trendkomponenten, S är säsongskomponenten och R är residualkomponenten i serien. Det här steget kallas nedbrytning. Slutligen utförs detektering av residualkomponenten för att hitta avvikelserna. I ML.NET är algoritmen SR-CNN en avancerad och ny algoritm som baseras på Spectral Residual (SR) och Convolutional Neural Network (CNN) för att identifiera avvikelse i tidsserier. Mer information om den här algoritmen finns i Time-Series Tjänsten för avvikelseidentifiering på Microsoft.

I den här självstudien ser du att dessa procedurer kan slutföras med hjälp av två funktioner.

Identifiera tidsperiod

I det första steget anropar du funktionen DetectSeasonality för att fastställa perioden för serien.

Skapa metoden DetectPeriod

  1. Skapa metoden DetectPeriod längst ned i filen Program.cs med hjälp av följande kod:

    int DetectPeriod(MLContext mlContext, IDataView phoneCalls)
    {
    
    }
    
  2. Använd funktionen DetectSeasonality för att upptäcka period. Lägg till den i metoden DetectPeriod med följande kod:

    int period = mlContext.AnomalyDetection.DetectSeasonality(phoneCalls, nameof(PhoneCallsData.value));
    
  3. Visa periodvärdet genom att lägga till följande som nästa kodrad i metoden DetectPeriod:

    Console.WriteLine($"Period of the series is: {period}.");
    
  4. Returnera periodvärdet.

    // <SnippetSetupSrCnnParameters>
    
  5. Lägg till följande anrop till metoden DetectPeriod under anropet till metoden LoadFromTextFile():

    int period = DetectPeriod(mlContext, dataView);
    

Tidsperioddetekteringsresultat

Kör programmet. Resultatet bör likna följande.

Period of the series is: 7.

Identifiera avvikelse

I det här steget använder du metoden DetectEntireAnomalyBySrCnn för att hitta avvikelser.

Skapa metoden DetectAnomaly

  1. Skapa DetectAnomaly-metoden, precis under metoden DetectPeriod, med hjälp av följande kod:

    void DetectAnomaly(MLContext mlContext, IDataView phoneCalls, int period)
    {
    
    }
    
  2. Konfigurera SrCnnEntireAnomalyDetectorOptions i metoden DetectAnomaly med följande kod:

    var options = new SrCnnEntireAnomalyDetectorOptions()
    {
        Threshold = 0.3,
        Sensitivity = 64.0,
        DetectMode = SrCnnDetectMode.AnomalyAndMargin,
        Period = period,
    };
    
  3. Identifiera avvikelse med SR-CNN algoritm genom att lägga till följande kodrad i metoden DetectAnomaly:

    var outputDataView = mlContext.AnomalyDetection.DetectEntireAnomalyBySrCnn(phoneCalls, nameof(PhoneCallsPrediction.Prediction), nameof(PhoneCallsData.value), options);
    
  4. Konvertera utdatavyn till ett starkt skrivet IEnumerable för enklare visning med hjälp av metoden CreateEnumerable med följande kod:

    var predictions = mlContext.Data.CreateEnumerable<PhoneCallsPrediction>(
        outputDataView, reuseRowObject: false);
    
  5. Skapa ett visningshuvud med följande kod som nästa rad i metoden DetectAnomaly:

    Console.WriteLine("Index,Data,Anomaly,AnomalyScore,Mag,ExpectedValue,BoundaryUnit,UpperBoundary,LowerBoundary");
    

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

    • Index är indexet för varje punkt.
    • Anomaly är indikatorn på om varje punkt identifieras som avvikelse.
    • ExpectedValue är det uppskattade värdet för varje punkt.
    • LowerBoundary är det lägsta värdet som varje punkt kan vara för att inte vara en avvikelse.
    • UpperBoundary är det högsta värdet som varje punkt kan vara för att inte vara en avvikelse.
  6. Iterera genom predictionsIEnumerable och visa resultatet med följande kod:

    var index = 0;
    
    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            string output;
            if (p.Prediction[0] == 1)
                output = "{0},{1},{2},{3},{4},  <-- alert is on! detected anomaly";
            else
                output = "{0},{1},{2},{3},{4}";
    
            Console.WriteLine(output, index, p.Prediction[0], p.Prediction[3], p.Prediction[5], p.Prediction[6]);
        }
        ++index;
    }
    
    Console.WriteLine("");
    
  7. Lägg till följande anrop till metoden DetectAnomaly under DetectPeriod()-metodanropet:

    DetectAnomaly(mlContext, dataView, period);
    

Resultat av avvikelseidentifiering

Kör programmet. 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 period of the series
Period of the series is: 7.
Detect anomaly points in the series
Index   Data    Anomaly AnomalyScore    Mag     ExpectedValue   BoundaryUnit    UpperBoundary   LowerBoundary
0,0,36.841787256739266,41.14206982401966,32.541504689458876
1,0,35.67303618137362,39.97331874865401,31.372753614093227
2,0,34.710132999891826,39.029491313022824,30.390774686760828
3,0,33.44765248883495,37.786086547816545,29.10921842985335
4,0,28.937110922276364,33.25646923540736,24.61775260914537
5,0,5.143895892785781,9.444178460066171,0.843613325505391
6,0,5.163325228419392,9.463607795699783,0.8630426611390014
7,0,36.76414836240396,41.06443092968435,32.46386579512357
8,0,35.77908590657007,40.07936847385046,31.478803339289676
9,0,34.547259536635245,38.847542103915636,30.246976969354854
10,0,33.55193524820608,37.871293561337076,29.23257693507508
11,0,29.091800129624648,33.392082696905035,24.79151756234426
12,0,5.154836630338823,9.455119197619213,0.8545540630584334
13,0,5.234332502492464,9.534615069772855,0.934049935212073
14,0,36.54992549471526,40.85020806199565,32.24964292743487
15,0,35.79526470980883,40.095547277089224,31.494982142528443
16,0,34.34099013096804,38.64127269824843,30.040707563687647
17,0,33.61201516582131,37.9122977331017,29.31173259854092
18,0,29.223563320561812,33.5238458878422,24.923280753281425
19,0,5.170512168851533,9.470794736131923,0.8702296015711433
20,0,5.2614938889462834,9.561776456226674,0.9612113216658926
21,0,36.37103858487317,40.67132115215356,32.07075601759278
22,0,35.813544599026855,40.113827166307246,31.513262031746464
23,0,34.05600492733225,38.356287494612644,29.755722360051863
24,0,33.65828319077884,37.95856575805923,29.358000623498448
25,0,29.381125690882463,33.681408258162854,25.080843123602072
26,0,5.261543539820418,9.561826107100808,0.9612609725400283
27,0,5.4873712582971805,9.787653825577571,1.1870886910167897
28,1,36.504694001629254,40.804976568909645,32.20441143434886  <-- alert is on, detected anomaly
...

Grattis! Nu har du skapat maskininlärningsmodeller för att identifiera period och avvikelse i en periodisk serie.

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

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

  • Läs in data
  • Identifiera period för tidsseriedata
  • Identifiera avvikelse för tidsseriedata

Nästa steg

Kolla in Machine Learning-exempel på GitHub-lagringsplatsen för att utforska ett exempel på avvikelseidentifiering i energiförbrukning.