A.I. basierte Maschinenzustandsüberwachung (2/3)

Dies ist Teil 2 einer mehrteiligen Serie, welche beispielhaft zeigt, wie mit Hilfe von maschinellen Lernverfahren eine K.I. trainiert wird, die den Zustand einer Maschine in Echtzeit überwachen kann (Condition Monitoring). Die Teile sind folgende:

  1. Problemstellung, Lösungsweg und Datenerhebung
  2. Training und Evaluation mit Tensorflow 2.0 (dieser)
  3. Deployment und Anwendungsbeispiel mit Tensorflow Serving in Amazon ECS

Dabei wird ein Neuronales Netz mit Tensorflow 2.0 angelernt, als Tensorflow Serving gepackt und in Amazon Elastic Container Service (ECS) in der Cloud Deployed. Außerdem wird eine simple Beispielanwendung die Sensordaten an den Cloud Endpunkt übertragen und den Maschinenzustand visualisieren.

Datenaufbereitung

Nachdem in Teil 1 beschrieben wurde, wie die Daten erhoben wurden, mit welchen das neuronale Netz trainiert werden soll, wird nochmal allgemein auf die Form von Daten hingewiesen.

Für maschinelle Lernverfahren sind Features und Label notwendig (so genanntes Supervised Learning). Dabei wird allgemein das Featureset mit \(X\) bezeichnet und die Label mit \(y\), sodass die Daten in der Form:

\[X = [[x_{11}, x_{12}, x_{13}], [x_{21}, x_{22}, x_{23}], [x_{31}, x_{32}, x_{33}], …]\]

\[y = [y_1, y_2, y_3, …]\]

vorliegen müssen.

Training Data (Gitlab Repository)

 

Die Label (also was der Algorithmus lernen soll) ergeben sich durch die Zugehörigkeit der Logdateien zum Maschinenzustand. In Teil 1 wurden jeweils für einen funktionierenden und eine nicht funktionierenden Maschinenzustand Logdaten erhoben. Die Daten werden eingelesen und die Label manuell hinzugefügt.

import pandas as pd
import numpy as np
X_0 = pd.read_csv('./TrainingData/notworking.csv')
X_1 = pd.read_csv('./TrainingData/working.csv')

classes = {'notworking': 0, 'working': 1} # to predict

X_0['label'] = classes['notworking']
X_1['label'] = classes['working']

X_df = pd.concat([X_0, X_1])

Als relevante Features wählen wir die Beschleunigungen in alle 3 Raumrichtungen. Diese sind im Falle eines balancierenden Roboters relativ trivial, für Business Prozesse oder andere Maschinen die überwacht werden sollen, stellt das das Expertenwissen dar, welches i.d.R. nur mit der Fachabteilung bestimmt werden kann. Die Wahl der Features (also was in den Daten überhaupt relevant ist), ist der Kern eines jeden K.I. Projekts.

features = ['ax [m/s²]', 'ay [m/s²]', 'az [m/s²]']

Wir bilden Feature Vektor \(X\) und dazugehörigen Label Vektor \(y\).

X = X_df[features].values
y = X_df.loc[:, 'label'].values

Training eines Neuronalen Netz mit Tensorflow 2.0

Ein maschinelles Lernverfahren wird mit relevanten Daten trainiert (Features) und man muss dem Algorithmus sagen, zu welcher Kategorie diese Daten gehören (Label). In unserem Beispiel haben wir zwei verschiedene Label: Die Maschine funktioniert ordnungsgemäß und die Maschine hat einen Fehler. Um zu überprüfen, wie gut der Algorithmus funktioniert, wird ein Teil der Trainingsdaten zur Evaluation (Test) aussortiert und nicht für das Training verwendet.

Wir importieren die notwendigen Tools  von SciKit Learn und teilen den Datensatz in Training und Testdaten auf.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

Nun haben wir Trainingsdaten und Testdaten und können ein einfaches Netzwerk mit 50 Neuronen und einem Layer trainieren.

Neuronales Netz zur Detektion des Maschinenzustands

import tensorflow as tf
from tensorflow import keras

model = keras.Sequential([
 keras.layers.Dense(50, input_dim=len(features), activation='relu'),
 keras.layers.Dense(len(classes), activation='softmax')
])
model.compile(optimizer='Adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=20)

Im Verlauf des Trainings sieht man den Lernerfolg, der Adam Optimizer verteilt die Fehler entsprechend auf die Aktivierungsfunktionen, dass das Netzwerk die vorherzusagenden Kategorien immer besser bestimmen kann.


Train on 816 samples
Epoch 1/20 816/816 [==============================] – 1s 753us/sample – loss: 2.0872 – accuracy: 0.2966
Epoch 2/20 816/816 [==============================] – 0s 42us/sample – loss: 0.6096 – accuracy: 0.6679
Epoch 3/20 816/816 [==============================] – 0s 43us/sample – loss: 0.2166 – accuracy: 0.9571
Epoch 4/20 816/816 [==============================] – 0s 41us/sample – loss: 0.1379 – accuracy: 0.9743
Epoch 5/20 816/816 [==============================] – 0s 41us/sample – loss: 0.1093 – accuracy: 0.9779
Epoch 6/20 816/816 [==============================] – 0s 42us/sample – loss: 0.0946 – accuracy: 0.9779
Epoch 7/20 816/816 [==============================] – 0s 41us/sample – loss: 0.0853 – accuracy: 0.9792
Epoch 8/20 816/816 [==============================] – 0s 39us/sample – loss: 0.0792 – accuracy: 0.9804
Epoch 9/20 816/816 [==============================] – 0s 43us/sample – loss: 0.0744 – accuracy: 0.9804
Epoch 10/20 816/816 [==============================] – 0s 40us/sample – loss: 0.0710 – accuracy: 0.9816
Epoch 11/20 816/816 [==============================] – 0s 42us/sample – loss: 0.0682 – accuracy: 0.9816
Epoch 12/20 816/816 [==============================] – 0s 42us/sample – loss: 0.0661 – accuracy: 0.9804
Epoch 13/20 816/816 [==============================] – 0s 40us/sample – loss: 0.0643 – accuracy: 0.9804
Epoch 14/20 816/816 [==============================] – 0s 39us/sample – loss: 0.0632 – accuracy: 0.9792
Epoch 15/20 816/816 [==============================] – 0s 41us/sample – loss: 0.0617 – accuracy: 0.9816
Epoch 16/20 816/816 [==============================] – 0s 42us/sample – loss: 0.0603 – accuracy: 0.9828
Epoch 17/20 816/816 [==============================] – 0s 41us/sample – loss: 0.0598 – accuracy: 0.9816
Epoch 18/20 816/816 [==============================] – 0s 41us/sample – loss: 0.0590 – accuracy: 0.980
Epoch 19/20 816/816 [==============================] – 0s 42us/sample – loss: 0.0578 – accuracy: 0.9816
Epoch 20/20 816/816 [==============================] – 0s 42us/sample – loss: 0.0581 – accuracy: 0.9779

Nach wenigen Iterationen ist die Accuracy auf 97.8% gestiegen.

Klassifikation

Das Netzwerk gibt als Output die Wahrscheinlichkeit für das jeweilige Label, basierend auf den eingehenden Features aus. Wir nehmen nun die vorher beiseite gelegten Testdaten und lassen das Netzwerk damit klassifizieren, ob die Maschine läuft oder nicht.

y_pred_probs = model.predict(X_test)
y_pred = np.argmax(y_pred_probs, axis=1) # Retranslate to the Class

Im Vektor \(y_{pred}\) ist jetzt für jedes Feature Set aus \(X_{test}\) der vorhergesagte Zustand gespeichert. Da wir diesen wissen, weil wir den Testdatensatz vorher beiseite gelegt haben, können wir damit testen, wie gut das Netzwerk die tatsächlichen Maschinenzustände korrekt vorhersagen konnte.

Evaluation

Der Output auf bisher ungesehene Daten kann mit dem wahren Maschinenzustand verglichen werden. Daraus ergeben sich verschiedene statistische Werte.

print(classification_report(y_test, y_pred, target_names=classes.keys()))
                 precision    recall  f1-score   support

  notworking       0.99      0.97      0.98       198
     working       0.97      1.00      0.98       205

Die Precision ist das Verhältnis \(tp / (tp + fp)\), wobei \(tp\) die Anzahl der echten positiven und \(fp\) die Anzahl der falschen positiven Werte ist. Die Präzision liegt bei 99% für die Fähigkeit des Netzwerks, eine nicht funktionierende Maschine nicht fälschlicher Weise als funktionierend zu detektieren.

Der Recall ist das Verhältnis \(tp / (tp + fn)\), wobei \(tp\) die Anzahl der echten positiven und \(fn\) die Anzahl der falschen negativen Werte ist. Der Recall ist die Fähigkeit des Klassifikators, alle positiven Proben zu finden.

Der F1 Score kann als gewichteter harmonischer Mittelwert der Präzision und des Recalls interpretiert werden. Mehr dazu hier…

Die Confusion Matrix für den vorhergesagten und wahren Zustand der Maschine

Zusammengefasst: Basierend auf den erhobenen Daten kann der Maschinenzustand ziemlich sicher vorhergesagt werden.

Tensorflow Modell abspeichern für spätere Verwendung in Tensorflow Serving

Das Modell ist nun trainiert und kann für die spätere Verwendung in Tensorflow Serving abgespeichert werden.

modelversion = '1'
tf.saved_model.save(model, f'./NeuralNetwork/{modelversion}/')

Hierbei wird sowohl Struktur als auch die Werte der gefundenen Gewichte abgespeichert (Größe auf der Festplatte: 82kB). Das Netzwerk ist nun fertig trainiert und kann für Vorhersagen genutzt werden.

Weiter zu Teil 3: Deployment und Beispiel-Anwendung

2 Comments

  1. […] Training und Evaluation mit Tensorflow 2.0 […]

  2. […] Training und Evaluation mit Tensorflow 2.0 […]

Leave A Comment