TensorFlow-gevoede IoT Weerstation Voorspelt Nauwkeurig Regenintensiteit
Onderdelen en benodigdheden
| DFRobot Weerstation Kit met Anemometer/Windvaan/Regenemmer | × | 1 |
| NodeMCU ESP8266 Breakout Board (ESP-12E) | × | 1 |
| DFRobot SIM808 GPS/GPRS/GSM Shield voor Arduino | × | 1 |
| Arduino UNO | × | 1 |
| Raspberry Pi 3 Model B+ | × | 1 |
| Raspberry Pi 4 Model B | × | 1 |
| SparkFun Soldeerbaar Breadboard - Mini | × | 2 |
Benodigde tools en machines
- Lijmpistool
Apps en online diensten
- Arduino IDE
- TensorFlow
- Microsoft Visual Studio 2017
Over dit project
Vooral in 2020 hebben plotselinge zware en gewelddadige regenval schadelijke effecten gehad op kassen en gewasopbrengsten in mijn land. Helaas komen onverwachte en extreme regenval vaker voor en zijn relatief algemeen geworden door klimaatverandering in sommige gebieden. Tegenovergesteld lijden andere regio's onder droogte. Naarmate 2020 voorbijging, werden meer dan dertig incidenten vastgelegd die verlies van gewassen en vee door zware regenval veroorzaakten in mijn regio. Om bij te dragen aan een oplossing om dergelijke problemen te voorkomen, besloot ik dit project als uitgangspunt te nemen.
Hoofdzakelijk richt ik me op effecten van extreme regenval op landbouw. Echter, extreme regenval kan talloze gevaren veroorzaken, bijvoorbeeld:
- overstromingen, met risico op menselijke levens
- schade aan gebouwen en infrastructuur
- verlies van gewassen en vee
- aardverschuivingen, die levens bedreigen, transport en communicatie verstoren
Zoals recent onderzoek aantoont, kan extreme regenval gewasproductiviteit op verschillende manieren beïnvloeden: direct fysieke schade, uitgestelde zaait/oogst, beperkte wortelgroei, zuurstoftekort, voedingsstofverlies. Te veel regen kan net zo gevaarlijk zijn als droogte voor landbouw: "Data uit de afgelopen drie decennia suggereren dat extreme regenval gewasopbrengest net zo kan beïnvloeden als extreme hitte en droogte. Een nieuw onderzoek van een interdisciplinair team van de Universiteit van Illinois koppelde gewasverzekering, klimaat, grond en maïsopbrengstdata van 1981 tot 2016. De studie vond dat extreme regenval in sommige jaren de VS maïsopbrengst met maximaal 34% deed dalen ten opzichte van de verwachte opbrengst. Data suggereren dat droogte en extreme hitte een opbrengstdaling van maximaal 37% veroorzaakten in sommige jaren [2]".
Helaas zijn vroege waarschuwingsystemen niet voldoende om de verergerende effecten van extreme regenval op landbouwproducten en -processen volledig te voorkomen zonder adequate en voorlopige lokale weergegevens voor elke kas of boerderij. Daarom, in de hoop de nadelige effecten van extreme regenval op landbouw te voorkomen, besloot ik dit project te maken als een budgetvriendelijk extern weerstation om lokale weerinformatie te verzamelen en te interpreteren voor nauwkeurigere voorspellingen van regenintensiteit.
Na onderzoek naar deep learning en neurale netwerken, besloot ik een kunstmatig neuraal netwerk (ANN) op basis van een classificatiemodel te bouwen om de geaccumuleerde lokale weergegevens te interpreteren en de regenintensiteit te voorspellen volgens gegeven klassen. Zoals de volgende studie aangeeft, hebben onderzoekers verschillende neurale netwerkmodellen en -typen toegepast om niet alleen regenval maar ook weersverschijnselen te voorspellen: "Veel experimenten hebben neurale netwerken gebruikt om kwantitatieve regenhoeveelheden op verschillende locaties en kijktijden te voorspellen. Onderzoekers in Thailand konnten hoog nauwkeurige voorspellingen verkrijgen met feed-forward neurale netwerken voor kwantitatieve regenhoeveelheden in het 1- tot 3-uurs kijktijdsbereik om mogelijke overstromingsgevaren te voorspellen. Neurale netwerken zijn ook gebruikt om weersverschijnselen te voorspellen naast traditionele voorspelwaarden, zoals kans/hoeveelheid regenval, windsnelheid, barometrische druk, etc. Ze zijn met succes gebruikt om tornado's te voorspellen. Daarnaast gebruikten onderzoekers in Australië met succes een neuraal netwerk om mist te identificeren bij verschillende voorspelbereiken van 3 tot 18 uur rondom Canberra International Airport [3]."
Voordat ik mijn neurale netwerkmodel bouwde en testte, had ik weergegevens verzameld op mijn balkon en achtertuin in een straal van drie kilometer gedurende meer dan drie maanden om een lokale weerdataset te creëren. Om weerinformatie te kunnen verzamelen zelfs in extreme weersomstandigheden, gebruikte ik een Weerstation Kit met Anemometer, Windvaan en Regenemmer van DFRobot met twee verschillende development boards:
- NodeMCU ESP-12E (WiFi-ingeschakeld)
- Arduino Uno + DFRobot SIM808 GPS/GPRS/GSM Shield (GPRS-ingeschakeld)
Dus kon ik weergegevens via WiFi op mijn balkon of via GPRS versturen als de afstand tot mijn router te ver was.
Ik besloot Google Sheets, een cloud-gebaseerd spreadsheetprogramma, te gebruiken om weergegevens te verzamelen omdat het maken van grote datasets en het toevoegen van nieuwe informatie eenvoudig is met de Google Sheets API. Daarom ontwikkelde ik een webapplicatie in PHP om weergegevens die door de development boards worden verzonden op te halen en toe te voegen aan een spreadsheet op Google Sheets.
Na het verzamelen van weergegevens gedurende meer dan drie maanden elke vijf minuten, bouwde ik een kunstmatig neuraal netwerk (ANN) model met TensorFlow om voorspellingen te doen over de regenintensiteit. Theoretisch wees ik een regenintensiteitsklasse toe aan elke meting na schalen en normaliseren van de dataset. Vervolgens trainde ik het neurale netwerkmodel om deze klassen te classificeren:
- Geen Regenval
- Lichte Regenval
- Matige Regenval
- Zware Regenval
- Gewelddadige Regenval
Dit is mijn project in een notendop 😃
In de volgende stappen vind je gedetailleerde informatie over coderen, lokale weergegevensverzameling en het bouwen van een ANN-model met TensorFlow.
Grote dank aan DFRobot voor het sponsoren van dit project.
Gesponsorde producten door DFRobot:
- ⭐ Weerstation Kit met Anemometer/Windvaan/Regenemmer
- ⭐ SIM808 GPS/GPRS/GSM Shield voor Arduino
Stap 1: Het weerstationkit samenstellen met anemometer, windvaan en regenemmer
Deze weerstationkit bevat een anemometer, windvaan, regenemmer en een sensorbord om weergegevens via het seriële communicatieprotocol te versturen. Het is dus makkelijk te gebruiken met development boards voor lokale data-verzameling.
Het stuurt 37 bytes per seconde uit, inclusief eind CR/LF.
c000s000g000t086r000p000h53b10020
Data Parser:
- c000: windrichting, graden
- s000: windsnelheid (gemiddelde), 0.1 mijl per uur
- g000: windsnelheid (max), 0.1 mijl per uur
- t086: temperatuur, Fahrenheit
- r000: regenval (1 uur), 0.01 inch
- p000: regenval (24 uur), 0.01 inch
- h53: vochtigheid, % (00% = 100)
- b10020: atmosferische druk, 0.1 hPa
⭐ Bevestig de anemometer en windvaan aan de brug met schroeven en moeren.
⭐ Verbind de windvaan met de anemometer via de RJ11-telefoondraad en bevestig het onder de brug.
⭐ Monteer de roestvrij staalstaaf aan de brug met schroeven.
⭐ Installeer de regenemmer-verbinding onder de regenemmer met schroeven.
⭐ Plaats de regenemmer op de roestvrij staalstaaf met schroeven en moeren.
⭐ Nu is het klaar om weergegevens te verzamelen zelfs in extreme omstandigheden. Echter, het sensor-(converter)bord is niet weerbestendig, dus ik voegde een plastic doos toe aan het weerstation om het sensorbord en de SIM808-shield te beschermen.
Stap 2: Weergegevens verzamelen op Google Sheets
Om informatie naar een spreadsheet op Google Sheets te sturen, moet je een nieuwe applicatie maken in de Google Developer Console en verificatiecredentials verkrijgen voor de Google Sheets API. Als je nieuw bent in het maken van applicaties met de Google Developer Console, volg de onderstaande instructies.
⭐ Ga naar Google Developer Console en klik op 'NIEUW PROJECT'. Voer projectnaam in als Remote Weather Station.
⭐ Ga naar APIs & Services en klik op de API-bibliotheek om de Google Sheets API in te schakelen.
Stap 2.1: Credentials verkrijgen voor Google Sheets API
⭐ Open het projectdashboard en klik op Credentials. Vul het formulier in om het serviceaccount en de sleutel te maken.
⭐ Klik op CREATE CREDENTIALS en configureer het toestemmingsscherm om een OAuth-client-ID te kunnen maken.
⭐ Maak een nieuwe OAuth-client-ID genaamd Client onder Desktop app (applicatietype).
⭐ Na het maken van de OAuth-client-ID (Client), download de credentials (ID en Secret) en noem het bestand credentials.json.
Stap 2.2: Een spreadsheet maken op Google Sheets
⭐ Ga naar Google Sheets en selecteer Personal.
⭐ Maak een Blank spreadsheet en noem het Remote Weather Station.
⭐ Definieer de kolomnamen als eerste rij:
- WD (Windrichting)
- Av_WS (Gemiddelde windsnelheid)
- Mx_WS (Maximale windsnelheid)
- 1h_RF (1-uur regenval)
- 24h_RF (24-uur regenval)
- Tem (Temperatuur)
- Hum (Vochtigheid)
- b_PR (Barometrische druk)
⭐ Optioneel: pas een grafiek aan om de verzamelde data te inspecteren.
Stap 3: Een webapplicatie in PHP ontwikkelen om weergegevens toe te voegen aan de spreadsheet
Deze PHP-webapplicatie haalt weergegevens op die door de development boards (ESP8266 en SIM808) via een HTTP GET-verzoek worden verstuurd, en voegt die data toe aan een gegeven spreadsheet (via ID) op Google Sheets met geverifieerde credentials en token.
De webapplicatie vereist de Google Client Library voor PHP.
⭐ Maak een map remote_weather_station op je server en installeer de Google Client Library voor PHP daarin.
De map moet deze vier bestanden bevatten naast de library:
- index.php
- account_verification_token.php
- credentials.json (uit Stap 2.1)
- token.json (uit Stap 3.1)
index.php
⭐ Haal lokale weergegevens op via GET-verzoek:
// Windrichting (wd), Gem. windsnelheid (a_ws), Max windsnelheid (m_ws), 1u regen (1_rf), 24u regen (24_rf), Temp (tem), Vocht (hum), Druk (b_pr)
$variables_from_module;
if(isset($_GET['wd']) && isset($_GET['a_ws']) && isset($_GET['m_ws']) && isset($_GET['1_rf']) && isset($_GET['24_rf']) && isset($_GET['tem']) && isset($_GET['hum']) && isset($_GET['b_pr'])){
$variables_from_module = [
"wd" => (int)$_GET['wd'],
"a_ws" => (float)$_GET['a_ws'],
"m_ws" => (float)$_GET['m_ws'],
"1_rf" => (float)$_GET['1_rf'],
"24_rf" => (float)$_GET['24_rf'],
"tem" => (float)$_GET['tem'],
"hum" => (int)$_GET['hum'],
"b_pr" => (float)$_GET['b_pr']
];
}else{
$variables_from_module = [
"wd" => "err", "a_ws" => "err", "m_ws" => "err", "1_rf" => "err",
"24_rf" => "err", "tem" => "err", "hum" => "err", "b_pr" => "err"
];
}
⭐ Verbinden met Google Developer Console applicatie Remote Weather Station via credentials.json.
$client = new Google_Client();
$client->setApplicationName('Remote Weather Station');
$client->setScopes('https://www.googleapis.com/auth/spreadsheets');
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
⭐ Laad eerder geautoriseerd token uit token.json als het bestaat.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
print("Token Found!");
}
⭐ Als er geen token is of het verlopen is, vraag autorisatie en stel verificatiecode in om token.json te maken.
if ($client->isAccessTokenExpired()) {
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
$authUrl = $client->createAuthUrl();
$authCode = trim($GLOBALS['account_verification_token']);
// ... verificatiecode uitwisselen voor accesstoken ...
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
}
⭐ Voer spreadsheet ID en bereik in om recente metingen toe te voegen.
$spreadsheetId = '';
$range = 'A1:H1';
$values = [[$variables_from_module["wd"], $variables_from_module["a_ws"], $variables_from_module["m_ws"], $variables_from_module["1_rf"], $variables_from_module["24_rf"], $variables_from_module["tem"], $variables_from_module["hum"], $variables_from_module["b_pr"]]];
$body = new Google_Service_Sheets_ValueRange(['values' => $values]);
$params = ['valueInputOption' => "RAW"];
$result = $service->spreadsheets_values->append($spreadsheetId, $range, $body, $params);
printf("
%d cells appended.", $result->getUpdates()->getUpdatedCells());
account_verification_token.php
⭐ Na autorisatie via de gegenereerde AuthUrl, voer de verificatiecode in om een accesstoken in te stellen.
$account_verification_token = "";
Stap 3.1: Webapplicatie instellen op Raspberry Pi (of elke server)
Na het maken van de PHP-webapplicatie, besloot ik hem op mijn Raspberry Pi te draaien, maar je kunt hem op elke PHP-server draaien.
⭐ Verplaats de applicatiemap naar de Apache-server (/var/www/html) via terminal.
sudo mv /home/pi/Downloads/remote_weather_station /var/www/html/
⭐ De webapplicatie geeft een fout bij eerste openen door ontbrekende verificatiecode. Ga naar de gegenereerde autorisatielink.
⭐ Klik op Go to Remote Weather Station (unsafe).
⭐ Geef de applicatie de vereiste machtigingen.
⭐ Kopieer de verificatiecode en plak in account_verification_token.php.
⭐ Terug naar de webapplicatie: moet Successful! Refresh the page tonen.
⭐ Na verfrissen gebruikt de applicatie de code om een accesstoken op te halen en op te slaan in token.json. Geen fout meer.
⭐ Test of de applicatie data correct toevoegt: https://localhost/remote_weather_station/?wd=12&a_ws=8&m_ws=11&1_rf=14&24_rf=84&tem=24&hum=32&b_pr=57
Stap 4: Weergegevens lezen en versturen met ESP8266 (WiFi)
Om data op mijn balkon te verzamelen, gebruikte ik een NodeMCU ESP-12E (ESP8266) met het weerstation. Geprogrammeerd om elke 5 minuten data naar de PHP-webapplicatie te sturen.
⭐ Benodigde libraries includeren en WiFi-instellingen definiëren.
#include
#include
#include
#include
#include
const char *ssid = "";
const char *password = "";
⭐ Weerstation-instellingen en seriële verbindingspinnen (D6, D5) definiëren.
char databuffer[35];
double temp;
int transferring = 0;
SoftwareSerial Serial_1(D6, D5); // (Rx, Tx)
⭐ In getBuffer() data ophalen van het weerstation.
void getBuffer(){
int index;
for (index = 0; index < 35; index++){
if(Serial_1.available()){
databuffer[index] = Serial_1.read();
if (databuffer[0] != 'c'){ index = -1; }
} else { index--; }
}
}
⭐ Debug data en maak de link aan.
String weather_data = "wd=" + String(WindDirection()) + "&a_ws=" + String(WindSpeedAverage()) + "&m_ws=" + String(WindSpeedMax()) + "&1_rf=" + String(RainfallOneHour()) + "&24_rf=" + String(RainfallOneDay()) + "&tem=" + String(Temperature()) + "&hum=" + String(Humidity()) + "&b_pr=" + String(BarPressure());
String server = "https://192.168.1.24/remote_weather_station/?";
int WindDirection(){ return transCharToInt(databuffer,1,3); }
float WindSpeedAverage(){ temp = 0.44704 * transCharToInt(databuffer,5,7); return temp; }
float WindSpeedMax(){ temp = 0.44704 * transCharToInt(databuffer,9,11); return temp; }
float Temperature(){ temp = (transCharToInt(databuffer,13,15) - 32.00) * 5.00 / 9.00; return temp; }
float RainfallOneHour(){ temp = transCharToInt(databuffer,17,19) * 25.40 * 0.01; return temp; }
float RainfallOneDay(){ temp = transCharToInt(databuffer,21,23) * 25.40 * 0.01; return temp; }
int Humidity(){ return transCharToInt(databuffer,25,26); }
float BarPressure(){ temp = transCharToInt(databuffer,28,32); return temp / 10.00; }
⭐ Data pakketten elke 5 minuten versturen naar Raspberry Pi (of server).
transferring++;
if(transferring == 5*60){
HTTPClient http;
http.begin(server + weather_data);
int httpCode = http.GET();
String payload = http.getString();
Serial.println("Data Send...\nHTTP Code => " + String(httpCode) + "\nServer Response => " + payload + "\n\n");
http.end();
transferring = 0;
}
delay(1000);
Na uploaden toont de seriële monitor elke seconde weergegevens en verstuurt pakketten elke 5 minuten. Serverrespons toont "Token Found!" en "8 cells appended."
Stap 4.1: Weergegevens lezen en versturen met SIM808 (GPRS)
Voor data in mijn achtertuin (te ver van router), gebruikte ik een SIM808-shield voor Arduino Uno. Meeste code is hetzelfde als vorige stap, behalve de onderdelen hieronder.
⭐ Benodigde libraries en sim808-object definiëren.
#include
#include
DFRobot_SIM808 sim808(&Serial);
⭐ SIM808-module initialiseren.
while(!sim808.init()) { delay(1000); Serial.print("Sim808 init error\r\n"); }
delay(2000);
Serial.println("Sim808 init success");
delay(5000);
⭐ Data pakketten elke 5 minuten versturen via TCP-verbinding en HTTP GET-request.
if(transferring == 5*60){
while(!sim808.join(F("cmnet"))) { Serial.println("Sim808 join network error!"); delay(2000); }
delay(5000); Serial.println("Successful DHCP");
if(!sim808.connect(TCP,"192.168.1.24", 80)) { Serial.println("Connection Error"); }
else { Serial.println("Connection OK"); }
delay(2000);
String line = "GET /remote_weather_station/?" + weather_data_1 + weather_data_2 + weather_data_3 + " HTTP/1.0\r\n\r\n";
char buffer[512];
char web_hook[110];
String_to_Char(line, 110, web_hook);
sim808.send(web_hook, sizeof(web_hook)-1);
while (true) {
int ret = sim808.recv(buffer, sizeof(buffer)-1);
if (ret <= 0){ Serial.println("Fetch Over..."); break; }
Serial.println("\nData Send"); break;
}
sim808.close(); sim808.disconnect(); transferring = 0;
}
Stap 4.2: Weerdataset aanmaken voor meer dan drie maanden
Na coderen, begon ik weergegevens op Google Sheets te verzamelen elke 5 minuten gedurende meer dan 3 maanden.
Verzamelde Weergegevens:
- Windrichting (graden)
- Gemiddelde windsnelheid (m/s)
- Maximale windsnelheid (m/s)
- 1-uur regenval (mm)
- 24-uur regenval (mm)
- Temperatuur (°C)
- Vochtigheid (%)
- Barometrische druk (hPa)
Spreadsheet gedownload als Remote Weather Station.csv met 32.219 rijen als voorlopige dataset. Nog steeds data verzamelen om model te verbeteren :)
Stap 5: Een Kunstmatig Neuraal Netwerk (ANN) bouwen met TensorFlow
Na het verzamelen van de voorlopige dataset, werkte ik aan het ANN-model voor regenintensiteitsvoorspelling.
Besloten om model in Python met TensorFlow te maken. Stappen voor beter begrip van data:
- Datavisualisatie
- Data Schalen (Normaliseren)
- Data Preprocessing
- Data Splitsen
Besloten om model te gebruiken om verschillende regenintensiteitsklassen te classificeren (theoretisch toegewezen als labels). Klassen gebaseerd op neerslagsintensiteit:
- Lichte regen — neerslag < 2.5 mm/uur
- Matige regen — 2.5 tot 7.6 mm/uur
- Zware regen — 7.6 tot 50 mm/uur
- Gewelddadige regen — > 50 mm/uur
Volgens neerslagpercentages, preprocessing om elke invoer een van vijf klassen toe te wijzen:
- 0 (Geen)
- 1 (Lichte Regen)
- 2 (Matige Regen)
- 3 (Zware Regen)
- 4 (Gewelddadige Regen)
Na schalen en preprocessing: 7 invoervariabelen en 1 label per meting, geclassificeerd in 5 klassen. ANN-model met TensorFlow gebouwd voor beste resultaten.
Lagen:
- 7 [Input]
- 16 [Verborgen]
- 32 [Verborgen]
- 64 [Verborgen]
- 128 [Verborgen]
- 5 [Output]
Stap 5.1: Visualiseren en Schalen (Normaliseren) van Weergegevens
Belangrijk om data te begrijpen voordat model bouw. Visualiseren en schalen in Python.
⭐ Weerdata inlezen uit Remote Weather Station.csv.
csv_path = "E:\\PYTHON\\Remote Weather Station.csv"
df = pd.read_csv(csv_path)
⭐ In graphics() functie, gevraagde kolommen visualiseren met Matplotlib.
def graphics(self, column_1, column_2, xlabel, ylabel):
plt.style.use("dark_background")
plt.gcf().canvas.set_window_title('IoT Weather Station')
plt.hist2d(self.df[column_1], self.df[column_2])
plt.colorbar()
plt.xlabel(xlabel); plt.ylabel(ylabel); plt.title(xlabel); plt.show()
⭐ In data_visualization() alle kolommen inspecteren voor modelbouw.
def data_visualization(self):
self.graphics('WD', '1h_RF', 'Windrichting (deg)', '1-uur Regenval (mm)')
self.graphics('Av_WS', '1h_RF', 'Gem. Windsnelheid (m/s)', '1-uur Regenval (mm)')
self.graphics('Mx_WS', '1h_RF', 'Max Windsnelheid (m/s)', '1-uur Regenval (mm)')
self.graphics('24h_RF', '1h_RF', '24-uur Regenval (mm)', '1-uur Regenval (mm)')
self.graphics('Tem', '1h_RF', 'Temperatuur (°C)', '1-uur Regenval (mm)')
self.graphics('Hum', '1h_RF', 'Vochtigheid (%)', '1-uur Regenval (mm)')
self.graphics('b_PR', '1h_RF', 'Barometrische Druk (hPA)', '1-uur Regenval (mm)')
Na visualiseren, elke kolom schalen voor correcte formatting.
Normaal zag elke rij er zo uit voor schaling: 315, 0.45, 0, 0.51, 0.51, 22.78, 65, 1005.5
⭐ In scale_data():
Windrichting in graden/hoeken maken geen goede model-inputs. 360° en 0° moeten dichtbij elkaar zijn en soepel omwikkelen. Richting mag niet uitmaken als wind niet waait. Converteer windrichting en snelheid kolommen naar windvector voor eenvoudige neurale netwerk-interpretatie.
def scale_data(self):
wv = self.df.pop('Av_WS')
max_wv = self.df.pop('Mx_WS')
wd_rad = self.df.pop('WD') * np.pi / 180
self.df['scaled_WX'] = wv * np.cos(wd_rad)
self.df['scaled_WY'] = wv * np.sin(wd_rad)
self.df['scaled_max_WX'] = max_wv * np.cos(wd_rad)
self.df['scaled_max_WY'] = max_wv * np.sin(wd_rad)
// Overige kolommen (behalve 1h_RF) delen door gemiddelde waarde:
tem = self.df.pop('Tem'); self.df['scaled_Tem'] = tem / 25
hum = self.df.pop('Hum'); self.df['scaled_Hum'] = hum / 70
bPR = self.df.pop('b_PR'); self.df["scaled_bPR"] = bPR / 1013
rain_24 = self.df.pop('24h_RF'); self.df['scaled_24h_RF'] = rain_24 / 24
Nieuwe gekolommen: scaled_WX, scaled_WY, scaled_max_WX, scaled_max_WY, scaled_Tem, scaled_Hum, scaled_bPR, scaled_24h_RF.
Stap 5.2: Model (ANN) trainen op regenintensiteitsklassen
Voor neurale netwerk in TensorFlow, input-array en label-array maken door preprocessing van geschaalde data.
⭐ In create_input_and_label():
Elk input-element als NumPy-array toevoegen aan input-array. Elk input-element heeft 7 variabelen [shape=(7,)]: [scaled_WX, scaled_WY, scaled_max_WX, scaled_max_WY, scaled_Tem, scaled_Hum, scaled_bPR]
def create_input_and_label(self):
n = len(self.df)
for i in range(n):
self.input.append(np.array([self.df['scaled_WX'][i], self.df['scaled_WY'][i], self.df['scaled_max_WX'][i], self.df['scaled_max_WY'][i], self.df['scaled_Tem'][i], self.df['scaled_Hum'][i], self.df['scaled_bPR'][i]]))
self.input = np.asarray(self.input)
// Ongeveer regenrate bepalen: approx_RF_rate = (1h_RF + scaled_24h_RF) * 100
// Klasse toewijzen [0-4] op basis van regenrate
for i in range(n):
_class = 0
approx_RF_rate = (self.df['1h_RF'][i] + self.df['scaled_24h_RF'][i]) * 100
if approx_RF_rate == 0: _class = 0
elif approx_RF_rate < 2.5: _class = 1
elif 2.5 < approx_RF_rate && approx_RF_rate < 7.6: _class = 2
elif 7.6 < approx_RF_rate && approx_RF_rate < 50: _class = 3
else: _class = 4
self.label.append(_class)
self.label = np.asarray(self.label)
Data splitsen: training (60%) en test (40%).
def split_data(self):
n = len(self.df)
self.train_input = self.input[0:int(n*0.6)]
self.test_input = self.input[int(n*0.6):]
self.train_label = self.label[0:int(n*0.6)]
self.test_label = self.label[int(n*0.6):]
ANN-model bouwen met Keras en trainen met training-data voor 19 epochs.
def build_and_train_model(self):
self.model = keras.Sequential([
keras.Input(shape=(7,)),
keras.layers.Dense(16, activation='relu'),
keras.layers.Dense(32, activation='relu'),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(5, activation='softmax')
])
self.model.compile(optimizer='adam', loss="sparse_categorical_crossentropy", metrics=['accuracy'])
self.model.fit(self.train_input, self.train_label, epochs=19)
// Test nauwkeurigheid:
print("\n\nModel Evaluation:")
test_loss, test_acc = self.model.evaluate(self.test_input, self.test_label)
print("Evaluated Accuracy: ", test_acc)
Na training met voorlopige data: modelnauwkeurigheid tussen 0.83 en 0.85.
Stap 5.3: Model evalueren en voorspellingen doen over regenintensiteit
Model getest met voorlopige testdata. Geëvalueerde nauwkeurigheid tussen 0.72 en 0.73 door onvoldoende testdata (overfitting). Nog steeds data verzamelen voor verbetering.
Model voorspelt mogelijkheden van labels voor elk input-element als array van 5 getallen (vertrouwen per klasse).
⭐ In make_prediction(), voorspelling maken voor gegeven array en meest nauwkeurig label tonen via argmax().
def make_prediction(self, pre_array):
print("\n\nModel Predictions:\n")
prediction = self.model.predict(pre_array)
for i in range(len(pre_array)):
print("Prediction => ", self.class_names[np.argmax(prediction[i])])
Voorspellingsinputs & outputs:
- [0, 0, 0.318, 0.318, 0.699, 0.815, 0.993] → 0 [Geen]
- [0, -0, 0, -0, 0.844, 1, 0.968] → 3 [Zware Regen]
- [0, 0, 0.45, 0, 0.876, 0.959, 1.001] → 4 [Gewelddadige Regen]
- [-0, -0, -0, -0, 0.822, 1.057, 0.993] → 4 [Gewelddadige Regen]
Aansluitingen en Instellingen (ESP8266 / SIM808)
Gedetailleerde pin-uitgangen voor beide configuraties in het originele project. Let op: SIM808 vereist externe batterij (7-23V), GPS/GSM-antennes, SIM-kaart, functieswitch op "None" (1) voor upload, daarna "Arduino" (3).
Video's en Conclusie
Na coderen en samenstellen, lokale weergegevens verzameld gedurende >3 maanden elke 5 minuten. Model succesvol gebouwd. Nog steeds data verzamelen op balkon en achtertuin voor verbetering :)
Verdere Discussies
☔ 💧 Budgetvriendelijke NN-ingeschakelde weerstations op boerderijen/kassen kunnen plaatselijke regenintensiteit voorspellen om landbouwschade te voorkomen.
☔ 💧 Als vroege waarschuwingsystemen met neurale netwerken, kunnen ze als een zwerm communiceren en elkaar voeden voor nauwkeurige lokale voorspellingen.
☔ 💧 Informatie bruikbaar voor: vitale waterbronnen, landbouw, gewasproductiviteit, ecosystemen, hydrologie.
Referenties
- Extreme weather - heavy rainfall, NIWA, https://niwa.co.nz/natural-hazards/extreme-weather-heavy-rainfall
- University of Illinois at Urbana-Champaign, News Bureau. "Excessive rainfall as damaging to corn yield as extreme heat, drought." ScienceDaily, 30 April 2019.
- Andrew Culclasure, Using Neural Networks to Provide Local Weather Forecasts, Georgia Southern University, Spring 2013.
Code
Volledige codebestanden beschikbaar in het project:
- IoT_weather_station_neural_network.py (Python)
- ESP12E_remote_weather_station.ino (Arduino)
- SIM808_remote_weather_station.ino (Arduino)
- index.php (webapplicatie)
- account_verification_token.php (webapplicatie)
Zie GitHub-repository voor complete bestanden.
Schema's
Schema-afbeeldingen beschikbaar in origineel project.
Productieproces
- DIY Zonne-energie Weerstation Met Raspberry Pi
- Een buitenweerstation bouwen met Raspberry Pi 2 en ADS-WS1
- Een Raspberry Pi-weerstation bouwen dat dagelijkse weergegevens e-mailt
- Beginner IoT-tutorial: Temperatuurdata streamen vanaf een Raspberry Pi
- Externe weerbewaking met Raspberry Pi 3 en PubNub
- Uw weerstation integreren met CWOP: Een praktische gids
- IoT Bouwen met Java ME 8 op Raspberry Pi: Deel 1 – GPIO-sensorintegratie
- Raspberry Pi 3 verbinden met DHT11-sensor en data uploaden naar ThingsIo.ai-cloud
- Adafruit 10DOF IMU-data van Raspberry Pi 2 naar Azure Event Hubs Sturen met Windows 10 IoT Core
- Geavanceerd Weerstation v2.0: Real-time Temperatuur, Druk, Vochtigheid & Hoogte Monitoring
- Windows 10 IoT Core Installeren op Raspberry Pi 3 Model B+: Stap-voor-stap Handleiding