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.
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).
Wir führen den Workflow zur Entwicklung des Systems in den folgenden fünf Schritten durch:
- Historische Daten sammeln
- Daten analysieren
- Vorhersagealgorithmen entwickeln
- Analyse in der Cloud bereitstellen
- 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).
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).
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).
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).
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 Deep Learning 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).
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).
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).
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).
Schritt 5: Durchführen von bedarfsgesteuerter Datenanalyse und Visualisierung
MATLAB-Code generiert den bedarfsgesteuerten Plot der Tidenanstiegsvorhersage (Abbildung 12).
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 - 93072v00
Eingesetzte Produkte
Weitere Informationen
-
„UTide“ Einheitliche Gezeitenanalyse- und Vorhersagefunktionen (Herunterladen)