Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Verwenden Sie gemessene Ergebnisse, um bessere Modellkoeffizienten zu finden. In diesem Beispiel passt eine Python-Anwendung eine Formel zur Gewichtsvorhersage an, prüft sie anhand separater Validierungsdatensätze und gibt sie frei, wenn sich die Vorhersagen verbessern.
Die Anwendung (genannt Supervisor) speichert genehmigte Koeffizienten für spätere Vorhersagen. Fitting läuft in NumPy, außerhalb des Datenflussgraphen. Eine integrierte Kartentransformation wertet dann die genehmigte Formel aus.
Wie die Teile zusammenhängen
- Übereinstimmungen exportieren. Der Exportgraph übermittelt abgeschlossene Übereinstimmungen an die Anwendung.
- Extern berechnen und genehmigen. Das Python-Beispiel berechnet einen Kandidaten und eine Prüfentscheidung. Ihr Supervisor ist für Genehmigung und Persistenz zuständig.
- Genehmigte Koeffizienten speichern. Der Supervisor schreibt den vollständigen aktiven Modell-Datensatz in den Zustandsspeicher.
Um diesen Datensatz zu konsumieren, lesen Sie Koeffizienten aus dem Statusspeicher.
Für die Zustellung über MQTT statt über State-Store-Suche siehe Genehmigte Modellaktualisierungen über MQTT bereitstellen.
Voraussetzungen
Erfüllen Sie die gemeinsamen Beispielvoraussetzungen, einschließlich des factory-mqtt Profils und des default Endpunkts. Verwenden Sie YAML zum Debuggen und Azure CLI oder Bicep für das Produktionsmanagement.
Für CLI-Bereitstellungen legen Sie AIO_INSTANCE_NAME und RESOURCE_GROUP auf Ihre bestehende Instanz und Ressourcengruppe fest. Für Bicep-Deployments solltest du auch CUSTOM_LOCATION_NAME auf den bestehenden benutzerdefinierten Standort der Instanz festlegen. Die Deployment-Tabs beziehen sich auf die bestehende Instanz, das Profil und den Endpunkt; sie erstellen sie nicht. Der Exportgraph benötigt keinen Registry-Endpunkt, weil er keine Transformationen hat.
Das Fitting-Skript erfordert außerdem Python 3 und NumPy. Das State-Store-Schreibbeispiel verwendet die mosquitto_pub und mosquitto_sub MQTT-Clients.
Übereinstimmende Datensätze vorbereiten
Bereite abgeschlossene Matches mit den von jeder Vorhersage verwendeten Feature-Werte vor. Das Abgleich- und Korrelationsmuster zeigt eine Möglichkeit, sie zu erzeugen.
Einen Kandidaten aus künstlich erzeugten abgestimmten Datensätzen ermitteln
Beginne mit Modell v7: weight = 2 * speed + 0.5 * temperature + 175.
Jeder abgestimmte Datensatz muss die für dieses Element verwendeten Funktionswerte, das gemessene Gewicht und die Modellversion, die die Vorhersage erstellt hat, enthalten.
Zum Beispiel ist ein Trainingsinput für den Vorgesetzten:
{"assetId":"line-1","pieceId":"part-1","modelVersion":7,"speed":8,"temperature":18,"predictedWeight":200,"measuredWeight":198,"residual":-2}
Verwenden Sie diese synthetischen Übereinstimmungen: vier zum Fitten und zwei zur Validierung. Halte die Teile-IDs der Sets unterschiedlich.
| Verwenden | Stück | Speed | Temperatur | Gemessenes Gewicht | Vorhersage des Modells v7 |
|---|---|---|---|---|---|
| Training | part-1 |
8 | 18 | 198 | 200 |
| Training | part-2 |
10 | 18 | 202 | 204 |
| Training | part-3 |
8 | 22 | 200 | 202 |
| Training | part-4 |
10 | 22 | 204 | 206 |
| Validation | part-5 |
9 | 20 | 201 | 203 |
| Validation | part-6 |
11 | 24 | 207 | 209 |
Die Fitting-Operation minimiert die Summe der quadratischen Fehler für b0 + b1 * speed + b2 * temperature. Diese Trainingswerte ergeben:
- Geschwindigkeitskoeffizient:
(202 - 198) / (10 - 8) = 2. - Temperaturkoeffizient:
(200 - 198) / (22 - 18) = 0.5. - Abfangen:
198 - 2 * 8 - 0.5 * 18 = 173.
Der Kandidat prognostiziert 201 und 207 für die beiden Validierungselemente. Der Wurzel-Mittler-Quadratfehler (RMSE) ist 0; das RMSE von Modell v7 ist 2. Wählen Sie eine angemessene Validierungsstichprobengröße für Ihre Anwendung.
Für Live-Eingaben stellen Sie den Exportgraphen mit einer der folgenden Methoden bereit. Die Anwendung abonniert factory/supervisor-input; sie veröffentlicht abgeschlossene Matches an factory/matches.
Die untenstehende Python-Demo verwendet die Tabelle direkt und erfordert kein MQTT.
- Betriebserfahrung
- Azure CLI
- Bicep
- Kubernetes (nur Debuggen)
- Öffnen Sie in der Vorgangsanzeige Ihre Instanz und wählen Sie Datenflussdiagramm>Datenflussdiagramm erstellen.
- Benennen Sie das Diagramm
export-training-matchesund wählen Sie dasdefaultProfil aus. - Quelle
sourcemit Endpunktfactory-mqttund Themafactory/matcheshinzufügen. - Fügen Sie Ziel
destinationmit Endpunktfactory-mqttund Topicfactory/supervisor-inputhinzu. - Verbinden Sie
sourcedirekt mitdestination, ohne eine Transformation hinzuzufügen, und wählen Sie Speichern.
Die Grafik leitet jedes abgeschlossene Match unverändert weiter. Die Anwendung sammelt Übereinstimmungen, hält Trainings- und Validierungsdatensätze getrennt und passt ein Kandidatenmodell an.
Ein Beispielkandidat, der von dieser Anwendung auf factory/model-proposals ausgegeben wird:
{
"kind": "modelProposal",
"assetId": "line-1",
"updateId": "update-42",
"expectedModelVersion": 7,
"modelVersion": 8,
"coefficients": {
"speedCoefficient": 2,
"temperatureCoefficient": 0.5,
"intercept": 173
},
"validation": {
"trainingPieceIds": ["part-1", "part-2", "part-3", "part-4"],
"validationPieceIds": ["part-5", "part-6"],
"activeRmse": 2,
"candidateRmse": 0
}
}
Für dieses Beispiel erfordert die Genehmigung das konfigurierte Asset line-1, die aktive Version 7, die Kandidatenversion 8, endliche Koeffizienten, disjunkte Stichprobensätze, eine niedrigere Validierungs-RMSE und eine Intercept-Änderung von höchstens 3. Der Intercept änderte sich um -2, sodass dieser Kandidat besteht. Ein Kandidat mit Intercept 180 scheitert beim letzten Check. Lehne einen erneuten Versuch ab, nachdem v8 aktiv ist.
Diese Überprüfungen sind Beispielrichtlinien für Anwendungen.
Speichere dieses Beispiel als fit-model.py und führe python3 fit-model.py aus. Es werden die sechs oben genannten Datensätze verwendet, und ein Kandidaten sowie eine Bewertungsentscheidung werden ausgedruckt. Ihr Supervisor übernimmt die MQTT-Kommunikation und das Schreiben des aktiven Zustands. Das Skript ist ausschließlich für das Berechnen und die Überprüfung zuständig.
import json
import numpy as np
# Each row is (piece ID, speed, temperature, measured weight).
training = [
("part-1", 8, 18, 198),
("part-2", 10, 18, 202),
("part-3", 8, 22, 200),
("part-4", 10, 22, 204),
]
validation = [("part-5", 9, 20, 201), ("part-6", 11, 24, 207)]
if {r[0] for r in training} & {r[0] for r in validation}:
raise ValueError("Training and validation pieces must be distinct.")
x = np.array([[1, speed, temperature] for _, speed, temperature, _ in training], dtype=float)
y = np.array([weight for _, _, _, weight in training], dtype=float)
candidate, _, rank, _ = np.linalg.lstsq(x, y, rcond=None)
if rank != 3 or not np.isfinite(candidate).all():
raise ValueError("The fit needs three independent, finite parameters.")
vx = np.array([[1, speed, temperature] for _, speed, temperature, _ in validation], dtype=float)
vy = np.array([weight for _, _, _, weight in validation], dtype=float)
active = np.array([175, 2, 0.5]) # Intercept, speed, temperature for v7.
active_rmse = float(np.sqrt(np.mean((vx @ active - vy) ** 2)))
candidate_rmse = float(np.sqrt(np.mean((vx @ candidate - vy) ** 2)))
proposal = {
"kind": "modelProposal",
"assetId": "line-1",
"updateId": "update-42",
"expectedModelVersion": 7,
"modelVersion": 8,
"coefficients": {
"intercept": float(candidate[0]),
"speedCoefficient": float(candidate[1]),
"temperatureCoefficient": float(candidate[2]),
},
"validation": {
"trainingPieceIds": [row[0] for row in training],
"validationPieceIds": [row[0] for row in validation],
"activeRmse": active_rmse,
"candidateRmse": candidate_rmse,
},
}
def review(update, active_model, committed_update_ids):
"""Example policy for candidates produced by this trusted fitting process."""
coefficients = update["coefficients"]
metrics = update["validation"]
if update["updateId"] in committed_update_ids:
return {"approved": False, "reason": "duplicate update"}
if update["assetId"] != active_model["assetId"]:
return {"approved": False, "reason": "wrong asset"}
if (update["expectedModelVersion"] != active_model["modelVersion"]
or update["modelVersion"] != active_model["modelVersion"] + 1):
return {"approved": False, "reason": "stale or unexpected version"}
if (set(metrics["trainingPieceIds"]) & set(metrics["validationPieceIds"])
or not metrics["trainingPieceIds"] or not metrics["validationPieceIds"]):
return {"approved": False, "reason": "invalid validation split"}
numbers = [*coefficients.values(), metrics["activeRmse"], metrics["candidateRmse"]]
if not np.isfinite(numbers).all():
return {"approved": False, "reason": "non-finite coefficient or metric"}
if metrics["candidateRmse"] < 0 or metrics["activeRmse"] < 0:
return {"approved": False, "reason": "invalid RMSE"}
if metrics["candidateRmse"] >= metrics["activeRmse"]:
return {"approved": False, "reason": "no validation improvement"}
if abs(coefficients["intercept"] - active_model["intercept"]) > 3:
return {"approved": False, "reason": "intercept change exceeds policy"}
return {"approved": True, "reason": "candidate passes example policy"}
active_record = {"assetId": "line-1", "modelVersion": 7, "intercept": 175}
decision = review(proposal, active_record, set())
print(json.dumps({"candidate": proposal, "review": decision}, allow_nan=False))
Gleitkomma-Fitting kann Werte nahe 173, 2, 0.5 und 0 ausgeben.
Verwenden Sie numerische Toleranzen und behalten Sie die genauen genehmigten Koeffizienten bei.
Bei der Überprüfung werden korrekt aufgebaute Kandidaten und Kennzahlen aus dem vertrauenswürdigen Fitting-Prozess erwartet.
Bevor der genehmigte Datensatz geschrieben wird, überprüft der Vorgesetzte die aktive Version erneut und verzeichnet die Genehmigungs- und Aktualisierungs-ID in seinem eigenen persistenten Protokoll. Prüfungen und Schreibvorgänge pro Asset serialisieren, damit konkurrierende Updates nicht beide die gleiche Versionsprüfung bestehen können.
Genehmigte Koeffizienten speichern
Nach der Genehmigung schreibt der Supervisor einen vollständigen aktiven Modell-Datensatz unter dem Schlüssel factory-active-models. Anfangs enthält es:
{"assetId":"line-1","modelVersion":7,"speedCoefficient":2,"temperatureCoefficient":0.5,"intercept":175}
Nach dem Akzeptieren von update-42 ersetzen Sie es durch:
{"assetId":"line-1","modelVersion":8,"speedCoefficient":2,"temperatureCoefficient":0.5,"intercept":173}
Für eine eigenständige Lookup-Demo schreibe direkt den synthetischen V8-Datensatz. Für ein angepasstes Modell ersetzen Sie alle drei unten aufgeführten Koeffizienten durch die exakt genehmigten Werte.
Um v7 und v8 zu vergleichen, führe zuerst den Writer mit modelVersion: 7 und intercept: 175aus, stelle dann die v8-Werte wieder her und führe es erneut aus.
Verwenden Sie das State-Store-SETProtokoll. Speichere dieses Python-Skript als write-model.py; es erstellt die Anfragedatei mit den erforderlichen Bytelängen.
import json
from pathlib import Path
record = {
"assetId": "line-1",
"modelVersion": 8,
"speedCoefficient": 2,
"temperatureCoefficient": 0.5,
"intercept": 173,
}
parts = [b"SET", b"factory-active-models", json.dumps(record, separators=(",", ":")).encode("utf-8")]
request = b"*3\r\n" + b"".join(
b"$" + str(len(part)).encode("ascii") + b"\r\n" + part + b"\r\n"
for part in parts
)
Path("set-model.resp").write_bytes(request)
Für einen Debug-Schreibvorgang generiere die Datei und sende sie dann mit den erforderlichen MQTT v5-Eigenschaften. Führen Sie den Abonnenten zuerst in einem anderen Terminal aus; fügen Sie beiden MQTT-Befehlen die Authentifizierungs- und TLS-Optionen Ihres Brokers hinzu.
Halten Sie die Uhr des Writers innerhalb einer Minute Abweichung zur Uhr des Brokers.
Die __ts Eigenschaft enthält den Zeitstempel der Anfrage. Wenn die Antwort meldet, dass der Zeitstempel zu weit in der Zukunft liegt, korrigiere die Uhr-Fehlanpassung, bevor du es erneut versuchst.
mosquitto_sub -h <BROKER_HOST> -p <BROKER_PORT> -V mqttv5 -q 1 \
-F '%D %p' \
-t 'clients/model-writer/services/statestore/_any_/command/invoke/response'
python3 write-model.py
mosquitto_pub -h <BROKER_HOST> -p <BROKER_PORT> -V mqttv5 -q 1 \
-t 'statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke' \
-D publish response-topic 'clients/model-writer/services/statestore/_any_/command/invoke/response' \
-D publish correlation-data 'update-42' \
-D publish user-property __ts "$(date +%s%3N):0:model-writer" \
-f set-model.resp
Ein erfolgreicher Schreibvorgang zeigt update-42 +OK an: die Korrelationsdaten der Anfrage, gefolgt von der Antwort-Nutzlast. Für Transport- und Autorisierungsanforderungen siehe die State Store Protokollreferenz.
Der manuelle Vorgang SET ersetzt den Datensatz ohne Überprüfung der erwarteten Modellversion.
Verwenden Sie für diese Demo einen einzelnen autorisierten Writer. In Ihrer Anwendung bewahren Sie die genehmigte Historie auf und aktualisieren Sie die IDs außerhalb des Prädiktors für Wiederherstellungs- und Duplikatprüfungen. Um die Formel zurückzusetzen, genehmigen Sie die alten Koeffizienten als neue Version.
Für das Diagramm, das das gespeicherte Modell liest und Vorhersagen berechnet, siehe Koeffizienten aus dem Zustandsspeicher lesen.