Bewerben Sie sich für unsere neuen Teilzeit-Kohorten Data Science & AI und Cybersecurity

Niederschlags-Nowcasting mit maschinellem Lernen

ML
DL
CNN
Wettervorhersage
UNet
Niederschlags-Nowcasting mit maschinellem Lernen cover image

Heutzutage schätzen Meteorologen, dass 90 % der Wettervorhersagen innerhalb von fünf Tagen korrekt sind. Die getroffenen Vorhersagen basieren normalerweise auf zwei verschiedenen Methoden:

  1. Physikbasierte Ansätze: Bei diesen Ansätzen werden Modelle verwendet, die messbare Größen wie Druck, Wolkenbewegung, Himmelsbedingungen usw. integrieren. Solche Modelle eignen sich gut für die Vorhersage des Wetters für die kommenden Tage oder Wochen.

  2. Physikfreie (datenbasierte) Ansätze: Diese Ansätze nutzen historische Daten, um Modelle zu erstellen, die Vorhersagen treffen können. Solche Modelle zeigen gute Ergebnisse bei der Vorhersage des Wetters für bis zu 6 Stunden, dem sogenannten Weather Nowcasting.

In diesem Artikel werden wir die zweite Kategorie von Ansätzen diskutieren. Wir werden die verschiedenen Formate von Wetterdaten diskutieren, wie maschinelles Lernen für die Wettervorhersage genutzt werden kann und wie die entwickelten Architekturen bei der Lösung ähnlicher Probleme hilfreich sein können.

Daten zur Klimavorhersage

Da die physikfreien Ansätze historische Daten verwenden, schauen wir uns zunächst die verfügbaren Daten an.

Wir werden zwei Hauptdatenquellen verwenden:

  1. Bilddaten: Bei diesen Daten handelt es sich um Radar- oder Satellitenbilder eines bestimmten geografischen Gebiets. Es dient zur Vorhersage von Niederschlag, Windbewegung oder Luftfeuchtigkeit.

Satellitenbild

  1. Tabellarische Daten: Bei diesen Daten handelt es sich um Aufzeichnungen messbarer Größen wie Temperatur, Luftfeuchtigkeit oder Windgeschwindigkeit.

Tabellarische Daten

Während beide Datenquellen wichtig sind, um leistungsstarke Modelle zu erstellen, konzentrieren wir uns aus Gründen der Einfachheit auf erstere (Bilddaten, die von Radargeräten oder Satelliten gesammelt wurden). Die am häufigsten verwendeten Modelle mit Bilddaten sind Convolutional Neural Networks (CNNs ).

Im Anschluss an diese Arbeit werden wir eine U-Net-Architektur verwenden, um unser eigenes Nowcasting-Modell zu erstellen.

Die Architektur

Aus vielen Gründen ist es hilfreich, von einer bestehenden Architektur auszugehen, darunter:

Architekturen dienen als Richtlinien für die Erstellung neuer Modelle. Menschen, die neue Architekturen erstellen, verfolgen einen Versuch-und-Irrtum-Ansatz, um zu ihren endgültigen Ergebnissen zu gelangen. Durch die Wiederverwendung ihrer Endergebnisse können wir viel Zeit sparen.

Vorgefertigte Modelle stehen in der Regel für den sofortigen Einsatz zur Verfügung. Wenn Forscher ihre neuen Architekturen veröffentlichen, veröffentlichen sie normalerweise auch die trainierten Parameter, sodass Benutzer sich nicht die Mühe machen müssen, von Grund auf zu trainieren/optimieren. Dies ist besonders nützlich für sehr große, ressourcenhungrige Modelle.

Beispiele berühmter Vision-Architekturen sind:

  • LeNet (60.000 Parameter)

LeNet

  • AlexNet (60m Parameter)

AlexNet

  • VGG-16 (138 m Parameter)

VGG-16

U-Net

U-Net ist eine Architektur, die auf einem vollständig Faltungsnetzwerk basiert, was bedeutet, dass es keine vollständig verbundenen Schichten hat. Es wurde erstmals für eine medizinische Bildsegmentierungsaufgabe eingeführt. Diese Ergebnisse inspirierten Forscher dazu, es auf andere Aufgaben im Bereich Computer Vision auszudehnen.

Im Jahr 2019 verwendete Google eine U-Net-basierte Architektur, um ein Niederschlagsvorhersagemodell zu erstellen.

Der Name „U-Net“ kommt von der „U“-Form seiner Architektur.

U-net-Architektur

Wir identifizieren drei Hauptkomponenten:

  1. Kontraktion/Encoder: Abfolge von Faltungs-/Pooling-Schichten, die das Eingabebild in eine kleinere Darstellung komprimieren.

  2. Brücke/Engpass: Der untere Teil des „U“ verbindet den Encoder mit dem Decoder. Es wird durch eine Reihe von Faltungsoperationen gebildet.

  3. Dekontrahierung / Decoder: Aufeinanderfolge von Aufwärtsfaltungen und Faltungsschichten, die die Ausgabe des Engpasses „dekomprimieren“.

Die Architektur eines U-Net ähnelt bisher einem Auto-Encoder. Der Unterschied liegt jedoch in der Informationsübertragung zwischen Encoder und Decoder. Diese Informationen werden weitergegeben, indem die Ergebnisse der Faltungen des Encoders mit denen der Aufwärtsfaltung des Decoders verkettet werden. Diese Änderung erhöht die Auflösung und ermöglicht dem Modell eine räumlich präzisere Ausgabe (die Position der Pixel in der Ausgabe wird präziser, wodurch ein Problem gelöst wird, das bei Modellen ohne Verkettung auftrat). Die Verkettung erfolgt symmetrisch.

Aufbau eines U-Net-Modells für Niederschlags-Nowcasting

In diesem Abschnitt erstellen wir ein U-Net-Modell, um das Wetter anhand von Satellitenbildern vorherzusagen. Wir werden ein vorab trainiertes Modell namens Rain-Net verwenden.

Der folgende Code ist in diesem colab verfügbar.

Wir installieren zunächst wradlib, eine Open-Source-Bibliothek für die Verarbeitung von Wetterradardaten

!pip install wradlib
import wradlib as wrl

Anschließend schreiben wir zwei Hilfsfunktionen zum Herunterladen von Satellitendaten vom offenen Datenserver des DWD.


import urllib.request
import io
import numpy as np
import datetime

def download_and_read_RY(RY_timestamp):
   url = f"https://opendata.dwd.de/weather/radar/radolan/ry/raa01-ry_10000-{RY_timestamp}-dwd---bin"
   data_binary = urllib.request.urlopen(url).read()
   data, attr = wrl.io.read_radolan_composite(io.BytesIO(data_binary), missing = 0)
   data = data.astype("float32")
   return data,attr

def download_data():
   latest_scan, latest_attr = download_and_read_RY("latest")
   latest_datetime = latest_attr["datetime"]
   list_for_downloading = [ts.strftime("%y%m%d%H%M") for ts in
       [latest_datetime - datetime.timedelta(minutes=t) for t in [15, 10, 5]]]
   previous_scans = np.array([download_and_read_RY(ts)[0] for ts in list_for_downloading])
   print(list_for_downloading)
   scans = np.concatenate([previous_scans, latest_scan[np.newaxis, ::, ::]], axis = 0)

   return scans, latest_datetime

Mit diesen Dienstprogrammen können wir die neuesten vier Satellitenbilder herunterladen. Dies ist die Anzahl der Satellitenbilder, die wir benötigen, um mit unserem vorab trainierten Modell Vorhersagen zu treffen.

Anschließend können wir die erstellten Funktionen verwenden, um die neuesten 4 Bilder abzurufen


RY_latest, RY_latest_timestep = download_data()

Nachdem wir die Bilder erhalten haben, verwenden wir die Methode vis.plot_ppi von wradlib, um die Daten darzustellen

for i in range(RY_latest.shape[0]):
   wrl.vis.plot_ppi(RY_latest[i])

VIS-Radar

Wir haben jetzt unsere Daten geladen. Als nächstes laden wir das Modell.

Wir beginnen mit dem Import der relevanten Klassen. In diesem Artikel verwenden wir TensorFlow.

aus tensorflow.keras.layers Import Input, Conv2D, Activation, Concatenate, Conv2DTranspose, MaxPool2D

aus tensorflow.keras.models Modell importieren

Lassen Sie uns drei primitive Bausteine konstruieren. Diese „Bausteine“ werden verwendet, um die gesamte Architektur gemäß dieser [Implementierung] zu erstellen (https://github.com/bnsreenu/python_for_microscopists/blob/master/219-unet_model_with_functions_of_blocks.py).

Der erste Block entspricht der Abfolge der Faltungsschichten, wir nennen ihn "conv_block".

def conv_block(input, num_filters):
   x = Conv2D(num_filters, 3, padding ="same", kernel_initializer="he_normal"(input))
   x = Activation("relu")(x)
   x = Conv2D(num_filters, 3, padding ="same", kernel_initializer="he_normal"(x))
   x = Activation("relu")(x)
   return x

Der zweite Block wird verwendet, um den Encoder-Teil aufzubauen (Faltungsblock + maximales Pooling). Wir nennen es ein “encoder_block”

def encoder_block(input, num_filters):
   x = conv_block(input, num_filters)
   p = MaxPool2D((2,2))(x)
   return x,p

Der dritte und letzte Block ist ein "decoder_block" (Auffaltung + Verkettung + Faltung).

def decoder_block(input, skip_features, num_filters):
   x = Conv2DTranspose(num_filters, (2,2), strides=2, padding="same", kernel_initializer="he_normal")
   x = Concatenate()([x, skip_features])
   x = conv_block(x, num_filters)
   return x

Wir kombinieren diese Bausteine, um das U-Net-Modell zu erstellen

def build_unet(input_shape = (928, 928, 4)):

   inputs = Input(input_shape)
   e1, p1 = encoder_bock(inputs, 64)
   e2, p2 = encoder_bock(p1, 128)
   e3, p3 = encoder_bock(p2, 256)
   e4, p4 = encoder_bock(p3, 512)

   b1 = conv_block(p4, 1024)

   d1 = decoder_block(b1, e4, 512)
   d2 = decoder_block(d1, e3, 256)
   d3 = decoder_block(d2, e2, 128)
   d4 = decoder_block(d3, e1, 64)

   outputs = Conv2D(1, 1, padding="same", activation="linear")(d4)

   unet = Model(inputs, outputs, name="U-Net")

   return unet

Spielen Sie gerne mit der Implementierung herum, verbessern Sie sie oder passen Sie sie an Ihre Bedürfnisse an, wenn Sie sie für etwas anderes verwenden möchten.

Das Training dieses Modells kann viel Zeit in Anspruch nehmen. Glücklicherweise gibt es ein Modell namens Rain-Net, das auf der U-Net-Architektur basiert und auf Niederschlags-Nowcasting spezialisiert ist.

Klonen wir sein GitHub-Repository

! git clone https://github.com/hydrogo/rainnet.git

Anschließend laden wir die vorab trainierten Gewichte für dieses Modell herunter

!wget -O /content/rainnet/rainnet_weights.h5 https://zenodo.org/record/3630429/files/rainnet_weights.h5

Der nächste Schritt besteht darin, ein Modell basierend auf der im Repository gefundenen Architektur zu erstellen und dann die heruntergeladenen Gewichte in dieses Modell zu laden

import sys
from rainnet import rainnet
model = rainnet.rainnet()
model.load_weights('/content/rainnet/rainnet_weights.h5')
model.summary()

Die von uns heruntergeladenen Bilder haben eine Größe von 900*900 Pixeln. Wir werden diese Bilder so umformen, dass sie der erwarteten Eingabe von Rain-Net entsprechen

def Scaler(array):
   return np.log(array+0.01)


def invScaler(array):
   return np.exp(array) - 0.01


def pad_to_shape(array, from_shape=900, to_shape=928, how="mirror"):
   # calculate how much to pad in respect with native resolution
   padding = int( (to_shape - from_shape) / 2)
   # for input shape as (batch, W, H, channels)
   if how == "zero":
       array_padded = np.pad(array, ((0,0),(padding,padding),(padding,padding),(0,0)), mode="constant", constant_values=0)
   elif how == "mirror":
       array_padded = np.pad(array, ((0,0),(padding,padding),(padding,padding),(0,0)), mode="reflect")
   return array_padded


def pred_to_rad(pred, from_shape=928, to_shape=900):
   # pred shape 12,928,928
   padding = int( (from_shape - to_shape) / 2)
   return pred[::, padding:padding+to_shape, padding:padding+to_shape].copy()

'''
the spatial extent of input data has to be a multiple of 2n+1
where n is the number of max pooling layers
'''

def data_preprocessing(X):

   # 0. Right shape for batch
   X = np.moveaxis(X, 0, -1)
   X = X[np.newaxis, ::, ::, ::]
   # 1. To log scale
   '''
   We use a log scale to respond to skewness towards large values
   '''
   X = Scaler(X)
   # 2. from 900x900 to 928x928
   X = pad_to_shape(X)

   return X


def data_postprocessing(nwcst):

   # 0. Squeeze empty dimensions
   nwcst = np.squeeze(np.array(nwcst))
   # 1. Convert back to rainfall depth
   nwcst = invScaler(nwcst)
   # 2. Convert from 928x928 back to 900x900
   nwcst = pred_to_rad(nwcst)
   # 3. Return only positive values
   nwcst = np.where(nwcst>0, nwcst, 0)
   return nwcst

Anschließend erstellen wir eine Funktion, die die Vorhersagen trifft.

def prediction(model_instance, input_data, lead_time=24):

   input_data = data_preprocessing(input_data)
   nwcst = []

   for _ in range(lead_time):
       pred = model_instance.predict(input_data)
       nwcst.append(pred)
       input_data = np.concatenate([input_data[::, ::, ::, 1:], pred], axis = -1)

   nwcst = data_postprocessing(nwcst)

   return nwcst

Anschließend rufen wir diese Funktion für die zuvor heruntergeladenen Daten auf

Y_pred = prediction(model, RY_latest)

Wir können die Vorhersagen grafisch darstellen und speichern, um anhand der gespeicherten Ergebnisse ein GIF-Bild zu erstellen, mit dem wir die Vorhersagen visualisieren können

import matplotlib.pyplot as plt
names = []
for i in range(0, 19):
   im = wrl.vis.plot_ppi(Y_pred[i])
   name = '/content/image'+str(i)+'.png'
   names.append(name)
   plt.savefig(name)

import imageio
from google.colab import files

imgs = []

for name in names:
   imgs.append(imageio.imread(name))

imageio.mimsave('/content/pred.gif', imgs, fps=4)
files.download('/content/pred.gif')

Ergebnisse

Herzlichen Glückwunsch, dass Sie es bis hierher geschafft haben! Sie können jetzt ein Rain-Net verwenden, um Vorhersagen zu treffen und diese zu visualisieren.

Abschluss

In diesem Artikel haben wir ein maschinelles Lernmodell (Rain-Net) verwendet, um Niederschlags-Nowcasting durchzuführen. Wir haben eine U-Net-Architektur verwendet, die wir mit TensorFlow erstellt haben. Wir haben ein vorab trainiertes Modell geladen, um Satellitenbilder vorherzusagen.

Diese Implementierung kann in vielerlei Hinsicht verbessert werden. Zum Beispiel:

  1. Optimieren Sie das Modell für Ihren Datensatz

  2. Verwenden Sie in der Architektur ein aufmerksamkeitsbasiertes Modul wie CBAM (Convolutional Block Attention Module).

Verweise

Kommen Sie zu einem unserer kostenlosen Workshops!

Beginnen Sie Ihre Karriere als Datenwissenschaftler mit unseren kostenlosen Workshops, die auf einem anpassbaren Lehrplan basieren und von Branchenexperten geleitet werden.


Career Services background pattern

Karrieredienste

Contact Section background image

Lass uns in Kontakt bleiben

Code Labs Academy © 2024 Alle Rechte vorbehalten.