Sa ngayon, tinatantya ng mga meteorologist na 90% ng mga hula sa panahon ay tama sa loob ng 5 araw. Ang mga hula na ginawa ay karaniwang batay sa dalawang magkahiwalay na pamamaraan:
-
Physics-based approaches: Gumagamit ang mga approach na ito ng mga modelong nagsasama ng mga masusukat na dami gaya ng pressure, paggalaw ng mga ulap, mga kondisyon ng kalangitan... Ang mga ganitong modelo ay mahusay sa paghula ng lagay ng panahon para sa mga paparating na araw o linggo.
-
Physics-free (data-based) approach: Gumagamit ang mga approach na ito ng historical data para gumawa ng mga modelong maaaring gumawa ng mga hula. Ang ganitong mga modelo ay nagpapakita ng magagandang resulta sa paghula ng lagay ng panahon nang hanggang 6 na oras o tinatawag na weather nowcasting.
Sa artikulong ito, tatalakayin natin ang pangalawang kategorya ng mga diskarte. Tatalakayin natin ang iba't ibang format ng data ng lagay ng panahon, kung paano magagamit ang machine learning para gawin ang weather nowcasting, at kung paano maaaring maging kapaki-pakinabang ang mga binuong arkitektura para sa paglutas ng mga katulad na problema.
Data para sa Climate Prediction
Dahil ang mga diskarteng walang physics ay gumagamit ng makasaysayang data, magsimula tayo sa pamamagitan ng pagtingin sa magagamit na data.
Gagamitin namin ang dalawang pangunahing mapagkukunan ng data:
- Data ng imahe: Ang data na ito ay nasa anyo ng radar o satellite na mga imahe ng isang tinukoy na heyograpikong lugar. Ito ay ginagamit upang mahulaan ang pag-ulan, paggalaw ng hangin o halumigmig.
- Tabular data : Ang data na ito ay nasa anyo ng mga talaan ng masusukat na dami tulad ng temperatura, halumigmig o bilis ng hangin.
Bagama't mahalaga ang parehong data source para makabuo ng mahuhusay na modelo, tututuon tayo sa dating (data ng imahe na nakolekta mula sa mga radar o satellite) para sa mga dahilan ng pagiging simple. Ang pinakakaraniwang ginagamit na mga modelo na may data ng larawan ay ang Convolutional Neural Networks (CNNs ).
Kasunod ng [trabaho] na ito(https://arxiv.org/pdf/1807.06521.pdf), gagamit kami ng U-Net na arkitektura para bumuo ng sarili naming modelo ng nowcasting.
Arkitektura
Ang pagsisimula sa isang umiiral na arkitektura ay kapaki-pakinabang para sa maraming mga kadahilanan, kung saan:
Ang mga arkitektura ay nagsisilbing mga patnubay para sa paglikha ng mga bagong modelo. Ang mga taong gumagawa ng mga bagong arkitektura ay gumagamit ng trial at error na diskarte para makuha ang kanilang mga huling resulta. Sa pamamagitan ng muling paggamit sa kanilang mga huling resulta, makakatipid tayo ng maraming oras.
Ang mga pretrained na modelo ay karaniwang magagamit para sa agarang paggamit. Kapag ang mga mananaliksik ay nag-publish ng kanilang mga bagong arkitektura, karaniwan din nilang ini-publish ang mga sinanay na parameter, upang ang mga user ay hindi na kailangang dumaan sa problema ng pagsasanay/pag-optimize mula sa simula. Ito ay partikular na kapaki-pakinabang para sa napakalaki, mga modelong uhaw sa mapagkukunan.
Ang mga halimbawa ng mga sikat na arkitektura ng paningin ay kinabibilangan ng:
- LeNet (60k parameter)
- AlexNet (60m na mga parameter)
- VGG-16 (138m parameter)
U-Net
Ang U-Net ay isang arkitektura na nakabatay sa isang ganap na convolutional network, ibig sabihin, wala itong anumang ganap na konektadong mga layer. Ito ay unang ipinakilala para sa isang medikal na gawain sa segmentation ng imahe. Ang mga resultang ito ay nagbigay inspirasyon sa mga mananaliksik na palawigin ito sa iba pang mga gawain sa computer vision.
Noong 2019, gumamit ang Google ng U-Net-based na arkitektura para gumawa ng modelo ng precipitation forecasting.
Ang pangalang "U-Net" ay nagmula sa "U" na hugis ng arkitektura nito.
Tinutukoy namin ang tatlong pangunahing bahagi:
-
Contracting / Encoder: Succession of convolution/pooling layers na pumipilit sa input image sa isang mas maliit na sukat na representasyon.
-
Tulay / Bottleneck: Ang ilalim na bahagi ng "U" ay nagkokonekta sa encoder sa decoder. Ito ay nabuo sa pamamagitan ng isang serye ng mga operasyon ng convolution.
-
Decontracting / Decoder : Succession of upconvolutions at convolution layers, na "decompress" ang output ng bottleneck.
Ang arkitektura ng isang U-Net ay mukhang isang auto-encoder sa ngayon. Gayunpaman, ang pagkakaiba ay namamalagi sa impormasyong dumadaan sa pagitan ng encoder at ng decoder. Ang impormasyong ito ay ipinapasa sa pamamagitan ng pagsasama-sama ng mga resulta ng mga convolutions mula sa encoder sa na ng upconvolution ng decoder. Pinapahusay ng pagbabagong ito ang resolution, at nagbibigay-daan sa modelo na mag-output ng mas tumpak na spatially na output (magiging mas tumpak ang lokasyon ng mga pixel sa output, paglutas ng problemang naganap sa mga modelong hindi kasama ang concatenation). Ang concatenation ay tapos na simetriko.
Pagbuo ng U-Net Model para sa Precipitation Nowcasting
Sa seksyong ito, bubuo kami ng modelong U-Net upang mahulaan ang lagay ng panahon mula sa mga imahe ng satellite. Gagamit kami ng pre-trained na modelo na tinatawag na Rain-Net.
Ang code sa ibaba ay available sa [colab] na ito(https://arxiv.org/abs/1505.04597).
Nag-install muna kami ng wradlib, isang Open Source Library para sa Pagproseso ng Data ng Weather Radar
!pip install wradlib
import wradlib as wrl
Sumusulat kami pagkatapos ng dalawang utility function para mag-download ng satellite data mula sa DWD's open data server
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
Binibigyang-daan kami ng mga utility na ito na mag-download ng pinakabagong 4 na satellite na imahe, na ang bilang ng mga satellite image na kailangan namin upang makagawa ng mga hula gamit ang aming pretrained na modelo.
Pagkatapos ay maaari naming gamitin ang mga function na nilikha upang makuha ang pinakabagong 4 na mga imahe
RY_latest, RY_latest_timestep = download_data()
Pagkatapos makuha ang mga larawan, ginagamit namin ang paraan ng vis.plot_ppi ng wradlib upang i-plot ang data
for i in range(RY_latest.shape[0]):
wrl.vis.plot_ppi(RY_latest[i])
Na-load na namin ngayon ang aming data. I-load natin ang modelo sa susunod.
Magsisimula kami sa pamamagitan ng pag-import ng mga nauugnay na klase. Gagamitin namin ang TensorFlow sa artikulong ito.
mula sa tensorflow.keras.layers import Input, Conv2D, Activation, Concatenate, Conv2DTranspose, MaxPool2D
mula sa tensorflow.keras.models import Model
Bumuo tayo ng 3 primitive building blocks. Gagamitin ang mga "building block" na ito upang likhain ang buong arkitektura, ayon sa [implementation] na ito(https://github.com/bnsreenu/python_for_microscopists/blob/master/219-unet_model_with_functions_of_blocks.py).
Ang unang bloke ay tumutugma sa sunud-sunod na mga convolutional layer, tinatawag namin itong "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
Ang pangalawang bloke ay ginagamit upang buuin ang mula sa bahagi ng encoder (convolutional block + max pooling). Tinatawag namin itong "encoder_block"
def encoder_block(input, num_filters):
x = conv_block(input, num_filters)
p = MaxPool2D((2,2))(x)
return x,p
Ang ikatlo at huling block ay isang "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
Pinagsasama-sama namin ang mga building block na ito para makabuo ng modelong 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
Huwag mag-atubiling makipaglaro sa pagpapatupad, pagbutihin ito o iakma ito sa iyong mga pangangailangan kung gusto mo itong gamitin para sa ibang bagay.
Ang pagsasanay sa modelong ito ay maaaring tumagal ng maraming oras. Sa kabutihang palad, mayroong isang modelo na tinatawag na Rain-Net, na nilikha batay sa isang U-Net na arkitektura, at dalubhasa sa pag-ulan ngayon.
I-clone natin ang GitHub repository nito
! git clone https://github.com/hydrogo/rainnet.git
Pagkatapos ay dina-download namin ang mga paunang sinanay na timbang para sa modelong ito
!wget -O /content/rainnet/rainnet_weights.h5 https://zenodo.org/record/3630429/files/rainnet_weights.h5
Ang susunod na hakbang ay lumikha ng isang modelo batay sa arkitektura na makikita sa repositoryo pagkatapos ay i-load ang mga timbang na na-download sa modelong ito
import sys
from rainnet import rainnet
model = rainnet.rainnet()
model.load_weights('/content/rainnet/rainnet_weights.h5')
model.summary()
Ang mga larawang na-download namin ay may sukat na 900*900 pixels. Ire-reshape namin ang mga larawang ito upang tumugma sa inaasahang input ng 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
Pagkatapos ay lumikha kami ng isang function na gumagawa ng mga hula.
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
Pagkatapos ay tinawag namin ang function na ito sa data na na-download namin kanina
Y_pred = prediction(model, RY_latest)
Maaari naming i-plot ang mga hula, at i-save ang mga ito upang magamit ang mga resultang na-save upang lumikha ng isang gif na imahe na nagbibigay-daan sa amin upang mailarawan ang mga hula
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')
Binabati kita sa pag-abot nito hanggang dito! Nagagawa mo na ngayong gumamit ng Rain-Net upang gumawa ng mga hula at mailarawan ang mga ito.
Konklusyon
Sa artikulong ito, gumamit kami ng machine learning model (Rain-Net) para gawin ang precipitation nowcasting. Gumamit kami ng arkitektura ng U-Net, na binuo namin gamit ang TensorFlow. Nag-load kami ng pretrained na modelo para mahulaan ang mga satellite image.
Ang pagpapatupad na ito ay maaaring mapabuti sa maraming paraan. Halimbawa:
-
I-fine ang modelo sa iyong dataset
-
Gumamit ng module na nakabatay sa atensyon, gaya ng CBAM (Convolutional Block Attention Module) sa arkitektura.
Mga sanggunian
Halika Sa Isa Sa Aming Mga Libreng Workshop!
Simulan ang iyong karera bilang data scientist sa aming mga libreng workshop, na nakabatay sa isang madaling ibagay na kurikulum at ginagabayan ng mga eksperto sa industriya.