predictive-maintenance

German Version

Beschreibung der Funtkionsweise der Anomalie-Erkennung

Diese Funktion führt eine Anomalieerkennung für Sensordaten basierend auf dem Sensortyp durch und speichert die Ergebnisse im results["anomaly"]-Dictionary.

Funktionsweise:

  1. Initialisierung der Anomaliespalte und Zähler:
    sensor_df['anomaly'] = 0
    anomaly_counts = {}
    
    • sensor_df['anomaly'] = 0 setzt eine neue Spalte anomaly in sensor_df auf 0.
    • anomaly_counts = {} erstellt ein leeres Dictionary für die Zählung der Anomalien pro Sensortyp.
  2. Iterative Anomalieerkennung pro Sensortyp:
    for sensor_type in sensor_df['sensorType'].unique():
        sensor_subset = sensor_df[sensor_df['sensorType'] == sensor_type]
        if not sensor_subset.empty:
            X_anomaly = sensor_subset[['value']]
            anomaly_detector = IsolationForest(n_estimators=100, contamination=0.05, random_state=42)
            anomaly_detector.fit(X_anomaly)
            predictions = anomaly_detector.predict(X_anomaly)
            sensor_df.loc[sensor_subset.index, 'anomaly'] = pd.Series(predictions, index=sensor_subset.index)
            anomaly_count = (sensor_df.loc[sensor_subset.index, 'anomaly'] == -1).sum()
            anomaly_counts[sensor_type] = anomaly_count
    
    • Schleife durch Sensortypen: Für jeden sensor_type im DataFrame wird ein Subset (sensor_subset) erstellt.
    • Anomalieerkennung mit Isolation Forest:
      • X_anomaly enthält die Spalte value für die Analyse.
      • IsolationForest wird mit contamination=0.05 initialisiert, was 5 % der Daten als Anomalien markiert.
      • Das Modell anomaly_detector wird auf X_anomaly trainiert.
      • predict liefert Anomalien (markiert als -1) und Normalwerte (1).
    • Speichern der Ergebnisse:
      • Anomalien in sensor_subset werden in sensor_df gespeichert.
      • anomaly_count zählt die -1-Markierungen für Anomalien, und anomaly_counts speichert sie für jeden sensor_type.
  3. Umwandlung der Anomalie-Flag:
    sensor_df['anomaly'] = sensor_df['anomaly'].apply(lambda x: 1 if x == -1 else 0)
    
    • Wandelt -1-Markierungen in 1 (Anomalie) und andere Werte in 0 um.
  4. Erstellen der Ergebnisse in results:
    for sensor_type, count in anomaly_counts.items():
        results["anomaly"].append({
            "sensor_type": sensor_type,
            "vehicle_id": self.vehicle_id,
            "anomaly_count": count,
            "anomaly_data": []
        })
        anomalies = sensor_df[(sensor_df['sensorType'] == sensor_type) & (sensor_df['anomaly'] == 1)]
        if not anomalies.empty:
            results["anomaly"][-1]["anomaly_data"].extend(anomalies[['timestamp', 'value', 'mileage', 'anomaly']].to_dict(orient='records'))
    
    • Erstellen der Einträge:
      • Für jeden Sensortyp wird in results["anomaly"] ein Dictionary erstellt mit "sensor_type", "vehicle_id", "anomaly_count", und "anomaly_data".
      • Anomaliedaten (timestamp, value, mileage, anomaly) werden als JSON-Objekte in anomaly_data gespeichert.
  5. Visualisierung:
    fig, ax = plt.subplots(figsize=(14, 6))
    ax.plot(sensor_df[sensor_df['sensorType'] == sensor_type]['timestamp'],
            sensor_df[sensor_df['sensorType'] == sensor_type]['value'], label='Sensorwert')
    ax.scatter(anomalies['timestamp'], anomalies['value'], color='red', label='Anomalie', marker='x')
    ax.set_xlabel('Zeit')
    ax.set_ylabel('Sensorwert')
    ax.set_title(f'Anomalieerkennung in den Sensordaten - Sensortyp: {sensor_type} - Fahrzeug-ID: {self.vehicle_id}')
    ax.legend()
    buf = io.BytesIO()
    plt.savefig(buf, format='png')
    buf.seek(0)
    results["anomaly"][-1]["plot"] = base64.b64encode(buf.getvalue()).decode('utf-8')
    plt.close(fig)
    
    • Diagrammerstellung: Für jede Anomalie wird ein Diagramm erstellt.
    • Plot speichern: Das Diagramm wird als Base64-kodierter String in results["anomaly"][-1]["plot"] gespeichert.

Zusammengefasst:

Die Funktion analysiert Sensordaten nach Sensortypen, erkennt Anomalien, speichert die Anzahl und die Details der Anomalien und erstellt Diagramme zur Visualisierung.

Um die Anomalieerkennungsfunktion weniger empfindlich zu machen, kannst du die Parameter des IsolationForest-Modells anpassen, insbesondere den Parameter contamination, der steuert, wie viele Datenpunkte als Anomalien klassifiziert werden. Hier sind verschiedene Möglichkeiten zur Anpassung:

  1. Kontaminationsgrad reduzieren (contamination):
    • Standardmäßig ist contamination=0.05, was bedeutet, dass 5 % der Daten als Anomalien markiert werden. Wenn du diesen Wert reduzierst, wird der Algorithmus weniger empfindlich gegenüber Anomalien.
    • Ein kleinerer Wert wie contamination=0.01 kann die Anzahl der als Anomalien markierten Datenpunkte erheblich verringern.
  2. Erhöhe die Anzahl der Bäume (n_estimators):
    • Eine höhere Anzahl an Bäumen im IsolationForest (z. B. n_estimators=200 oder mehr) kann die Stabilität der Anomalieerkennung verbessern und damit Empfindlichkeitsschwankungen ausgleichen.
  3. Wähle ein robustes Quantil anstatt den Mittelwert:
    • Verwende z. B. das 5. oder 95. Quantil, um robuste Grenzwerte für die Anomalieerkennung zu setzen.

Hier ist die angepasste Funktion:

import pandas as pd
from sklearn.ensemble import IsolationForest
import matplotlib.pyplot as plt
import base64
import io

def detect_anomalies(sensor_df, vehicle_id, debug=False, contamination=0.01, n_estimators=200):
    """
    Erkennt Anomalien in Sensordaten nach Sensortyp und gibt ein Dictionary mit Anomalien und Visualisierungen zurück.
    
    Parameter:
    - sensor_df (DataFrame): DataFrame mit Sensordaten, das die Spalten 'sensorType', 'value', 'timestamp', 'mileage' enthält.
    - vehicle_id (str): Die ID des Fahrzeugs, für das Anomalien erkannt werden sollen.
    - debug (bool): Wenn True, zeigt Debug-Plots für jede Anomalieerkennung an.
    - contamination (float): Prozentsatz der Daten, der als Anomalie markiert wird (Standardwert 0.01).
    - n_estimators (int): Anzahl der Bäume im Isolation Forest (Standardwert 200).
    
    Rückgabe:
    - results (dict): Ein Dictionary mit den Anomalieergebnissen, einschließlich Zählungen, Daten und Visualisierungen.
    """
    
    results = {"anomaly": []}

    # Initialisiere die Anomaliespalte
    sensor_df['anomaly'] = 0
    anomaly_counts = {}

    # Schleife durch jeden Sensortyp, um Anomalien zu erkennen
    for sensor_type in sensor_df['sensorType'].unique():
        sensor_subset = sensor_df[sensor_df['sensorType'] == sensor_type]
        if not sensor_subset.empty:
            X_anomaly = sensor_subset[['value']]
            anomaly_detector = IsolationForest(n_estimators=n_estimators, contamination=contamination, random_state=42)
            anomaly_detector.fit(X_anomaly)
            predictions = anomaly_detector.predict(X_anomaly)
            
            # Speichern der Anomalieergebnisse im sensor_df
            sensor_df.loc[sensor_subset.index, 'anomaly'] = pd.Series(predictions, index=sensor_subset.index)
            anomaly_count = (sensor_df.loc[sensor_subset.index, 'anomaly'] == -1).sum()
            anomaly_counts[sensor_type] = anomaly_count

    # Konvertiere -1 in 1 für Anomalien und 0 für normale Daten
    sensor_df['anomaly'] = sensor_df['anomaly'].apply(lambda x: 1 if x == -1 else 0)

    # Füge Anomalieergebnisse zu results hinzu
    for sensor_type, count in anomaly_counts.items():
        anomalies = sensor_df[(sensor_df['sensorType'] == sensor_type) & (sensor_df['anomaly'] == 1)]
        anomaly_entry = {
            "sensor_type": sensor_type,
            "vehicle_id": vehicle_id,
            "anomaly_count": count,
            "anomaly_data": anomalies[['timestamp', 'value', 'mileage', 'anomaly']].to_dict(orient='records')
        }

        # Erstelle ein Diagramm für die Anomalien und speichere es als Base64-kodierten String
        fig, ax = plt.subplots(figsize=(14, 6))
        ax.plot(sensor_df[sensor_df['sensorType'] == sensor_type]['timestamp'],
                sensor_df[sensor_df['sensorType'] == sensor_type]['value'], label='Sensorwert')
        ax.scatter(anomalies['timestamp'], anomalies['value'], color='red', label='Anomalie', marker='x')
        ax.set_xlabel('Zeit')
        ax.set_ylabel('Sensorwert')
        ax.set_title(f'Anomalieerkennung in den Sensordaten - Sensortyp: {sensor_type} - Fahrzeug-ID: {vehicle_id}')
        ax.legend()
        
        # Debug-Ausgabe der Plots
        if debug:
            plt.show()

        # Speichern des Plots im results-Dictionary
        buf = io.BytesIO()
        plt.savefig(buf, format='png')
        buf.seek(0)
        anomaly_entry["plot"] = base64.b64encode(buf.getvalue()).decode('utf-8')
        plt.close(fig)

        results["anomaly"].append(anomaly_entry)

    return results

Anpassungen und Verwendung:

Beispielaufruf:

results = detect_anomalies(sensor_df, vehicle_id="V001", contamination=0.01, n_estimators=200, debug=True)

Durch diese Anpassungen wird die Anomalieerkennung weniger empfindlich auf kleine Abweichungen reagieren und dadurch robuster.

Integration in das ML-Modell

Die Ergebnisse aus der Anomalieerkennung können wertvolle Informationen für die Vorhersage eines Defekts liefern. Hier sind einige Ansätze, wie die Anomalieergebnisse in die Defektvorhersage integriert werden können:

1. Zusätzliche Features für das ML-Modell

Codebeispiel zur Feature-Erstellung:

   # Beispiel: Berechne die Anzahl der Anomalien für jeden Sensor in den letzten 30 Tagen
   sensor_df["anomaly_count_last_30_days"] = sensor_df.groupby("sensorType")["anomaly"].rolling('30D').sum().reset_index(level=0, drop=True)

2. Einführung einer Zeitlichen Dimension

Code zur Erstellung von Zeitabständen:

   # Berechne die Zeitabstände zwischen den Anomalien für jeden Sensortyp
   sensor_df["anomaly_timedelta"] = sensor_df.groupby("sensorType")["timestamp"].diff()

3. Verwendung der Anomalien als Gewichtung in der Zielvariable

4. Feature Engineering mit Zeitfenstern

Codebeispiel für ein gleitendes Fenster:

   # Durchschnittliche Anzahl an Anomalien im gleitenden Fenster von 30 Tagen
   sensor_df["anomaly_rolling_avg_30"] = sensor_df["anomaly"].rolling(window=30).mean()

5. Kombinierte Modelle für Defektvorhersage und Anomalieerkennung

Beispiel-Integration in den Code

Hier ist eine angepasste Version, die anomaly_count und anomaly_rolling_avg_30 als zusätzliche Features in das Defektvorhersagemodell integriert:

# Anomalien berechnen
sensor_df["anomaly_count"] = sensor_df.groupby("sensorType")["anomaly"].transform("sum")
sensor_df["anomaly_rolling_avg_30"] = sensor_df.groupby("sensorType")["anomaly"].rolling(window=30, min_periods=1).mean().reset_index(level=0, drop=True)

# Wähle die Features, einschließlich der Anomalie-Features
numerical_features = ["value", "mileage", "age_in_years", "past_workshop_count", 
                      "avg_past_workshop_cost", "past_defect_count", "anomaly_count", "anomaly_rolling_avg_30"]
categorical_features = ["sensorType"]

# ColumnTransformer und Pipeline aktualisieren, um die neuen Features zu verwenden
column_transformer = ColumnTransformer(
    transformers=[
        ("num_imputer", SimpleImputer(strategy="mean"), numerical_features),
        ("encoder", OneHotEncoder(), categorical_features),
        ("scaler", StandardScaler(), numerical_features)
    ],
    remainder="passthrough"
)

# Model fitting und Vorhersage wie gehabt
pipeline = Pipeline([
    ("preprocessor", column_transformer),
    ("classifier", RandomForestClassifier(random_state=42, n_estimators=100, max_depth=10))
])

pipeline.fit(X_train, y_train)

Fazit

Durch die Kombination der Anomalieerkennungsergebnisse mit dem Defektvorhersagemodell kannst du die Sensitivität des Modells verbessern und die Defektvorhersage präziser gestalten. Die oben genannten Methoden erlauben es dem Modell, Anomalien und ihre Häufigkeit als zusätzliche Vorboten eines möglichen Defekts zu berücksichtigen.

Funktionsweise der Anomalieerkennung anhand von oberen und unteren Grenzwerten

Die Anomalieerkennung anhand von Grenzwerten ist eine einfache und effektive Methode, um ungewöhnliche oder abnormale Werte in Sensordaten zu identifizieren. Sie basiert auf der Festlegung von oberen und unteren Schwellenwerten, die definieren, was als “normaler” Bereich für die Daten eines Sensors betrachtet wird.


Schritt-für-Schritt-Funktionsweise

1. Definition der Grenzwerte

2. Überprüfung jedes Sensordatenpunkts

3. Markierung von Anomalien

4. Aggregation der Ergebnisse


Vorteile der Methode

  1. Einfachheit: Die Methode ist leicht zu verstehen und zu implementieren.
  2. Effizienz: Sie erfordert nur wenige Berechnungen, da sie Grenzwertvergleiche nutzt.
  3. Interpretierbarkeit: Die Ergebnisse (normal/anomal) sind direkt nachvollziehbar.

Nachteile der Methode

  1. Manuelle Grenzwertfestlegung:
    • Wenn die Grenzwerte manuell festgelegt werden, können sie ungenau oder schwer zu bestimmen sein, besonders bei komplexen Systemen.
  2. Statische Grenzen:
    • Statische Grenzen berücksichtigen keine dynamischen Veränderungen der Daten oder des Systems.
  3. Fehlende Sensitivität für subtile Muster:
    • Die Methode erkennt keine komplexen oder schleichenden Muster, die zu Anomalien führen könnten.

Einsatzbeispiele

  1. Temperaturüberwachung:
    • Ein Temperatursensor meldet Werte. Wenn die Temperatur unter -20°C oder über 120°C liegt, wird dies als Anomalie betrachtet.
  2. Druckmessung:
    • Ein Drucksensor misst Werte, die zwischen 0 und 300 bar liegen sollten. Werte außerhalb dieses Bereichs werden als fehlerhaft eingestuft.

Erweiterungen

Die Grenzwert-basierte Methode kann durch folgende Techniken ergänzt werden:

  1. Dynamische Grenzwerte: Verwende statistische Verfahren wie z. B. Mittelwert ± 2 Standardabweichungen, um adaptive Grenzwerte zu definieren.
  2. Kontextbezogene Anomalien: Berücksichtige andere Variablen (z. B. Temperatur in Kombination mit Luftfeuchtigkeit).
  3. Zeitraum-basierte Analyse: Identifiziere, ob Anomalien in bestimmten Zeiträumen oder unter besonderen Bedingungen gehäuft auftreten.

Zusammenfassung

Die Anomalieerkennung anhand von oberen und unteren Grenzwerten ist eine effektive Methode zur Identifikation von ungewöhnlichen Werten in Sensordaten. Sie ist besonders geeignet, wenn klare Schwellenwerte bekannt sind. Für dynamische und komplexere Szenarien kann die Methode erweitert oder durch maschinelles Lernen ergänzt werden.

Lizenz

Autor: Jörg Harzmann

Dieser Inhalt ist unter einer CC BY-NC Lizenz veröffentlicht. Jeglicher Quellcode ist urheberrechtlich geschützt!