Das Labeln von Zeitreihen-Sensordaten ist meist der schwierigste Teil des überwachten maschinellen Lernens im IoT – nicht weil die Werkzeuge kompliziert wären, sondern weil die Ground Truth über das Gedächtnis der Bediener, Papierprotokolle und Instandhaltungssysteme verstreut ist. Dieser Leitfaden zeigt, wie Sie Ereignisse und Bediener-Labels in dem Moment, in dem sie auftreten, per MQTT erfassen, wie Sie ein Label-Schema entwerfen, das den Praxiseinsatz übersteht, und wie Sie diese Ereignisse in gelabelte Zeitfenster umwandeln, die mit Ihrer Telemetrie verknüpft sind.
Warum Labels der Engpass sind
Sensordaten lassen sich günstig sammeln. Ein Gateway, das alle paar Sekunden veröffentlicht, erzeugt innerhalb weniger Wochen Millionen von Datenpunkten. Ein Modell, das einen verstopften Filter, einen Werkzeugbruch oder einen Qualitätsmangel erkennen soll, braucht jedoch Beispiele, bei denen jemand gesagt hat: „Das ist hier zu diesem Zeitpunkt passiert.“ Solche Beispiele sind selten, und die üblichen Quellen sind unzuverlässig:
- Instandhaltungsaufträge halten fest, wann die Reparatur erfolgte, nicht wann der Fehler begann, und enthalten oft Freitext wie „Pumpe repariert“.
- Schichtbücher werden am Schichtende geschrieben, mit ungefähren Zeitangaben.
- Alarmhistorien erfassen Schwellenwertüberschreitungen, die nicht mit echten Störungen gleichzusetzen sind.
- Nachträgliches Labeln durch Ingenieure, die Diagramme betrachten, ist langsam und von Person zu Person uneinheitlich.
Die wirksamste Lösung besteht darin, Labels als strukturierte Ereignisse zum Zeitpunkt ihres Auftretens zu erfassen, und zwar auf derselben Messaging-Schicht wie die Telemetrie. Drückt der Bediener auf einem Tablet „Stau behoben“ und wird daraus eine MQTT-Nachricht mit Zeitstempel und Anlagenpfad, ist das Label bereits mit den Sensordaten abgeglichen.
Label-Typen für Sensordaten
| Label-Typ | Form | Beispiel | Typische Verwendung |
|---|---|---|---|
| Punktereignis | Einzelner Zeitstempel | „Werkzeug gewechselt“, „Probe entnommen“ | Standzeiten segmentieren, Eingriffe markieren |
| Intervall | Start und Ende | „Rüsten von 08:10 bis 08:45“ | Nicht-Produktionszeiten ausschließen, Zustandsklassifikation |
| Fensterklasse | Festes Fenster mit Klasse | „Dieses 10-Minuten-Fenster: Kavitation“ | Training von Klassifikatoren |
| Ergebnis | Mit einem Zeitraum verknüpftes Resultat | „Charge 4411 hat die Qualitätsprüfung nicht bestanden“ | Qualitätsprognose |
| Ausfall | Zeitstempel plus Ausfallart | „Lagerschaden, Außenring“ | Ausfall- und RUL-Modelle |
Die meisten Projekte benötigen mehrere Typen gleichzeitig. Intervalle für den Maschinenzustand (Betrieb, Rüsten, Reinigung, Störung) sind besonders wertvoll, weil Sie damit Zeiträume ausschließen können, die ein Modell sonst verwirren würden.
Ein Label-Schema entwerfen
Einigen Sie sich auf ein Schema, bevor Sie irgendeine Oberfläche bauen. Ein praxistaugliches Schema umfasst:
- Ein festes Vokabular an Label-Codes, zum Beispiel
STATE_SETUP,STATE_CLEANING,FAULT_JAM,FAULT_LEAK,MAINT_BEARING_REPLACED. Freitext gehört in ein separates Kommentarfeld. - Einen Ereignistyp:
start,endoderpoint. Intervalle entstehen aus Start-Ende-Paaren. - Den Anlagenpfad mit derselben Hierarchie wie die Telemetrie, damit die Verknüpfung trivial wird.
- Quell- und Erfassungszeitstempel. Der Bediener gibt womöglich „Stau begann vor 5 Minuten“ ein; erfassen Sie sowohl, wann es passiert ist, als auch, wann es eingegeben wurde.
- Wer gelabelt hat (Rolle oder Ausweisnummer, nicht unbedingt ein Name) und, wo relevant, die Konfidenz.
- Eine eindeutige Ereignis-ID, damit Korrekturen auf ein früheres Label verweisen und es ersetzen können.
- Eine Schemaversion, um Änderungen zu verarbeiten, ohne ältere Daten unbrauchbar zu machen.
Halten Sie das Vokabular kurz. Zehn klar definierte, konsequent verwendete Codes sind mehr wert als hundert Codes, die jeder Bediener anders auslegt. Der Leitfaden zur IIoT-Datenmodellierung behandelt die Anlagenpfad-Seite dieses Entwurfs.
Labels per MQTT erfassen
Veröffentlichen Sie Labels auf einem eigenen Untertopic jeder Anlage, direkt neben ihrer Telemetrie:
connectmq/plant1/line2/filler1/telemetry/vibration
connectmq/plant1/line2/filler1/labels
Am besten liegt dieser Anlagenpfad in einem Unified Namespace (UNS), dessen Topic-Struktur der ISA-95-Hierarchie folgt (Enterprise → Site → Area → Line → Cell), etwa acme/werk-stuttgart/abfuellung/linie-2/fueller-1/labels neben .../fueller-1/telemetrie/vibration. Labels, Maschinendaten aus SPS und OPC UA sowie Auftragsdaten aus MES oder ERP teilen dann denselben Kontext, und die spätere Verknüpfung ist ein reiner Pfadvergleich. Wie Sparkplug B in dieses Bild passt, beschreibt der Beitrag zu Sparkplug B und Unified Namespace.
Labels sollten QoS 1 verwenden, damit sie nicht unbemerkt verloren gehen, und nicht als Retained Message gesendet werden, weil jedes Label ein Ereignis und kein aktueller Zustand ist. Soll der aktuelle Maschinenzustand zusätzlich in Dashboards sichtbar sein, veröffentlichen Sie ihn separat als Retained-Topic state.
Hier ist ein kleiner Python-Labeling-Client, den eine Bedienstation oder ein Testskript nutzen kann. Er veröffentlicht strukturierte Label-Ereignisse an den öffentlichen MQTT-Broker, der nur für Tests gedacht ist; im realen Betrieb mit Produktionsdaten verwenden Sie Ihre eigenen Broker-Zugangsdaten.
# label_client.py
import json
import sys
import time
import uuid
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
ASSET = "connectmq/demo/lbl-4c2e/line2/filler1"
CODES = {"STATE_SETUP", "STATE_CLEANING", "FAULT_JAM", "FAULT_LEAK", "MAINT_BEARING_REPLACED"}
def publish_label(client, code, event, minutes_ago=0, comment="", operator="op-station-2"):
if code not in CODES:
raise ValueError(f"unknown label code {code}")
now = int(time.time() * 1000)
label = {
"schema": 1,
"id": str(uuid.uuid4()),
"code": code,
"event": event, # start | end | point
"ts": now - int(minutes_ago * 60000),
"entered": now,
"by": operator,
"comment": comment,
}
info = client.publish(f"{ASSET}/labels", json.dumps(label), qos=1)
info.wait_for_publish()
print("sent", label["code"], label["event"])
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="labeler-" + uuid.uuid4().hex[:8])
client.connect(BROKER, 1883, keepalive=60)
client.loop_start()
# Aufruf: python label_client.py FAULT_JAM start 3 "bottle stuck at infeed"
code, event = sys.argv[1], sys.argv[2]
minutes = float(sys.argv[3]) if len(sys.argv) > 3 else 0
comment = sys.argv[4] if len(sys.argv) > 4 else ""
publish_label(client, code, event, minutes, comment)
client.loop_stop()
client.disconnect()
In der Praxis kann dieselbe Nachricht von einer Schaltfläche in einem Node-RED-Dashboard, einer Tablet-App mit MQTT über WebSocket, einem Barcodescanner an einer Qualitätsstation oder einer SPS stammen, die ihre eigenen Zustandswechsel veröffentlicht. Maschinengenerierte Labels wie SPS-Zustandscodes sind oft die zuverlässigste Quelle für Zustandsintervalle; die Bediener ergänzen dann, was die Maschine nicht wissen kann, etwa Grundursachen.
Aus Ereignissen Trainingsdaten machen
Sobald Labels und Telemetrie von einem Historian-Subscriber gespeichert sind, folgt der nächste Schritt: Start- und Ende-Ereignisse in Intervalle umwandeln und sie Telemetriefenstern zuordnen. Das folgende Skript erledigt das mit pandas.
# build_dataset.py
import pandas as pd
# labels.csv: id,code,event,ts telemetry.csv: ts,vib_rms,current
labels = pd.read_csv("labels.csv", parse_dates=["ts"]).sort_values("ts")
tele = pd.read_csv("telemetry.csv", parse_dates=["ts"]).sort_values("ts")
# 1. Start-/Ende-Ereignisse pro Code zu Intervallen zusammenfügen
intervals = []
open_events = {}
for row in labels.itertuples():
if row.event == "start":
open_events[row.code] = row.ts
elif row.event == "end" and row.code in open_events:
intervals.append((row.code, open_events.pop(row.code), row.ts))
intervals = pd.DataFrame(intervals, columns=["code", "start", "end"])
# 2. Feste Fenster mit Telemetriemerkmalen bilden
win = (tele.set_index("ts").resample("1min")
.agg({"vib_rms": ["mean", "std", "max"], "current": ["mean"]}))
win.columns = ["_".join(c) for c in win.columns]
win = win.dropna().reset_index()
win["window_end"] = win["ts"] + pd.Timedelta(minutes=1)
# 3. Label vergeben, wenn ein Fenster ein Intervall zu mehr als der Hälfte überlappt
def label_for(w):
for iv in intervals.itertuples():
overlap = (min(w.window_end, iv.end) - max(w.ts, iv.start)).total_seconds()
if overlap > 30:
return iv.code
return "NORMAL"
win["label"] = [label_for(w) for w in win.itertuples()]
# 4. Mehrdeutige Fenster nahe Intervallgrenzen verwerfen
for iv in intervals.itertuples():
near = ((win["ts"] - iv.start).abs() < pd.Timedelta(minutes=2)) | \
((win["ts"] - iv.end).abs() < pd.Timedelta(minutes=2))
win.loc[near, "label"] = "EXCLUDE"
dataset = win[win["label"] != "EXCLUDE"]
print(dataset["label"].value_counts())
dataset.to_csv("training_windows.csv", index=False)
Zwei Details sind hier wichtig. Fenster an den Grenzen werden ausgeschlossen, weil der genaue Beginn eines Staus oder einer Leckage unsicher ist und das Training auf diesen Fenstern dem Modell Rauschen beibringt. Und nicht gepaarte Start-Ereignisse werden nicht stillschweigend geschlossen; prüfen Sie sie, denn ein vergessener „Ende“-Klick kann Stunden normalen Betriebs in ein Störungs-Label verwandeln.
Qualitätsprüfungen für Labels
Nutzen Sie vor dem Training diese Checkliste:
- Zählen Sie Labels pro Code und pro Anlage; sehr ungleiche Zahlen zeigen oft, dass eine Schicht oder ein Standort überhaupt nicht labelt.
- Suchen Sie nicht gepaarte Start- und Ende-Ereignisse sowie überlappende Intervalle unvereinbarer Codes.
- Vergleichen Sie Erfassungszeit und Ereigniszeit; große Abstände deuten auf nachträgliche Schätzungen hin.
- Plotten Sie die Telemetrie rund um eine Zufallsstichprobe von Labels und prüfen Sie, ob sich das Signal tatsächlich verändert.
- Lassen Sie eine zweite Person eine Stichprobe prüfen und messen Sie die Übereinstimmung.
- Versionieren Sie den Datensatz zusammen mit der Version des Label-Schemas und der Abfrage, die ihn erzeugt hat.
Labels kontinuierlich erfassen
Labeln ist kein einmaliges Projekt. Machen Sie es zum Teil der normalen Arbeit: Die Schaltfläche, die einen Stau-Alarm quittiert, kann auch das Label veröffentlichen, und das Abschlussformular der Instandhaltung kann die Ausfallart veröffentlichen. Speisen Sie Modellalarme als Label-Kandidaten zurück, die Bediener bestätigen oder ablehnen; diese Bestätigung ist selbst ein wertvolles Label. Der Artikel IoT MLOps beschreibt, wie solche Feedbackschleifen das Nachtrainieren antreiben, und Machine Learning für Predictive Maintenance zeigt, wie Ausfall-Labels zu Trainingszielen werden. Für Degradationsmodelle sind vollständige Lebenszyklusereignisse unerlässlich, wie in Prognose der Restlebensdauer erläutert.
Labels und Telemetrie mit ConnectMQ betreiben
Wenn Telemetrie und Labels über einen einzigen Broker laufen, bleibt alles über Anlagenpfad und Zeit abgeglichen. ConnectMQ bietet einen verwalteten MQTT-Broker mit MQTT über sicheres WebSocket auf Port 8084, sodass eine browserbasierte Labeling-Seite direkt veröffentlichen kann, und mit dem Live-Topic-Explorer können Sie Label-Nachrichten prüfen, während Bediener sie senden. Speicherung und Datensatzerstellung laufen in Ihren eigenen Subscribern, etwa einem Historian-Writer und dem obigen Skript. Das Gesamtbild von KI mit vernetzten Geräten finden Sie im Leitfaden zu KI und IoT.
Mit ConnectMQ starten
Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ganz ohne Kreditkarte. Verwenden Sie die generierten Werte YOUR_USERNAME, YOUR_PASSWORD und YOUR_CLIENT_ID für Ihr Gateway und Ihre Labeling-Clients und beginnen Sie noch heute, Labels neben Ihrer Telemetrie zu sammeln; jede Woche mit konsistenten Labels macht Ihr nächstes Modell besser.
Häufig gestellte Fragen
Wie labelt man Zeitreihen-Sensordaten am besten?
Erfassen Sie Labels als strukturierte Ereignisse in dem Moment, in dem sie auftreten – mit festem Vokabular, Anlagenpfad und Zeitstempeln und auf derselben Messaging-Schicht wie die Telemetrie. Nachträgliches Labeln anhand von Diagrammen ist langsamer und weniger konsistent.
Sollten Label-Nachrichten in MQTT als Retained Message gesendet werden?
Nein. Labels sind Ereignisse; veröffentlichen Sie sie daher mit QoS 1 und ohne Retain-Flag und speichern Sie sie mit einem Subscriber. Den aktuellen Maschinenzustand veröffentlichen Sie separat als Retained-Topic, falls Dashboards ihn benötigen.
Wie gehe ich mit unsicheren Startzeiten von Labels um?
Erfassen Sie sowohl die geschätzte Ereigniszeit als auch die Erfassungszeit und schließen Sie Fenster nahe den Intervallgrenzen vom Training aus. So entfernen Sie die mehrdeutigsten Beispiele, ohne das Label zu verwerfen.
Können Maschinen Labels automatisch erzeugen?
Ja. SPS-Zustandscodes, Alarmereignisse und Ergebnisse von Qualitätsstationen sind gute automatische Labels. Bediener ergänzen dann Informationen, die die Maschine nicht kennen kann, etwa die Grundursache oder die Bestätigung eines Modellalarms.



