Mūsdienās meteorologi lēš, ka 90% laika prognožu ir pareizi 5 dienu laikā. Prognozes, kas tiek veiktas, parasti balstās uz divām atsevišķām metodēm:
1. Uz fiziku balstītas pieejas. Šajās pieejās tiek izmantoti modeļi, kas integrē izmērāmus lielumus, piemēram, spiedienu, mākoņu kustību, debess apstākļus... Šādi modeļi labi prognozē laikapstākļus nākamajām dienām vai nedēļām.
- Bezfizikas (uz datiem balstītas) pieejas. Šīs pieejas izmanto vēsturiskos datus, lai izveidotu modeļus, kas var sniegt prognozes. Šādi modeļi uzrāda labus rezultātus, prognozējot laikapstākļus līdz pat 6 stundām vai tā saukto laika prognozi.
Šajā rakstā mēs apspriedīsim otro pieeju kategoriju. Mēs apspriedīsim dažādus laikapstākļu datu formātus, to, kā mašīnmācīšanos var izmantot, lai veiktu laikapstākļu apraidi, un kā izstrādātās arhitektūras var būt noderīgas līdzīgu problēmu risināšanai.
Dati klimata prognozēšanai
Tā kā pieejās bez fizikas tiek izmantoti vēsturiskie dati, sāksim ar pieejamo datu izpēti.
Mēs izmantosim divus galvenos datu avotus:
- Attēla dati: šie dati tiek iegūti noteikta ģeogrāfiskā apgabala radara vai satelītattēlu veidā. To izmanto, lai prognozētu nokrišņus, vēja kustību vai mitrumu.
- Tabulas dati : šie dati ir izmērāmu lielumu, piemēram, temperatūras, mitruma vai vēja ātruma, ierakstu veidā.
Lai gan abi datu avoti ir svarīgi, lai izveidotu jaudīgus modeļus, vienkāršības labad mēs koncentrēsimies uz pirmo (attēlu dati, kas savākti no radariem vai satelītiem). Visbiežāk izmantotie modeļi ar attēlu datiem ir Convolutional Neural Networks (CNN ).
Pēc šī darba mēs izmantosim U-Net arhitektūru, lai izveidotu savu tagadapraides modeli.
Arhitektūra
Sākot ar esošu arhitektūru, ir noderīgi daudzu iemeslu dēļ, tostarp:
Arhitektūras kalpo kā vadlīnijas jaunu modeļu radīšanai. Cilvēki, kas veido jaunas arhitektūras, izmanto izmēģinājumu un kļūdu pieeju, lai sasniegtu savus galīgos rezultātus. Atkārtoti izmantojot to galīgos rezultātus, mēs varam ietaupīt daudz laika.
Iepriekš apmācīti modeļi parasti ir pieejami tūlītējai lietošanai. Kad pētnieki publicē savas jaunās arhitektūras, viņi parasti publicē arī apmācītos parametrus, lai lietotājiem nebūtu jāpiedzīvo apmācības/optimizēšanas problēmas no nulles. Tas ir īpaši noderīgi ļoti lieliem, resursu izslāpušiem modeļiem.
Slavenu redzes arhitektūru piemēri ir:
- LeNet (60 000 parametri)
- AlexNet (60 m parametri)
- VGG-16 (138 m parametri)
U-Net
U-Net ir arhitektūra, kuras pamatā ir pilnībā konvolūcijas tīkls, kas nozīmē, ka tai nav pilnībā savienotu slāņu. Tas pirmo reizi tika ieviests medicīniskā attēla segmentēšanas uzdevumam. Šie rezultāti iedvesmoja pētniekus to attiecināt uz citiem datorredzes uzdevumiem.
2019. gadā Google izmantoja U-Net arhitektūru, lai izveidotu nokrišņu prognozēšanas modeli.
Nosaukums “U-Net” cēlies no tā arhitektūras “U” formas.
Mēs identificējam trīs galvenās sastāvdaļas:
-
Contracting / Encoder: konvolūcijas/apvienošanas slāņu pēctecība, kas saspiež ievades attēlu mazāka izmēra attēlojumā.
-
Tilts / sašaurinājums: “U” apakšējā daļa savieno kodētāju ar dekodētāju. To veido virkne konvolūcijas darbību.
-
Atdalīšana / dekodētājs: augšupvērsumu un konvolūcijas slāņu pēctecība, kas “dekompresē” sašaurinājuma izvadi.
U-Net arhitektūra līdz šim izskatās pēc automātiskā kodētāja. Tomēr atšķirība ir informācijā, kas tiek pārraidīta starp kodētāju un dekodētāju. Šī informācija tiek nodota, savienojot kodētāja konvolūciju rezultātus ar dekodētāja augšupkonvolūcijas rezultātiem. Šī modifikācija uzlabo izšķirtspēju un ļauj modelim izvadīt telpiski precīzāku izvadi (pikseļu atrašanās vieta izvadē būs precīzāka, tādējādi atrisinot problēmu, kas radās modeļos, kuros nav iekļauta savienošana). Savienošana tiek veikta simetriski.
U-Net modeļa izveide nokrišņu tagadnes apraidei
Šajā sadaļā mēs izveidosim U-Net modeli, lai prognozētu laikapstākļus no satelīta attēliem. Mēs izmantosim iepriekš apmācītu modeli ar nosaukumu Rain-Net.
Tālāk norādītais kods ir pieejams šajā colab.
Vispirms mēs instalējam wradlib, atvērtā pirmkoda bibliotēku laikapstākļu radaru datu apstrādei.
!pip install wradlib
import wradlib as wrl
Pēc tam mēs rakstām divas utilīta funkcijas, lai lejupielādētu satelīta datus no DWD atvērto datu servera
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
Šīs utilītas ļauj mums lejupielādēt jaunākos 4 satelītattēlus, kas ir satelītattēlu skaits, kas mums ir nepieciešams, lai prognozētu mūsu iepriekš apmācīto modeli.
Pēc tam mēs varam izmantot izveidotās funkcijas, lai iegūtu jaunākos 4 attēlus
RY_latest, RY_latest_timestep = download_data()
Pēc attēlu iegūšanas datu attēlošanai izmantojam wradlib vis.plot_ppi metodi.
for i in range(RY_latest.shape[0]):
wrl.vis.plot_ppi(RY_latest[i])
Tagad mēs esam ielādējuši savus datus. Tālāk ielādēsim modeli.
Mēs sākam ar attiecīgo klašu importēšanu. Šajā rakstā mēs izmantosim TensorFlow.
no tensorflow.keras.layers importa ievade, Conv2D, aktivizēšana, savienošana, Conv2DTranspose, MaxPool2D
no tensorflow.keras.models importa Modelis
Uzbūvēsim 3 primitīvus celtniecības blokus. Šie “veidošanas bloki” tiks izmantoti, lai izveidotu visu arhitektūru saskaņā ar šo ieviešanu.
Pirmais bloks atbilst konvolucionālo slāņu secībai, mēs to saucam par "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
Otrais bloks tiek izmantots, lai izveidotu no kodētāja daļas (konvolucionālais bloks + maksimālā apvienošana). Mēs to saucam par “encoder_block”
def encoder_block(input, num_filters):
x = conv_block(input, num_filters)
p = MaxPool2D((2,2))(x)
return x,p
Trešais un pēdējais bloks ir “decoder_block” (augšupkonvolūcija + konkatenācija + konvolūcija).
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
Mēs apvienojam šos blokus, lai izveidotu U-Net modeli
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
Jūtieties brīvi spēlēties ar ieviešanu, uzlabot to vai pielāgot savām vajadzībām, ja vēlaties to izmantot kaut kam citam.
Šī modeļa apmācība var aizņemt daudz laika. Par laimi, ir modelis ar nosaukumu Rain-Net, kas ir izveidots, pamatojoties uz U-Net arhitektūru un ir specializējies nokrišņu tagadnē.
Klonēsim tās GitHub repozitoriju
! git clone https://github.com/hydrogo/rainnet.git
Pēc tam mēs lejupielādējam šim modelim sagatavotos svarus
!wget -O /content/rainnet/rainnet_weights.h5 https://zenodo.org/record/3630429/files/rainnet_weights.h5
Nākamais solis ir izveidot modeli, pamatojoties uz krātuvē atrasto arhitektūru, un pēc tam ielādēt šajā modelī lejupielādētos svarus
import sys
from rainnet import rainnet
model = rainnet.rainnet()
model.load_weights('/content/rainnet/rainnet_weights.h5')
model.summary()
Lejupielādēto attēlu izmērs ir 900*900 pikseļi. Mēs pārveidosim šos attēlus, lai tie atbilstu paredzamajai Rain-Net ievadei
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
Pēc tam mēs izveidojam funkciju, kas veido prognozes.
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
Pēc tam mēs izsaucam šo funkciju, pamatojoties uz iepriekš lejupielādētajiem datiem
Y_pred = prediction(model, RY_latest)
Mēs varam uzzīmēt prognozes un saglabāt tās, lai izmantotu saglabātos rezultātus, lai izveidotu gif attēlu, kas ļauj vizualizēt prognozes
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')
Apsveicam, ka tikāt tik tālu! Tagad varat izmantot Rain-Net, lai veiktu prognozes un tās vizualizētu.
Secinājums
Šajā rakstā mēs esam izmantojuši mašīnmācīšanās modeli (Rain-Net), lai veiktu nokrišņu apraidi. Mēs izmantojām U-Net arhitektūru, kuru izveidojām, izmantojot TensorFlow. Mēs ielādējām iepriekš apmācītu modeli, lai prognozētu satelītattēlus.
Šo ieviešanu var uzlabot daudzos veidos. Piemēram:
1. Precīzi noregulējiet modeli savā datu kopā
2. Arhitektūrā izmantojiet uz uzmanību balstītu moduli, piemēram, CBAM (Convolutional Block Attention Module).
Atsauces
Nāciet uz kādu no mūsu bezmaksas darbnīcām!
Sāciet savu karjeru kā datu zinātnieks ar mūsu bezmaksas semināriem, kuru pamatā ir pielāgojama mācību programma un kuras vada nozares eksperti.