Technical Articles and Newsletters

Entwicklung eines IoT-Analysesystems mit MATLAB, Machine Learning und ThingSpeak

Von Robert S. Mawrey, MathWorks

Die Kombination aus intelligenten verbundenen Geräten mit Datenanalysen und maschinellem Lernen ermöglicht eine breite Palette an Anwendungen, von Eigenbau-Verkehrsüberwachungsysteme bis hin zu komplexen Systemen für die vorausschauende Wartung und futuristische Konsumgüter (wie Amazon Echo und Google Nest).

Während das Potenzial des Internets der Dinge (IoT, Internet of Things) nahezu unbegrenzt ist, kann die Entwicklung von IoT-Systemen entmutigend erscheinen, da sie eine komplexe Webinfrastruktur und Erfahrung mit mehreren Domänen erfordert.

Dieser Artikel zeigt, wie Sie einen Prototyp für ein IoT-System mit Datenanalysen erstellen und bereitstellen können, ohne benutzerdefinierte Websoftware oder Server zu entwickeln. Der Workflow basiert auf MATLAB® and ThingSpeak™, einer analytischen IoT-Plattform, die MATLAB-Code bedarfsgesteuert in der Cloud ausführt. Um den Workflow darzustellen, erstellen wir ein Gezeitenvorhersagesystem, das Bootsfahrer verwenden können, um die Auswirkung von Wind auf die Wassertiefe vorherzusagen.

Die Wassertiefe variiert mit den Gezeiten, sie wird jedoch zusätzlich wesentlich durch die Stärke, Dauer und Richtung des Windes beeinflusst. Die Vorhersage von durch Wind beeinflussten Wasserständen erfordert in der Regel komplexe hydrodynamische Modelle sowie detaillierte Kenntnisse über die Form der Bucht vor Ort und des Meeresgrundes. Das NOAA und andere Organisationen nutzen diese Ressourcen, um die Wassertiefe in wichtigen Häfen vorherzusagen, für kleinere Häfen und Buchten sind die damit verbundenen Kosten jedoch nicht vertretbar.

Das System, das wir entwickeln werden, basiert auf neuronalen Netzwerken und kostengünstigen Hardwaregeräten anstelle von rechenintensiven hydrodynamischen Modellen und einer komplexen Webinfrastruktur und stellt somit eine wirtschaftlich vertretbare Gezeitenvorhersage für kleinere Häfen und Buchten bereit.

Den in diesem Beispiel verwendeten Code können Sie herunterladen.

Vorhersage von Tidenanstieg und verstärktem Wind – Beispiel

Dieses Beispiel basiert auf Daten, die in einer Bucht in Cape Cod, Massachusetts, erfasst wurden (Abbildung 1).

Den in diesem Beispiel verwendeten Code können Sie herunterladen.

Abbildung 1: Gezeitenvorhersagesystem.

MATLAB-Code liest Wind- und Gezeitendaten aus ThingSpeak und anderen Online-Datenquellen und führt Gezeitenvorhersage- und neuronale Netzwerkalgorithmen aus, die den Tidenanstieg vorhersagen und einen bedarfsgesteuerten Plot der Tidenanstiegsvorhersage generieren (Abbildung 2).

Abbildung 2: Vorhersage-Plot von durch Wind beeinflusste Gezeiten auf MATLAB Machine Learning und ThingSpeak. Der Plot zeigt die tatsächlich gemessene Gezeit, die astronomische Gezeitenvorhersage (ohne Wind), die anhand neuronaler Netzwerke vorhergesagte, durch Wind beeinflusste Gezeitenvorhersage (astronomische Vorhersage plus Wind) und das Residuum (Differenz zwischen den tatsächlichen oder durch Wind beeinflussten Vorhersagen und der astronomischen Vorhersage).

Wir führen den Workflow zur Entwicklung des Systems in den folgenden fünf Schritten durch:

  1. Historische Daten sammeln
  2. Daten analysieren
  3. Vorhersagealgorithmen entwickeln
  4. Analyse in der Cloud bereitstellen
  5. Bedarfsgesteuerte Datenanalysen und -Visualisierung durchführen

Schritt 1: Sammeln von Daten

Wir beginnen mit dem Sammeln von Tidenstanddaten mit ThingSpeak und einem kostengünstigen Gezeitenmessgerät. Die Firmware des Gezeitenmessgeräts ist in C-Code geschrieben und verwendet Open-Source-Kommunikationsbibliotheken von ThingSpeak für eingebettete Geräte, die auf GitHub veröffentlicht wurden..

Schritt 2: Analyse von historischen Daten

Wir laden die historischen Daten aus ThingSpeak in MATLAB herunter, das auf dem Desktop ausgeführt wird. Dort können wir die Daten untersuchen und bereinigen, um Rauschen, Ausreißer, fehlende oder fehlerhafte Werte und gegebenenfalls andere Abweichungen zu beseitigen.

% Download the tide data using a custom function
[tideTime,tideRangemm] = readAllMyTideData();
% Convert the range to water depth from the mud
disttomud = 3449; %Measured distance from the gauge to the mud.
depthFeet = (disttomud - tideRangemm) / 25.4 / 12;
[tideTime,duptimeindex] = unique(tideTime);
depthFeet = depthFeet(duptimeindex);
depthFeetNoisy = depthFeet;
% Remove outliers (could also use movmedian)
depthFeet = hampel(depthFeet,121,2);
depthFeet = hampel(depthFeet,11,1);

Wir plotten die Daten, um zu verifizieren, dass die Ausreißer und andere Abweichungen entfernt wurden (Abbildung 3).

Abbildung 3: Plot der Daten mit entferntem Rauschen und entfernten Ausreißern.

Tidenstände werden im Verhältnis zum mittleren niedrigeren Niedrigwasser (MLLW, mean lower low water) oder dem niedrigsten Stand während des Mondtages gemessen. Wir berechnen die LLW-Stände mit der findpeaks-Funktion in der Signal Processing Toolbox™.

%Invert the data to use findpeaks to find the valleys
negdepthFeet = -depthFeet;
dur = duration(15,0,0);
% Use findpeaks
[lowerLowWater,lowerLowUTC] = findpeaks(negdepthFeet,
tideTime,'MinPeakProminence',10/12,'MinPeakDistance',dur);
lowerLowWater = -lowerLowWater;
MLLWmud = mean(lowerLowWater);
MLLW = 0;
% Tide level in feet relative to MLLW
feetMLLW = (depthFeet-MLLWmud);

Wir erstellen einen Plot der niedrigeren Niedrigwasserwerte, um die Ergebnisse der Berechnung zu untersuchen (Abbildung 4).

Abbildung 4: Berechnung des mittleren niedrigeren Niedrigwassers (MLLW, mean lower low water).

Wir verwenden die bereinigten Tidendaten, um zukünftige Tidenstände mit UTide (komplexe Gezeitenanalysefunktionen, die auf File Exchange verfügbar sind) vorherzusagen. Mit UTide können wir die Phase und Amplitude der zahlreichen sinusförmigen Funktionen berechnen, die die Gezeit an einem bestimmten Ort bilden.

% Predict Tides. Downsample to avoid memory issues.
sampledTide = feetMLLW(1:15:end);
sampledTime = tideTime(1:15:end);

MashpeeLatitude = 41.6483;
% Calculate the tidal coefficients using UTide’s ut_solv function
    tideCoefWithSurge = ut_solv(datenum(sampledTime),sampledTide,[],...
    MashpeeLatitude,'auto','notrend','DiagnPlots');

% Use ut-reconstr to forecast the astronomical tides at the same times as the
% measuredtides
forecastedFeetMLLW = ut_reconstr(datenum(tideTime),tidecoefNoSurge);

% Calculate the residual error
residualFeetMLLW = feetMLLW - forecastedFeetMLLW;
residualFeetMLLWhourly = 
interp1(datenum(tideTime),residualFeetMLLW,datenum(tideTimeHourly));
residualFeetMLLWhourly = fillgaps(residualFeetMLLWhourly);

Der Vergleich der astronomischen Vorhersage und der gemessenen Daten zeigt einen Restfehler, der im Zeitverlauf variiert (Abbildung 5).

Abbildung 5: Restfehler zwischen gemessenen Gezeiten und der astronomischen Vorhersage.

Wir sehen, dass sich der Restfehler proportional zur Windstärke verhält: Während der Wind weht, wird das Wasser in die Bucht hinein- oder aus dieser herausgedrückt. Wenn der Wind stark aus bestimmten Richtungen weht, kann er den Wasserstand um bis zu 1 Fuß (0,3 Meter) anheben oder absenken (Abbildung 6).

Abbildung 6: Kreuzkorrelation des Windes mit dem Wasserstand.

Wir müssen eindeutig die Windstärke berücksichtigen. Im nächsten Abschnitt besprechen wir, wie man die Wirkung des Windes auf den Wasserstand vorhersagt.

Schritt 3: Entwickeln von prädiktiven Algorithmen

Nachdem wir die neuronalen Netzwerke Fitting und NARX mit verschiedenen Sätzen von Eingabedaten ausprobiert haben, konnten wir feststellen, dass sich die NARX-Netzwerke gut für kurzfristige Vorhersagen eignen und das Fitting-Netzwerk sowohl für kurz- als auch langfristige Vorhersagen eignet.

Eingabedaten an die neuronalen Netzwerke umfassen historischen und vorhergesagten Wind, gemessene Gezeitenstände und vorhergesagte astronomische Gezeitenstände. Wir entwickeln und testen neuronale Netzwerke unter Verwendung der Apps Neural Net Fitting und Neural Net Time, die in die Neural Network Toolbox™ integriert sind.

% Use the readNOAABuoy function to read the data from NOAA buoy 44020
% readNOAABuoy(buoyNumber,years)
[buoyTime,buoyWSPD,buoyWDIR,buoyPRES]=readNOAABuoy(44020,1);

tideTimeHourly.TimeZone = 'UTC';
windSpeedResampled = interp1(buoyTime,buoyWSPD,tideTimeHourly,'linear','extrap');
windDirResampled = interp1(buoyTime,buoyWDIR,tideTimeHourly,'linear','extrap');
windSpeedSquared = windSpeedResampled.^2;

% Prepare the data to create arrays to train a NARX neural network
tideForecastHourly = ut_reconstr(datenum(tideTimeHourly),tidecoefNoSurge);
stressN = (windSpeedResampled.^2).*cosd(windDirResampled);
stressE = (windSpeedResampled.^2).*sind(windDirResampled);
neuralInputNarx = [tideForecastHourly,stressN,stressE];
neuralOutputNarx = tideResampled - MLLWmud;

neuralInputNarxTrain = neuralInputNarx(300:4950,:);
neuralOutputNarxTrain = neuralOutputNarx(300:4950);

Wir verwenden die neuronale Netzwerk-App, um das NARX-Netzwerk zu trainieren (Abbildung 7).

Abbildung 7: Trainieren des NARX-Netzwerks mit der Neural Time Series App.

Wir verwenden die Neural-Time-Series-App, um das NARX-Netzwerk zu trainieren und den folgenden Code zu generieren:

% Solve an Autoregression Problem with External Input with a NARX Neural 
% Network
% Script generated by Neural Time Series app

X = tonndata(neuralInputNarxTrain,false,false);
T = tonndata(neuralOutputNarxTrain,false,false);

% Choose a Training Function
trainFcn = 'trainlm';  % Levenberg-Marquardt backpropagation.

% Create a Nonlinear Autoregressive Network with External Input
inputDelays = 1:24;
feedbackDelays = 1:24;
hiddenLayerSize = 9;
net = narxnet(inputDelays,feedbackDelays,hiddenLayerSize,'open',trainFcn);

% Choose Input and Feedback Pre/Post-Processing Functions
net.inputs{1}.processFcns = {'removeconstantrows','mapminmax'};
net.inputs{2}.processFcns = {'removeconstantrows','mapminmax'};

% Prepare the Data for Training and Simulation
 [x,xi,ai,t] = preparets(net,X,{},T);

% Setup Division of Data for Training, Validation, Testing
net.divideFcn = 'dividerand';  % Divide data randomly
net.divideMode = 'time';  % Divide up every sample
net.divideParam.trainRatio = 70/100;
net.divideParam.valRatio = 15/100;
net.divideParam.testRatio = 15/100;

% Choose a Performance Function
net.performFcn = 'mse';  % Mean Squared Error

% Train the Network
[net,tr] = train(net,x,t,xi,ai);
netNarx = net;

Wir verwenden die Neural-Fitting-App, um ein Feed-Forward-Netzwerk mit zwei Schichten zu trainieren.

Wir bewerten die Leistung des neuronalen Netzwerks während verstärktem Wind, indem wir die Leistung des NARX-Netzwerks mit dem Fitting-Netzwerk im Hinblick auf variierende Brandungen vergleichen (Abbildung 8).

Abbildung 8: Leistung der neuronalen Netzwerke Fitting und NARX als Funktion des Wasseranstiegs.

Wir erkennen, dass die Multi-Step-Vorhersage in NARX einen kleineren mittleren Fehler liefert als das Fitting-Netzwerk für Vorhersagen eines mittleren Anstiegs bis zu 12 Stunden im Voraus. Bei Vorhersagen von 24 oder mehr Stunden im Voraus liegt die Leistung des NARX-Netzwerks unter der des Fitting-Netzwerks.

Um die Tidenstände mit Wind für die ersten 12 Stunden vorherzusagen, verwenden wir das NARX-Netzwerk. Zwischen den Stunden 12 und 24 interpolieren wir die Ergebnisse des NARX- und Fitting-Netzwerks linear und nach 24 Stunden verwenden wir das Fitting-Netzwerk.

Wir erstellen einen Plot der Ergebnisse und sehen, dass die Vorhersagen den tatsächlichen Ständen bei verstärktem Wind entsprechen (Abbildung 9 und 10).

Abbildung 9: Der Plot zeigt, inwieweit die Vorhersage des neuronalen Netzwerks dem tatsächlichen Stand während eines Sturmwinds, der den Wasserstand anhebt, entspricht.

Abbildung 10: Der Plot zeigt, wie die Vorhersage des neuronalen Netzwerks dem tatsächlichen Stand während eines Sturmwinds entspricht, der den Wasserstand senkt.

Schritt 4: Bereitstellen von Analysen für die Cloud

Wir schreiben ein MATLAB-Skript mit den neuronalen Netzwerken Fitting und NARX und stellen es auf ThingSpeak bereit, um gemessene und vorhergesagte Tidenstände vorherzusagen und anzuzeigen (Abbildung 11).

Abbildung 11: ThingSpeak MATLAB-Visualisierungsoberfläche mit MATLAB-Code.

Schritt 5: Durchführen von bedarfsgesteuerter Datenanalyse und Visualisierung

MATLAB-Code generiert den bedarfsgesteuerten Plot der Tidenanstiegsvorhersage (Abbildung 12).

Abbildung 12: Plot, der von durch Wind beeinflussten Gezeitenvorhersagen basierend auf MATLAB Machine Learning und ThingSpeak. Die Eingaben in neuronale Netzwerke umfassen die vorhergesagte Windgeschwindigkeit und -richtung des National Weather Service, aktuelle Windgeschwindigkeit und -richtung des NOAA und die, anhand von UTide berechnete, vorhergesagte astronomische Gezeit.

Wir verwenden MATLAB-Code, um die Daten aus ThingSpeak unter Verwendung der thingSpeakRead-Funktion und aus den anderen Quellen mittels websave zu lesen. Wir kombinieren die Daten mithilfe der Timetable-Funktion und führen die neuronalen Netzwerke aus, um die Vorhersage zu generieren.

Wir haben die Option, den Plot öffentlich zur Verfügung zu stellen oder privat zu nutzen, und der Plot kann auf einfache Weise in eine benutzerdefinierte Website eingebettet werden.

Zusammenfassung

Wir haben die Prototypenentwicklung und Bereitstellung komplexer IoT-Analysen ohne Webentwicklung oder die Bereitstellung von Webinfrastruktur demonstriert. Wir sind zu dem Ergebnis gekommen, dass die Möglichkeit der Nutzung von MATLAB-Funktionen und -Tools wie Neural-Network-Toolbox-Apps den Gesamtaufwand reduziert und einem einzelnen Ingenieur die Chance bietet, ein funktionsfähiges IoT-Analysesystem zu implementieren, ohne spezialisierte Webentwicklungsfähigkeiten oder hochspezialisierte Kenntnisse über Statistik und maschinelles Lernen zu besitzen.

Der IoT-Analyse-Workflow lässt sich einfach auf andere Anwendungen für Datenanalyse und maschinelles Lernen, wie z. B. vorausschauende Wartung oder Stromlastvorhersagen, anwenden.

Veröffentlicht 2016


Artikel für verwandte Branchen anzeigen