Deesdae skat meteoroloë dat 90% van die weervoorspellings in 'n 5 dae-tydperk korrek is. Die voorspellings wat gemaak word, is gewoonlik gebaseer op twee afsonderlike metodes:
-
Fisika-gebaseerde benaderings: Hierdie benaderings gebruik modelle wat meetbare hoeveelhede integreer soos druk, wolke se beweging, lugtoestande ... Sulke modelle is goed om die weer vir die komende dae of weke te voorspel.
-
Fisika-vrye (data-gebaseerde) benaderings: Hierdie benaderings gebruik historiese data om modelle te skep wat voorspellings kan maak. Sulke modelle toon goeie resultate in die voorspelling van die weer vir tot 6 uur of wat bekend staan as weer-nowcasting.
In hierdie artikel sal ons die tweede kategorie benaderings bespreek. Ons sal die verskillende formate van weerdata bespreek, hoe masjienleer aangewend kan word om weer-nowcasting te doen, en hoe die argitekture wat ontwikkel is, voordelig kan wees om soortgelyke probleme op te los.
Data vir klimaatvoorspelling
Aangesien die fisika-vrye benaderings historiese data gebruik, kom ons begin deur na die beskikbare data te kyk.
Ons sal twee hoofbronne van data gebruik:
- Beelddata: Hierdie data neem die vorm aan van radar- of satellietbeelde van 'n gespesifiseerde geografiese gebied. Dit word gebruik om neerslag, windbeweging of humiditeit te voorspel.
- Data in tabelvorm: Hierdie data neem die vorm aan van rekords van meetbare hoeveelhede soos temperatuur, humiditeit of windspoed.
Alhoewel beide databronne belangrik is om kragtige modelle te bou, sal ons om eenvoudsredes op eersgenoemde fokus (beelddata wat van radars of satelliete ingesamel is). Die mees algemeen gebruikte modelle met beelddata is Convolutional Neural Networks (CNNs ).
Na aanleiding van hierdie werk, gaan ons 'n U-Net-argitektuur gebruik om ons eie nowcasting-model te bou.
Argitektuur
Om van 'n bestaande argitektuur te begin is om baie redes nuttig, waaronder:
Argitekture dien as riglyne vir die skep van nuwe modelle. Mense wat nuwe argitekture skep, volg 'n proef-en-foutbenadering om by hul finale resultate uit te kom. Deur hul finale resultate te hergebruik, kan ons baie tyd bespaar.
Vooraf opgeleide modelle is gewoonlik beskikbaar vir onmiddellike gebruik. Wanneer navorsers hul nuwe argitekture publiseer, publiseer hulle gewoonlik ook die opgeleide parameters, sodat gebruikers nie van nuuts af deur die moeite van opleiding/optimering hoef te gaan nie. Dit is veral nuttig vir baie groot, hulpbron-dorstige modelle.
Voorbeelde van bekende visie-argitekture sluit in:
- LeNet (60k parameters)
- AlexNet (60m parameters)
- VGG-16 (138m parameters)
U-Net
U-Net is 'n argitektuur wat gebaseer is op 'n volledig konvolusionele netwerk, wat beteken dat dit geen volledig gekoppelde lae het nie. Dit is die eerste keer bekendgestel vir 'n mediese beeldsegmenteringstaak. Hierdie resultate het navorsers geïnspireer om dit uit te brei na ander take in rekenaarvisie.
In 2019 het Google 'n U-Net-gebaseerde argitektuur gebruik om 'n neerslagvoorspellingsmodel te skep.
Die naam "U-Net" kom van die "U"-vorm van sy argitektuur.
Ons identifiseer drie hoofkomponente:
-
Sametrekking / Enkodeerder: Opeenvolging van konvolusie/poel lae wat die insetbeeld saampers in 'n kleiner grootte voorstelling.
-
Brug / Bottelnek: Die onderste deel van die “U” verbind die enkodeerder met die dekodeerder. Dit word gevorm deur 'n reeks konvolusie-bewerkings.
-
Dekontraktering / Dekodeerder : Opeenvolging van opkonvolusies en konvolusielae, wat die uitset van die bottelnek “dekomprimeer”.
Die argitektuur van 'n U-Net lyk tot dusver soos 'n outo-enkodeerder. Die verskil lê egter in die inligting wat deurgegee word tussen die enkodeerder en die dekodeerder. Hierdie inligting word deurgegee deur die resultate van konvolusies vanaf die enkodeerder aaneen te koppel met dié van die opkonvolusie van die dekodeerder. Hierdie wysiging verbeter die resolusie en laat die model toe om 'n meer ruimtelik presiese uitset uit te voer (die ligging van die pixels in die uitset sal meer presies wees, wat 'n probleem oplos wat in modelle voorgekom het wat nie aaneenskakeling ingesluit het nie). Die aaneenskakeling word simmetries gedoen.
Bou 'n U-Net-model vir Precipitation Nowcasting
In hierdie afdeling sal ons 'n U-Net-model bou om die weer vanaf satellietbeelde te voorspel. Ons sal 'n vooraf-opgeleide model genaamd Rain-Net gebruik.
Die kode hieronder is beskikbaar in hierdie colab.
Ons installeer eers wradlib, 'n oopbronbiblioteek vir weerradardataverwerking
!pip install wradlib
import wradlib as wrl
Ons skryf dan twee nutsfunksies om satellietdata van die [DWD se oop databediener] af te laai (https://www.dwd.de/EN/ourservices/opendata/opendata.html)
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
Hierdie nutsprogramme stel ons in staat om die nuutste 4 satellietbeelde af te laai, wat die aantal satellietbeelde is wat ons nodig het om voorspellings te maak met ons voorafopgeleide model.
Ons kan dan die funksies wat geskep is gebruik om die nuutste 4 beelde te kry
RY_latest, RY_latest_timestep = download_data()
Nadat ons die beelde gekry het, gebruik ons wradlib se vis.plot_ppi metode om die data te plot
for i in range(RY_latest.shape[0]):
wrl.vis.plot_ppi(RY_latest[i])
Ons het nou ons data gelaai. Kom ons laai die model volgende.
Ons begin deur die betrokke klasse in te voer. Ons sal TensorFlow in hierdie artikel gebruik.
vanaf tensorflow.keras.layers voer invoer, Conv2D, Aktivering, Concatenate, Conv2DTranspose, MaxPool2D in
vanaf tensorflow.keras.models invoer Model
Kom ons bou 3 primitiewe boublokke. Hierdie "boublokke" sal gebruik word om die hele argitektuur te skep, volgens hierdie implementering.
Die eerste blok stem ooreen met die opeenvolging van konvolusionele lae, ons noem dit "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
Die tweede blok word gebruik om die van die enkodeerder deel te bou (konvolusieblok + maksimum poel). Ons noem dit 'n "encoder_block"
def encoder_block(input, num_filters):
x = conv_block(input, num_filters)
p = MaxPool2D((2,2))(x)
return x,p
Die derde en laaste blok is 'n "dekodeerder_blok" (opkonvolusie + aaneenskakeling + konvolusie).
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
Ons kombineer hierdie boustene om die U-Net-model te bou
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
Speel gerus rond met die implementering, verbeter dit of pas dit aan by jou behoeftes as jy dit vir iets anders wil gebruik.
Opleiding van hierdie model kan baie tyd neem. Gelukkig is daar 'n model genaamd Rain-Net, wat geskep is op grond van 'n U-Net-argitektuur, en gespesialiseer is in neerslag-nowcasting.
Kom ons kloon sy GitHub-bewaarplek
! git clone https://github.com/hydrogo/rainnet.git
Ons laai dan die voorafopgeleide gewigte vir hierdie model af
!wget -O /content/rainnet/rainnet_weights.h5 https://zenodo.org/record/3630429/files/rainnet_weights.h5
Die volgende stap is om 'n model te skep gebaseer op die argitektuur wat op die bewaarplek gevind word en dan die gewigte wat na hierdie model afgelaai is, te laai
import sys
from rainnet import rainnet
model = rainnet.rainnet()
model.load_weights('/content/rainnet/rainnet_weights.h5')
model.summary()
Die beelde wat ons afgelaai het, het 'n grootte van 900*900 pixels. Ons gaan hierdie beelde hervorm om by die verwagte insette van Rain-Net te pas
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
Ons skep dan 'n funksie wat die voorspellings maak.
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
Ons noem hierdie funksie dan op die data wat ons vroeër afgelaai het
Y_pred = prediction(model, RY_latest)
Ons kan die voorspellings plot en stoor om die resultate wat gestoor is te gebruik om 'n gif-beeld te skep wat ons in staat stel om die voorspellings te visualiseer
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')
Baie geluk dat jy dit so ver gemaak het! Jy kan nou 'n Rain-Net gebruik om voorspellings te maak en dit te visualiseer.
Gevolgtrekking
In hierdie artikel het ons 'n masjienleermodel (Rain-Net) gebruik om neerslag-nowcasting te doen. Ons het 'n U-Net-argitektuur gebruik, wat ons met TensorFlow gebou het. Ons het 'n voorafopgeleide model gelaai om satellietbeelde te voorspel.
Hierdie implementering kan op baie maniere verbeter word. Byvoorbeeld:
-
Verfyn die model op jou datastel
-
Gebruik 'n aandag-gebaseerde module, soos CBAM (Convolutional Block Attention Module) in die argitektuur.
Verwysings
Kom na een van ons gratis werkswinkels!
Begin jou loopbaan as 'n datawetenskaplike met ons gratis werkswinkels, wat gebaseer is op 'n aanpasbare kurrikulum en gelei word deur kundiges in die bedryf.