Precipitation Nowcasting gépi tanulással

ML
DL
CNN
Időjárás előrejelzés
UNet
Precipitation Nowcasting gépi tanulással cover image

Napjainkban a meteorológusok becslése szerint az időjárás-előrejelzések 90%-a helytálló 5 napos távon. Az előrejelzések általában két különböző módszeren alapulnak:

  1. Fizikai alapú megközelítések: Ezek a megközelítések olyan modelleket használnak, amelyek olyan mérhető mennyiségeket integrálnak, mint például a nyomás, a felhők mozgása, az égbolt állapota… Az ilyen modellek jól megjósolják a következő napok vagy hetek időjárását.

  2. Fizikamentes (adatalapú) megközelítések: Ezek a megközelítések történelmi adatokat használnak fel olyan modellek létrehozására, amelyek előrejelzéseket tudnak készíteni. Az ilyen modellek jó eredményeket mutatnak az időjárás előrejelzésében akár 6 órán keresztül, vagy az úgynevezett időjárási mostani előrejelzésben.

Ebben a cikkben a megközelítések második kategóriáját tárgyaljuk. Szó lesz az időjárási adatok különböző formátumairól, arról, hogyan lehet a gépi tanulást felhasználni az időjárás mérésére, és hogyan lehetnek előnyösek a kifejlesztett architektúrák hasonló problémák megoldásában.

Adatok az éghajlat-előrejelzéshez

Mivel a fizikamentes megközelítések előzményadatokat használnak, kezdjük a rendelkezésre álló adatok megvizsgálásával.

Két fő adatforrást fogunk használni:

  1. Képadatok: Ezek az adatok egy meghatározott földrajzi terület radar- vagy műholdképei. Csapadék, szélmozgás vagy páratartalom előrejelzésére szolgál.

Satellite Image

  1. Táblázatos adatok : Ezek az adatok mérhető mennyiségek, például hőmérséklet, páratartalom vagy szélsebesség rögzítésének formáját öltik.

Tabular Data

Bár mindkét adatforrás fontos az erőteljes modellek felépítéséhez, az egyszerűség kedvéért az előbbire (radarokról vagy műholdakról gyűjtött képadatokra) fogunk összpontosítani. A képadatokkal leggyakrabban használt modellek a Convolutional Neural Networks (CNN-ek ).

Ezt a munkát követően egy U-Net architektúrát fogunk használni saját nowcasting modellünk felépítéséhez.

Építészet

A meglévő architektúrából való kiindulás számos okból hasznos, többek között:

Az építészet iránymutatásként szolgál új modellek létrehozásához. Azok az emberek, akik új architektúrákat hoznak létre, a próba és hiba módszerét alkalmazzák a végső eredmények eléréséhez. A végeredményük újrafelhasználásával rengeteg időt takaríthatunk meg.

Az előképzett modellek általában azonnali használatra rendelkezésre állnak. Amikor a kutatók közzéteszik új architektúrájukat, általában közzéteszik a betanított paramétereket is, hogy a felhasználóknak ne kelljen a nulláról átmenniük a betanítással/optimalizálással. Ez különösen hasznos nagyon nagy, erőforrásigényes modelleknél.

Példák a híres látványarchitektúrákra:

  • LeNet (60 000 paraméter)

LeNet

  • AlexNet (60 m-es paraméterek)

AlexNet

  • VGG-16 (138 m-es paraméterek)

VGG-16

U-Net

Az U-Net egy teljesen konvolúciós hálózaton alapuló architektúra, ami azt jelenti, hogy nincsenek teljesen összekapcsolt rétegei. Először egy orvosi képszegmentációs feladathoz vezették be. Ezek az eredmények arra ösztönözték a kutatókat, hogy ezt a számítógépes látás egyéb feladataira is kiterjesszék.

2019-ben a Google U-Net-alapú architektúrát használt a csapadék-előrejelzési modell létrehozásához.

Az „U-Net” név az építészet „U” alakjából származik.

U-net Architecture

Három fő összetevőt azonosítunk:

  1. Összehúzó / kódoló: Konvolúciós/összevonási rétegek egymásutánja, amelyek a bemeneti képet kisebb méretű reprezentációra tömörítik.

  2. Híd / szűk keresztmetszet: Az „U” alsó része köti össze a kódolót a dekóderrel. Konvolúciós műveletek sorozata alkotja.

  3. Decontracting / Decoder : Felkonvolúciók és konvolúciós rétegek egymásutánja, amelyek „kitömörítik” a szűk keresztmetszet kimenetét.

Az U-Net architektúrája eddig úgy néz ki, mint egy automatikus kódoló. A különbség azonban a kódoló és a dekódoló között áthaladó információban rejlik. Ezt az információt a kódoló konvolúcióinak és a dekódoló felkonvolúciójának eredményeinek összefűzésével továbbítják. Ez a módosítás javítja a felbontást, és lehetővé teszi a modell számára, hogy térbelileg pontosabb kimenetet adjon ki (pontosabb lesz a képpontok elhelyezkedése a kimenetben, ami megoldja az összefűzést nem tartalmazó modellekben előforduló problémát). Az összefűzés szimmetrikusan történik.

U-Net modell készítése a csapadékmosás céljára

Ebben a részben egy U-Net modellt fogunk építeni, amely a műholdfelvételek alapján megjósolja az időjárást. A Rain-Net nevű előre betanított modellt fogjuk használni.

Az alábbi kód ebben a colabban érhető el.

Először telepítjük a wradlib nyílt forráskódú könyvtárat az időjárási radar adatfeldolgozáshoz

!pip install wradlib
import wradlib as wrl

Ezután két segédfunkciót írunk, amelyek a műholdas adatokat töltik le a DWD nyílt adatszerveréről


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

Ezek a segédprogramok lehetővé teszik a legutóbbi 4 műholdkép letöltését, vagyis annyi műholdképet, amelyre előre képzett modellünkkel előrejelzéseket kell készítenünk.

Ezt követően a létrehozott függvények segítségével megkaphatjuk a legújabb 4 képet


RY_latest, RY_latest_timestep = download_data()

A képek beszerzése után a wradlib vis.plot_ppi metódusát használjuk az adatok ábrázolására

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

VIS Radar

Most feltöltöttük adatainkat. Ezután töltsük be a modellt.

Kezdjük a megfelelő osztályok importálásával. Ebben a cikkben a TensorFlow-t fogjuk használni.

a tensorflow.keras.layers-ből import Bemenet, Conv2D, Aktiválás, Összefűzés, Conv2DTranspose, MaxPool2D

from tensorflow.keras.models import Model

Építsünk 3 primitív építőelemet. Ezeket az „építőkockákat” a rendszer a teljes architektúra létrehozására fogja használni, ennek a megvalósításnak szerint.

Az első blokk a konvolúciós rétegek egymásutánjának felel meg, mi "conv_block"-nak hívjuk.

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

A második blokk a kódoló részből való felépítésére szolgál (konvolúciós blokk + max pooling). „Encoder_block”-nak hívjuk

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

A harmadik és egyben utolsó blokk egy „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

Ezeket az építőelemeket kombináljuk az U-Net modell megalkotásához

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

Nyugodtan játszd el a megvalósítást, javítsd vagy igazítsd az igényeidhez, ha másra szeretnéd használni.

Ennek a modellnek a betanítása sok időt vehet igénybe. Szerencsére van egy Rain-Net nevű modell, amely U-Net architektúrára épült, és a csapadékmosásra specializálódott.

Klónozzuk a GitHub adattárat

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

Ezután letöltjük az előképzett súlyokat ehhez a modellhez

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

A következő lépés egy modell létrehozása a tárolóban található architektúra alapján, majd betölti a modellre letöltött súlyokat

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

Az általunk letöltött képek 900*900 pixel méretűek. Ezeket a képeket úgy alakítjuk át, hogy azok megfeleljenek a Rain-Net várható bemenetének

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

Ezután létrehozunk egy függvényt, amely előrejelzéseket készít.

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

Ezután ezt a függvényt a korábban letöltött adatok alapján hívjuk meg

Y_pred = prediction(model, RY_latest)

Megrajzolhatjuk az előrejelzéseket, és elmenthetjük őket, hogy a mentett eredményeket felhasználva gif képet készítsünk, amely lehetővé teszi az előrejelzések megjelenítését

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

Gratulálunk, hogy idáig eljutott! Mostantól egy Rain-Net segítségével előrejelzéseket készíthet és megjelenítheti azokat.

Következtetés

Ebben a cikkben gépi tanulási modellt (Rain-Net) használtunk a csapadékmosás mérésére. U-Net architektúrát használtunk, amelyet TensorFlow segítségével építettünk. Betöltöttünk egy előre betanított modellt a műholdképek előrejelzésére.

Ez a megvalósítás sokféleképpen javítható. Például:

  1. Finomítsa be a modellt az adatkészleten

  2. Használjon figyelem alapú modult, például CBAM-et (Convolutional Block Attention Module) az architektúrában.

Referenciák

Gyere el ingyenes workshopjaink egyikére!

Kezdje adattudós karrierjét ingyenes workshopjainkkal, amelyek adaptálható tananyagon alapulnak, és iparági szakértők vezetik őket.


Career Services background pattern

Karrier szolgáltatások

Contact Section background image

Maradjunk kapcsolatban

Code Labs Academy © 2024 Minden jog fenntartva.