Precipitation Nowcasting with Machine Learning

ML
DL
CNN
Πρόβλεψη καιρού
UNet
Precipitation Nowcasting with Machine Learning cover image

Σήμερα, οι μετεωρολόγοι υπολογίζουν ότι το 90% των καιρικών προβλέψεων είναι σωστές σε διάστημα 5 ημερών. Οι προβλέψεις που γίνονται συνήθως βασίζονται σε δύο ξεχωριστές μεθόδους:

  1. Προσεγγίσεις βασισμένες στη φυσική: Αυτές οι προσεγγίσεις χρησιμοποιούν μοντέλα που ενσωματώνουν μετρήσιμα μεγέθη όπως πίεση, κίνηση των νεφών, συνθήκες του ουρανού… Τέτοια μοντέλα είναι καλά στην πρόβλεψη του καιρού για τις επόμενες ημέρες ή εβδομάδες.

  2. Προσεγγίσεις χωρίς φυσική (βασισμένες σε δεδομένα): Αυτές οι προσεγγίσεις χρησιμοποιούν ιστορικά δεδομένα για να δημιουργήσουν μοντέλα που μπορούν να κάνουν προβλέψεις. Τέτοια μοντέλα δείχνουν καλά αποτελέσματα στην πρόβλεψη του καιρού για έως και 6 ώρες ή αυτό που είναι γνωστό ως καιρού τώρα μετάδοση.

Σε αυτό το άρθρο, θα συζητήσουμε τη δεύτερη κατηγορία προσεγγίσεων. Θα συζητήσουμε τις διαφορετικές μορφές δεδομένων καιρού, τον τρόπο με τον οποίο η μηχανική μάθηση μπορεί να αξιοποιηθεί για να πραγματοποιηθεί τώρα μετάδοση καιρού και πώς οι αρχιτεκτονικές που αναπτύχθηκαν μπορούν να είναι επωφελείς για την επίλυση παρόμοιων προβλημάτων.

Δεδομένα για την πρόβλεψη του κλίματος

Εφόσον οι προσεγγίσεις χωρίς φυσική χρήση χρησιμοποιούν ιστορικά δεδομένα, ας ξεκινήσουμε εξετάζοντας τα διαθέσιμα δεδομένα.

Θα χρησιμοποιήσουμε δύο κύριες πηγές δεδομένων:

  1. Δεδομένα εικόνας: Αυτά τα δεδομένα έχουν τη μορφή εικόνων ραντάρ ή δορυφόρου μιας καθορισμένης γεωγραφικής περιοχής. Χρησιμοποιείται για την πρόβλεψη βροχοπτώσεων, κίνησης ανέμου ή υγρασίας.

Satellite Image

  1. Πίνακες δεδομένων : Αυτά τα δεδομένα έχουν τη μορφή καταγραφών μετρήσιμων μεγεθών όπως θερμοκρασία, υγρασία ή ταχύτητα ανέμου.

Tabular Data

Ενώ και οι δύο πηγές δεδομένων είναι σημαντικές για τη δημιουργία ισχυρών μοντέλων, θα εστιάσουμε στο πρώτο (δεδομένα εικόνας που συλλέγονται από ραντάρ ή δορυφόρους) για λόγους απλότητας. Τα πιο συχνά χρησιμοποιούμενα μοντέλα με δεδομένα εικόνας είναι τα Convolutional Neural Networks (CNNs ).

Μετά από αυτήν την εργασία, θα χρησιμοποιήσουμε μια αρχιτεκτονική U-Net για να δημιουργήσουμε το δικό μας μοντέλο τώρα μετάδοσης.

Αρχιτεκτονική

Η εκκίνηση από μια υπάρχουσα αρχιτεκτονική είναι χρήσιμη για πολλούς λόγους, μεταξύ των οποίων:

Οι αρχιτεκτονικές χρησιμεύουν ως κατευθυντήριες γραμμές για τη δημιουργία νέων μοντέλων. Οι άνθρωποι που δημιουργούν νέες αρχιτεκτονικές υιοθετούν μια προσέγγιση δοκιμής και λάθους για να φτάσουν στα τελικά τους αποτελέσματα. Χρησιμοποιώντας ξανά τα τελικά τους αποτελέσματα, μπορούμε να εξοικονομήσουμε πολύ χρόνο.

Τα προεκπαιδευμένα μοντέλα είναι συνήθως διαθέσιμα για άμεση χρήση. Όταν οι ερευνητές δημοσιεύουν τις νέες τους αρχιτεκτονικές, συνήθως δημοσιεύουν και τις εκπαιδευμένες παραμέτρους, έτσι ώστε οι χρήστες να μην χρειάζεται να περάσουν από τον κόπο της εκπαίδευσης/βελτιστοποίησης από την αρχή. Αυτό είναι ιδιαίτερα χρήσιμο για πολύ μεγάλα μοντέλα που διψούν για πόρους.

Παραδείγματα διάσημων αρχιτεκτονικών όρασης περιλαμβάνουν:

  • LeNet (60k παράμετροι)

LeNet

  • AlexNet (60m παράμετροι)

AlexNet

  • VGG-16 (138m παράμετροι)

VGG-16

U-Net

Το U-Net είναι μια αρχιτεκτονική που βασίζεται σε ένα πλήρως συνελικτικό δίκτυο, που σημαίνει ότι δεν έχει πλήρως συνδεδεμένα επίπεδα. Εισήχθη για πρώτη φορά για μια εργασία τμηματοποίησης ιατρικής εικόνας. Αυτά τα αποτελέσματα ενέπνευσαν τους ερευνητές να το επεκτείνουν και σε άλλες εργασίες στην όραση υπολογιστή.

Το 2019, η Google χρησιμοποίησε μια αρχιτεκτονική που βασίζεται στο U-Net για να δημιουργήσει ένα μοντέλο πρόβλεψης βροχοπτώσεων.

Το όνομα "U-Net" προέρχεται από το σχήμα "U" της αρχιτεκτονικής του.

U-net Architecture

Αναγνωρίζουμε τρία βασικά συστατικά:

  1. Συμφωνία / Κωδικοποιητής: Διαδοχή στρωμάτων συνέλιξης/ομαδοποίησης που συμπιέζουν την εικόνα εισόδου σε μια αναπαράσταση μικρότερου μεγέθους.

  2. Γέφυρα / Bottleneck: Το κάτω μέρος του "U" συνδέει τον κωδικοποιητή με τον αποκωδικοποιητή. Σχηματίζεται από μια σειρά πράξεων συνέλιξης.

  3. Decontracting / Decoder : Διαδοχή upconvelutions και convolution layers, τα οποία «αποσυμπιέζουν» την έξοδο του bottleneck.

Η αρχιτεκτονική ενός U-Net μοιάζει με αυτόματο κωδικοποιητή μέχρι στιγμής. Ωστόσο, η διαφορά έγκειται στις πληροφορίες που περνούν μεταξύ του κωδικοποιητή και του αποκωδικοποιητή. Αυτές οι πληροφορίες μεταβιβάζονται με τη σύνδεση των αποτελεσμάτων των περιελίξεων από τον κωδικοποιητή με αυτά της ανοδικής περιέλιξης του αποκωδικοποιητή. Αυτή η τροποποίηση βελτιώνει την ανάλυση και επιτρέπει στο μοντέλο να εξάγει μια πιο ακριβή χωρική έξοδο (η θέση των pixel στην έξοδο θα είναι πιο ακριβής, επιλύοντας ένα πρόβλημα που παρουσιάστηκε σε μοντέλα που δεν περιλάμβαναν συνένωση). Η συνένωση γίνεται συμμετρικά.

Κατασκευή ενός μοντέλου U-Net για κατακρήμνιση τώρα

Σε αυτή την ενότητα, θα δημιουργήσουμε ένα μοντέλο U-Net για να προβλέψουμε τον καιρό από δορυφορικές εικόνες. Θα χρησιμοποιήσουμε ένα προεκπαιδευμένο μοντέλο που ονομάζεται Rain-Net.

Ο παρακάτω κωδικός είναι διαθέσιμος σε αυτό το colab.

Αρχικά εγκαθιστούμε το wradlib, μια βιβλιοθήκη ανοιχτού κώδικα για επεξεργασία δεδομένων με ραντάρ καιρού

!pip install wradlib
import wradlib as wrl

Στη συνέχεια γράφουμε δύο βοηθητικές συναρτήσεις για τη λήψη δορυφορικών δεδομένων από τον τον διακομιστή ανοιχτών δεδομένων του 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

Αυτά τα βοηθητικά προγράμματα μας επιτρέπουν να κατεβάσουμε τις τελευταίες 4 δορυφορικές εικόνες, που είναι ο αριθμός των δορυφορικών εικόνων που χρειαζόμαστε για να κάνουμε προβλέψεις με το προεκπαιδευμένο μοντέλο μας.

Στη συνέχεια, μπορούμε να χρησιμοποιήσουμε τις λειτουργίες που δημιουργήθηκαν για να λάβουμε τις τελευταίες 4 εικόνες


RY_latest, RY_latest_timestep = download_data()

Αφού λάβουμε τις εικόνες, χρησιμοποιούμε τη μέθοδο vis.plot_ppi του wradlib για να σχεδιάσουμε τα δεδομένα

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

VIS Radar

Τώρα έχουμε φορτώσει τα δεδομένα μας. Ας φορτώσουμε το μοντέλο στη συνέχεια.

Ξεκινάμε εισάγοντας τις σχετικές κλάσεις. Θα χρησιμοποιήσουμε το TensorFlow σε αυτό το άρθρο.

από το tensorflow.keras.layers εισαγωγή Input, Conv2D, Activation, Concatenate, Conv2DTranspose, MaxPool2D

από το tensorflow.keras.models import Model

Ας κατασκευάσουμε 3 πρωτόγονα δομικά στοιχεία. Αυτά τα "δομικά στοιχεία" θα χρησιμοποιηθούν για τη δημιουργία ολόκληρης της αρχιτεκτονικής, σύμφωνα με αυτήν την υλοποίηση.

Το πρώτο μπλοκ αντιστοιχεί στη διαδοχή συνελικτικών επιπέδων, το ονομάζουμε "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

Το δεύτερο μπλοκ χρησιμοποιείται για τη δημιουργία του τμήματος από τον κωδικοποιητή (συνελικτικό μπλοκ + μέγ. συγκέντρωση). Το ονομάζουμε "encoder_block"

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

Το τρίτο και τελευταίο μπλοκ είναι ένα "decoder_block" (upconvolution + concatenation + convolution).

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

Συνδυάζουμε αυτά τα δομικά στοιχεία για να κατασκευάσουμε το μοντέλο U-Net

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

Μη διστάσετε να παίξετε με την υλοποίηση, να τη βελτιώσετε ή να την προσαρμόσετε στις ανάγκες σας, αν θέλετε να τη χρησιμοποιήσετε για κάτι άλλο.

Η εκπαίδευση αυτού του μοντέλου μπορεί να πάρει πολύ χρόνο. Ευτυχώς, υπάρχει ένα μοντέλο που ονομάζεται Rain-Net, το οποίο έχει δημιουργηθεί με βάση μια αρχιτεκτονική U-Net και είναι εξειδικευμένο στη ροή βροχοπτώσεων.

Ας κλωνοποιήσουμε το αποθετήριο GitHub

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

Στη συνέχεια κατεβάζουμε τα προεκπαιδευμένα βάρη για αυτό το μοντέλο

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

Το επόμενο βήμα είναι να δημιουργήσετε ένα μοντέλο με βάση την αρχιτεκτονική που βρίσκεται στο αποθετήριο και στη συνέχεια να φορτώσετε τα βάρη που έχουν ληφθεί σε αυτό το μοντέλο

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

Οι εικόνες που κατεβάσαμε έχουν μέγεθος 900*900 pixel. Θα αναδιαμορφώσουμε αυτές τις εικόνες ώστε να ταιριάζουν με την αναμενόμενη είσοδο του Rain-Net

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

Στη συνέχεια δημιουργούμε μια συνάρτηση που κάνει τις προβλέψεις.

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

Στη συνέχεια καλούμε αυτήν τη συνάρτηση στα δεδομένα που κατεβάσαμε νωρίτερα

Y_pred = prediction(model, RY_latest)

Μπορούμε να σχεδιάσουμε τις προβλέψεις και να τις αποθηκεύσουμε για να χρησιμοποιήσουμε τα αποθηκευμένα αποτελέσματα για να δημιουργήσουμε μια εικόνα gif που μας επιτρέπει να οπτικοποιούμε τις προβλέψεις

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')

Resuts

Συγχαρητήρια που έφτασες ως εδώ! Τώρα μπορείτε να χρησιμοποιήσετε ένα Rain-Net για να κάνετε προβλέψεις και να τις οπτικοποιήσετε.

Συμπέρασμα

Σε αυτό το άρθρο, χρησιμοποιήσαμε ένα μοντέλο μηχανικής εκμάθησης (Rain-Net) για να κάνουμε τη ροή βροχοπτώσεων τώρα. Χρησιμοποιήσαμε μια αρχιτεκτονική U-Net, την οποία κατασκευάσαμε χρησιμοποιώντας το TensorFlow. Φορτώσαμε ένα προεκπαιδευμένο μοντέλο για την πρόβλεψη δορυφορικών εικόνων.

Αυτή η υλοποίηση μπορεί να βελτιωθεί με πολλούς τρόπους. Για παράδειγμα:

  1. Προσαρμόστε το μοντέλο στο σύνολο δεδομένων σας

  2. Χρησιμοποιήστε μια λειτουργική μονάδα που βασίζεται στην προσοχή, όπως το CBAM (Convolutional Block Attention Module) στην αρχιτεκτονική.

Βιβλιογραφικές αναφορές

Ελάτε σε ένα από τα δωρεάν εργαστήρια μας!

Ξεκινήστε την καριέρα σας ως επιστήμονας δεδομένων με τα δωρεάν εργαστήρια, τα οποία βασίζονται σε ένα προσαρμόσιμο πρόγραμμα σπουδών και καθοδηγούνται από ειδικούς του κλάδου.


Career Services background pattern

Υπηρεσίες καριέρας

Contact Section background image

Ας μείνουμε σε επαφή

Code Labs Academy © 2024 Όλα τα δικαιώματα διατηρούνται.