Freigeben über


Tutorial: Erkennen von Anomalien bei Zeitreihen mit ML.NET

Hier erfahren Sie, wie Sie eine Anwendung zur Erkennung von Anomalien bei Zeitreihendaten erstellen. Dieses Tutorial erstellt mithilfe von C# in Visual Studio 2019 eine .NET Core-Konsolenanwendung.

In diesem Tutorial lernen Sie, wie die folgenden Aufgaben ausgeführt werden:

  • Laden der Daten
  • Erkennen eines Zeitraums für eine Zeitreihe
  • Erkennen von Anomalien bei einer periodischen Zeitreihe

Sie finden den Quellcode für dieses Tutorial im Repository dotnet/samples.

Voraussetzungen

Erstellen einer Konsolenanwendung

  1. Erstellen Sie eine C#-Konsolenanwendung mit dem Namen „PhoneCallsAnomalyDetection“. Klicken Sie auf die Schaltfläche Weiter.

  2. Wählen Sie .NET 6 als zu verwendendes Framework aus. Klicken Sie auf die Schaltfläche Erstellen .

  3. Erstellen Sie ein Verzeichnis mit dem Namen Data in Ihrem Projekt, um die Datasetdateien zu speichern.

  4. Installieren Sie das Microsoft.ML-NuGet-Paket, Version 1.5.2:

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie NuGet-Pakete verwalten aus.
    2. Wählen Sie als Paketquelle „nuget.org“ aus.
    3. Wählen Sie die Registerkarte Durchsuchen aus.
    4. Suchen Sie nach Microsoft.ML.
    5. Wählen Sie Microsoft.ML aus der Liste der Pakete aus, und wählen Sie Version 1.5.2 in der Dropdownliste Version aus.
    6. Wählen Sie die Schaltfläche Installieren aus.
    7. Wählen Sie die Schaltfläche OK im Dialogfeld Vorschau der Änderungen und dann die Schaltfläche Ich stimme zu im Dialogfeld Zustimmung zur Lizenz aus, wenn Sie den Lizenzbedingungen für die aufgelisteten Pakete zustimmen.

    Wiederholen Sie diese Schritte für Microsoft.ML.TimeSeries, Version 0.1.5.2.

  5. Fügen Sie am Anfang der Datei Program.cs die folgenden using-Anweisungen hinzu:

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

Herunterladen der Daten

  1. Laden Sie die das Dataset herunter, und speichern Sie es im Ordner Data, den Sie vorher erstellt haben:

    Klicken Sie mit der rechten Maustaste auf phone-calls.csv und anschließend auf „Link speichern unter“ oder „Ziel speichern unter“.

    Achten Sie darauf, die CSV-Datei entweder im Ordner Data zu speichern oder sie in den Ordner Data zu verschieben, nachdem Sie die CSV-Datei an anderer Stelle gespeichert haben.

  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die CSV-Datei, und wählen Sie Eigenschaften aus. Ändern Sie unter Erweitert den Wert von In Ausgabeverzeichnis kopieren in Kopieren, wenn neuer.

Die folgende Tabelle enthält eine Datenvorschau aus Ihrer CSV-Datei:

timestamp value
2018/9/3 36.69670857
2018/9/4 35.74160571
..... .....
2018/10/3 34.49893429
... ....

Diese Datei stellt eine Zeitreihe dar. Jede Zeile in der Datei entspricht einem Datenpunkt. Jeder Datenpunkt verfügt über die beiden Attribute timestamp und value, mit denen die Anzahl der Telefonanrufe für jeden Tag dargestellt werden. Die Anzahl der Telefonanrufe wird zur Desensitivität transformiert.

Erstellen von Klassen und Definieren von Pfaden

Als Nächstes definieren Sie Ihre Datenstruktur der Eingabe- und Vorhersageklasse.

Fügen Sie dem Projekt eine neue Klasse hinzu:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und klicken Sie auf Hinzufügen > Neues Element.

  2. Wählen Sie im Dialogfeld Neues Element hinzufügen die Option Klasse aus, und ändern Sie das Feld Name in PhoneCallsData.cs. Wählen Sie dann die Schaltfläche Hinzufügen aus.

    Die Datei PhoneCallsData.cs wird im Code-Editor geöffnet.

  3. Fügen Sie die folgende using-Anweisung am Anfang der Datei PhoneCallsData.cs hinzu:

    using Microsoft.ML.Data;
    
  4. Entfernen Sie die vorhandene Klassendefinition, und fügen Sie den folgenden Code mit den beiden Klassen PhoneCallsData und PhoneCallsPrediction der Datei PhoneCallsData.cs hinzu:

    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 ist eine Klasse für Eingabedaten. Das LoadColumn-Attribut legt fest, welche Spalten (durch Angabe des Spaltenindex) im Dataset geladen werden sollen. Es verfügt über die beiden Attribute timestamp und value, die den jeweiligen Attributen in der Datendatei entsprechen.

    PhoneCallsPrediction gibt die Vorhersagedatenklasse an. Bei der SR-CNN-Erkennung hängt die Vorhersage vom angegebenen Erkennungsmodus ab. In diesem Beispiel wählen wir den Modus AnomalyAndMargin aus. Die Ausgabe enthält sieben Spalten. In der Regel sind IsAnomaly, ExpectedValue, UpperBoundary und LowerBoundary ausreichend informativ. Anhand dieser Vektoren können Sie erkennen, ob es sich bei einem Punkt um eine Anomalie handelt. Zudem enthalten diese Vektoren Informationen zum erwarteten Wert des Punkts sowie zum unteren/oberen Grenzbereich des Punkts.

  5. Fügen Sie der Zeile direkt unter den using-Anweisungen den folgenden Code hinzu, um die Pfade zu Ihrer Datendatei anzugeben:

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

Initialisieren der Variablen

  1. Ersetzen Sie die Zeile Console.WriteLine("Hello World!") durch den folgenden Code, um die mlContext-Variable zu deklarieren und zu initialisieren:

    MLContext mlContext = new MLContext();
    

    Die MLContext-Klasse ist der Startpunkt für alle ML.NET-Vorgänge. Durch das Initialisieren von mlContext wird eine neue ML.NET-Umgebung erstellt, die für mehrere Objekte des Modellerstellungsworkflows verwendet werden kann. Die Klasse ähnelt dem Konzept von DBContext in Entity Framework.

Laden der Daten

Daten im ML.NET werden angezeigt als ein IDataView interface. Mit IDataView können Tabellendaten (Zahlen und Text) flexibel und effizient beschrieben werden. Daten können aus einer Textdatei oder aus anderen Ressourcen (z. B. aus einer SQL-Datenbank oder aus Protokolldateien) in ein IDataView-Objekt geladen werden.

  1. Fügen Sie unterhalb der Erstellung der mlContext-Variablen den folgenden Code hinzu:

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

    Die LoadFromTextFile()-Methode definiert das Datenschema und liest die Datei ein. Diese Methode akzeptiert Datenpfadvariablen und gibt ein IDataView-Objekt zurück.

Anomalieerkennung in Zeitreihen

Bei der Erkennung von Anomalien bei Zeitreihen handelt es sich um einen Prozess, bei dem Ausreißer in Zeitreihendaten ermittelt werden. Damit wird auf Eingabezeitreihen hingewiesen, bei denen nicht das erwartete oder ein ungewöhnliches Verhalten aufgetreten ist. Diese Anomalien sind in der Regel Hinweise auf einige relevante Ereignisse in der Problemdomäne: ein Cyberangriff auf Benutzerkonten, Stromausfälle, ein sprunghafter Anstieg von Anforderungen pro Sekunde auf einem Server, Arbeitsspeicherverlust usw.

Zum Auffinden von Anomalien in Zeitreihen sollten Sie zunächst den Zeitraum der Reihe bestimmen. Anschließend kann die Zeitreihe in Form von Y = T + S + R in verschiedene Komponenten zerlegt werden, wobei Y der ursprünglichen Reihe, T der Trendkomponente, S der saisonalen Komponente und R der Restkomponente der Reihe entspricht. Dieser Schritt wird als Zerlegung bezeichnet. Abschließend wird zum Auffinden der Anomalien für die Restkomponente eine Erkennung ausgeführt. In ML.NET ist der SR-CNN-Algorithmus ein intelligenter und neuartiger Algorithmus, mit dem Anomalien bei Zeitreihen mittels SR-Methode (Spectral Residual) und Convolutional Neural Network (CNN) erkannt werden. Weitere Informationen zu diesem Algorithmus finden Sie unter Time-Series Anomaly Detection Service at Microsoft (Dienst bei Microsoft zur Erkennung von Anomalien bei Zeitreihen).

In diesem Tutorial werden Sie sehen, dass diese Verfahren mit zwei Funktionen durchgeführt werden können.

Erkennen eines Zeitraums

Im ersten Schritt wird die Funktion DetectSeasonality aufgerufen, um den Zeitraum der Reihe zu bestimmen.

Erstellen der DetectPeriod-Methode

  1. Erstellen Sie mithilfe des folgenden Codes unten in der Datei Program.cs eine DetectPeriod-Methode:

    int DetectPeriod(MLContext mlContext, IDataView phoneCalls)
    {
    
    }
    
  2. Verwenden Sie die Funktion DetectSeasonality zum Erkennen des Zeitraums. Fügen Sie ihn mit dem folgenden Code zur DetectPeriod-Methode hinzu:

    int period = mlContext.AnomalyDetection.DetectSeasonality(phoneCalls, nameof(PhoneCallsData.value));
    
  3. Zeigen Sie den Wert für den Zeitraum an, indem Sie den unten aufgeführten Code als nächste Codezeile in der DetectPeriod-Methode hinzufügen:

    Console.WriteLine("Period of the series is: {0}.", period);
    
  4. Geben Sie den Wert für den Zeitraum zurück.

    // <SnippetSetupSrCnnParameters>
    
  5. Fügen Sie der DetectPeriod-Methode unter dem Aufruf der LoadFromTextFile()-Methode den folgenden Aufruf hinzu:

    int period = DetectPeriod(mlContext, dataView);
    

Ergebnisse der Zeitraumerkennung

Führen Sie die Anwendung aus. Die Ergebnisse sollten den unten dargestellten ähneln.

Period of the series is: 7.

Erkennen von Anomalien

In diesem Schritt werden Anomalien mithilfe der DetectEntireAnomalyBySrCnn-Methode erkannt.

Erstellen der DetectAnomaly-Methode

  1. Erstellen Sie mit dem folgenden Code die DetectAnomaly-Methode direkt unterhalb der DetectPeriod-Methode:

    void DetectAnomaly(MLContext mlContext, IDataView phoneCalls, int period)
    {
    
    }
    
  2. Richten Sie SrCnnEntireAnomalyDetectorOptions mit dem folgenden Code in der DetectAnomaly-Methode ein:

    var options = new SrCnnEntireAnomalyDetectorOptions()
    {
        Threshold = 0.3,
        Sensitivity = 64.0,
        DetectMode = SrCnnDetectMode.AnomalyAndMargin,
        Period = period,
    };
    
  3. Erkennen Sie Anomalien mithilfe des SR-CNN-Algorithmus, indem Sie in der DetectAnomaly-Methode die folgende Codezeile hinzufügen:

    var outputDataView = mlContext.AnomalyDetection.DetectEntireAnomalyBySrCnn(phoneCalls, nameof(PhoneCallsPrediction.Prediction), nameof(PhoneCallsData.value), options);
    
  4. Konvertieren Sie die Ansicht der Ausgabedaten zur einfacheren Anzeige mit der CreateEnumerable-Methode mit dem folgenden Code in ein stark typisiertes IEnumerable-Element:

    var predictions = mlContext.Data.CreateEnumerable<PhoneCallsPrediction>(
        outputDataView, reuseRowObject: false);
    
  5. Erstellen Sie mit dem folgenden Code als nächste Zeile in der DetectAnomaly-Methode einen Anzeigeheader:

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

    In den Ergebnissen der Änderungspunkterkennung werden folgende Informationen angezeigt:

    • Index entspricht dem Index des jeweiligen Datenpunkts.
    • Anomaly entspricht dem Indikator, der angibt, ob der jeweilige Punkt als Anomalie erkannt wird.
    • ExpectedValue entspricht dem Schätzwert des jeweiligen Punkts.
    • LowerBoundary ist der niedrigste Wert, den jeder Punkt annehmen kann, um nicht als Anomalie zu gelten.
    • UpperBoundary ist der höchste Wert, den jeder Punkt annehmen kann, um nicht als Anomalie zu gelten.
  6. Mit dem folgenden Code können Sie predictionsIEnumerable durchlaufen und die Ergebnisse anzeigen:

    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. Fügen Sie der DetectAnomaly-Methode unter dem DetectPeriod()-Methodenaufruf den folgenden Aufruf hinzu:

    DetectAnomaly(mlContext, dataView, period);
    

Ergebnisse der Anomalieerkennung

Führen Sie die Anwendung aus. Die Ergebnisse sollten den unten dargestellten ähneln. Während der Verarbeitung werden Meldungen angezeigt. Möglicherweise werden Warnungen oder Verarbeitungsmeldungen angezeigt. Einige der Nachrichten wurden der Übersichtlichkeit halber aus den folgenden Ergebnissen entfernt.

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
...

Herzlichen Glückwunsch! Sie haben Machine Learning-Modelle zur Erkennung von Zeiträumen und Anomalien in einer periodischen Zeitreihe erstellt.

Sie finden den Quellcode für dieses Tutorial im Repository dotnet/samples.

In diesem Tutorial haben Sie gelernt, wie die folgenden Aufgaben ausgeführt werden:

  • Laden der Daten
  • Erkennen eines Zeitraums bei Zeitreihendaten
  • Erkennen einer Anomalie bei Zeitreihendaten

Nächste Schritte

Durchsuchen Sie das GitHub-Repository für Machine Learning-Beispiele nach einem Beispiel für die Erkennung von Stromverbrauchsanomalien, damit Sie es untersuchen können.