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:
-
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.
-
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:
- 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.
- 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.
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)
- AlexNet (60 m-es paraméterek)
- VGG-16 (138 m-es paraméterek)
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.
Három fő összetevőt azonosítunk:
-
Ö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.
-
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.
-
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])
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')
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:
-
Finomítsa be a modellt az adatkészleten
-
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.