Dự báo lượng mưa bằng Machine Learning

ML
DL
CNN
Dự báo thời tiết
UNet
Dự báo lượng mưa bằng Machine Learning cover image

Ngày nay, các nhà khí tượng học ước tính rằng 90% dự đoán thời tiết là chính xác trong khoảng thời gian 5 ngày. Các dự đoán được đưa ra thường dựa trên hai phương pháp riêng biệt:

  1. Phương pháp tiếp cận dựa trên vật lý: Các phương pháp này sử dụng các mô hình tích hợp các đại lượng có thể đo lường được như áp suất, chuyển động của mây, điều kiện bầu trời… Những mô hình này rất tốt trong việc dự đoán thời tiết cho những ngày hoặc tuần sắp tới.

  2. Cách tiếp cận không cần vật lý (dựa trên dữ liệu): Những cách tiếp cận này sử dụng dữ liệu lịch sử để tạo ra các mô hình có thể đưa ra dự đoán. Những mô hình như vậy cho kết quả tốt trong việc dự đoán thời tiết trong tối đa 6 giờ hoặc cái được gọi là dự báo thời tiết hiện tại.

Trong bài viết này, chúng ta sẽ thảo luận về loại phương pháp tiếp cận thứ hai. Chúng ta sẽ thảo luận về các định dạng khác nhau của dữ liệu thời tiết, cách học máy có thể được tận dụng để thực hiện dự báo thời tiết và cách các kiến ​​trúc được phát triển có thể mang lại lợi ích cho việc giải quyết các vấn đề tương tự.

Dữ liệu dự báo khí hậu

Vì các phương pháp tiếp cận phi vật lý sử dụng dữ liệu lịch sử nên hãy bắt đầu bằng cách xem xét dữ liệu có sẵn.

Chúng tôi sẽ sử dụng hai nguồn dữ liệu chính:

  1. Dữ liệu hình ảnh: Dữ liệu này có dạng hình ảnh radar hoặc vệ tinh của một khu vực địa lý cụ thể. Nó được sử dụng để dự đoán lượng mưa, chuyển động của gió hoặc độ ẩm.

Satellite Image

  1. Dữ liệu dạng bảng: Dữ liệu này có dạng bản ghi các đại lượng có thể đo lường được như nhiệt độ, độ ẩm hoặc tốc độ gió.

Tabular Data

Mặc dù cả hai nguồn dữ liệu đều quan trọng để xây dựng các mô hình mạnh mẽ, nhưng chúng tôi sẽ tập trung vào nguồn dữ liệu trước (dữ liệu hình ảnh được thu thập từ radar hoặc vệ tinh) vì lý do đơn giản. Các mô hình có dữ liệu hình ảnh được sử dụng phổ biến nhất là Mạng thần kinh chuyển đổi (CNNs ).

Sau công việc, chúng tôi sẽ sử dụng kiến ​​trúc U-Net để xây dựng mô hình truyền hình trực tuyến của riêng mình.

Ngành kiến ​​​​trúc

Bắt đầu từ một kiến ​​trúc hiện có sẽ hữu ích vì nhiều lý do, trong đó:

Kiến trúc đóng vai trò là hướng dẫn để tạo ra các mô hình mới. Những người tạo ra kiến ​​trúc mới áp dụng phương pháp thử và sai để đạt được kết quả cuối cùng. Bằng cách sử dụng lại kết quả cuối cùng của họ, chúng ta có thể tiết kiệm rất nhiều thời gian.

Các mô hình được huấn luyện trước thường có sẵn để sử dụng ngay. Khi các nhà nghiên cứu xuất bản kiến ​​trúc mới của họ, họ cũng thường xuất bản các tham số đã được đào tạo để người dùng không phải gặp khó khăn trong việc đào tạo/tối ưu hóa từ đầu. Điều này đặc biệt hữu ích cho các mô hình rất lớn, khát tài nguyên.

Ví dụ về kiến ​​trúc tầm nhìn nổi tiếng bao gồm:

  • LeNet (tham số 60k)

LeNet

  • AlexNet (tham số 60m)

AlexNet

  • VGG-16 (thông số 138m)

VGG-16

##U-Net

U-Net là một kiến ​​trúc dựa trên mạng tích chập hoàn toàn, nghĩa là nó không có bất kỳ lớp nào được kết nối đầy đủ. Nó lần đầu tiên được giới thiệu cho nhiệm vụ phân đoạn hình ảnh y tế. Những kết quả này đã truyền cảm hứng cho các nhà nghiên cứu mở rộng nó sang các nhiệm vụ khác trong thị giác máy tính.

Năm 2019, Google đã sử dụng kiến ​​trúc U-Net để tạo mô hình dự báo lượng mưa.

Cái tên “U-Net” xuất phát từ hình dạng “U” trong kiến ​​trúc của nó.

U-net Architecture

Chúng tôi xác định ba thành phần chính:

  1. Hợp đồng / Bộ mã hóa: Tiếp nối các lớp tích chập/gộp chung để nén hình ảnh đầu vào thành một biểu diễn có kích thước nhỏ hơn.

  2. Cầu nối/Nút thắt cổ chai: Phần dưới cùng của chữ “U” kết nối bộ mã hóa với bộ giải mã. Nó được hình thành bởi một loạt các hoạt động tích chập.

  3. Giải nén / Giải mã : Sự kế tiếp của các lớp chập lên và lớp chập, giúp “giải nén” đầu ra của nút cổ chai.

Cho đến nay, kiến ​​trúc của U-Net trông giống như một bộ mã hóa tự động. Tuy nhiên, sự khác biệt nằm ở việc truyền thông tin giữa bộ mã hóa và bộ giải mã. Thông tin này được truyền bằng cách ghép các kết quả của phép xoắn từ bộ mã hóa với kết quả của phép xoắn lên của bộ giải mã. Sửa đổi này nâng cao độ phân giải và cho phép mô hình xuất ra đầu ra chính xác hơn về mặt không gian (vị trí của các pixel trong đầu ra sẽ chính xác hơn, giải quyết vấn đề xảy ra trong các mô hình không bao gồm nối). Việc nối được thực hiện đối xứng.

Xây dựng mô hình U-Net để dự báo lượng mưa hiện tại

Trong phần này chúng ta sẽ xây dựng mô hình U-Net để dự đoán thời tiết từ ảnh vệ tinh. Chúng tôi sẽ sử dụng mô hình được đào tạo trước có tên là Rain-Net.

Mã bên dưới có sẵn trong colab.

Trước tiên, chúng tôi cài đặt wradlib, Thư viện nguồn mở để xử lý dữ liệu radar thời tiết

!pip install wradlib
import wradlib as wrl

Sau đó, chúng tôi viết hai hàm tiện ích để tải xuống dữ liệu vệ tinh từ máy chủ dữ liệu mở của DWD


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

Các tiện ích này cho phép chúng ta tải xuống 4 ảnh vệ tinh mới nhất, đây là số lượng ảnh vệ tinh mà chúng ta cần để đưa ra dự đoán với mô hình đã được huấn luyện trước của mình.

Sau đó chúng ta có thể sử dụng các hàm đã tạo để lấy 4 hình ảnh mới nhất


RY_latest, RY_latest_timestep = download_data()

Sau khi có được hình ảnh, chúng tôi sử dụng phương thức vis.plot_ppi của wradlib để vẽ dữ liệu

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

VIS Radar

Bây giờ chúng tôi đã tải dữ liệu của mình. Hãy tải mô hình tiếp theo.

Chúng tôi bắt đầu bằng cách nhập các lớp có liên quan. Chúng tôi sẽ sử dụng TensorFlow trong bài viết này.

từ tensorflow.keras.layers nhập Đầu vào, Conv2D, Kích hoạt, Ghép nối, Conv2DTranspose, MaxPool2D

từ mô hình nhập tensorflow.keras.models

Hãy xây dựng 3 khối xây dựng nguyên thủy. Theo [cách triển khai] này, những "khối xây dựng" này sẽ được dùng để tạo ra toàn bộ kiến ​​trúc (https://github.com/hydrogo/rainnet).

Khối đầu tiên tương ứng với sự nối tiếp của các lớp chập, chúng tôi gọi là "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

Khối thứ hai được sử dụng để xây dựng phần từ bộ mã hóa (khối chập + gộp tối đa). Chúng tôi gọi nó là “encode_block”

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

Khối thứ ba và cuối cùng là một “decode_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

Chúng tôi kết hợp các khối xây dựng này để xây dựng mô hình 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

Hãy thoải mái thử nghiệm việc triển khai, cải thiện hoặc điều chỉnh nó cho phù hợp với nhu cầu của bạn nếu bạn muốn sử dụng nó cho mục đích khác.

Việc đào tạo mô hình này có thể mất rất nhiều thời gian. May mắn thay, có một mô hình tên là Rain-Net, được tạo ra dựa trên kiến ​​trúc U-Net và chuyên về phát sóng lượng mưa.

Hãy sao chép kho lưu trữ GitHub của nó

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

Sau đó chúng tôi tải xuống các trọng số đã được huấn luyện trước cho mô hình này

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

Bước tiếp theo là tạo một mô hình dựa trên kiến ​​trúc được tìm thấy trên kho lưu trữ, sau đó tải các trọng số được tải xuống mô hình này

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

Hình ảnh chúng tôi tải xuống có kích thước 900*900 pixel. Chúng tôi sẽ định hình lại những hình ảnh này để phù hợp với đầu vào dự kiến ​​của 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

Sau đó chúng tôi tạo ra một hàm đưa ra dự đoán.

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

Sau đó chúng tôi gọi hàm này trên dữ liệu chúng tôi đã tải xuống trước đó

Y_pred = prediction(model, RY_latest)

Chúng ta có thể vẽ các dự đoán và lưu chúng để sử dụng các kết quả đã lưu để tạo hình ảnh gif cho phép chúng ta hình dung các dự đoán

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

Xin chúc mừng vì đã tiến xa đến mức này! Bây giờ bạn có thể sử dụng Rain-Net để đưa ra dự đoán và hình dung chúng.

Phần kết luận

Trong bài viết này, chúng tôi đã sử dụng mô hình học máy (Rain-Net) để thực hiện dự báo lượng mưa hiện nay. Chúng tôi đã sử dụng kiến ​​trúc U-Net mà chúng tôi xây dựng bằng TensorFlow. Chúng tôi đã tải một mô hình đã được huấn luyện trước để dự đoán hình ảnh vệ tinh.

Việc thực hiện này có thể được cải thiện theo nhiều cách. Ví dụ:

  1. Tinh chỉnh mô hình trên tập dữ liệu của bạn

  2. Sử dụng mô-đun dựa trên sự chú ý, chẳng hạn như CBAM (Mô-đun chú ý khối chuyển đổi) trong kiến ​​trúc.

Tài liệu tham khảo

Hãy đến với một trong những buổi hội thảo miễn phí của chúng tôi!

Bắt đầu sự nghiệp của bạn với tư cách là nhà khoa học dữ liệu với hội thảo miễn phí của chúng tôi, dựa trên chương trình giảng dạy có thể thích ứng và được hướng dẫn bởi các chuyên gia trong ngành.


Career Services background pattern

Dịch vụ nghề nghiệp

Contact Section background image

Hãy giữ liên lạc

Code Labs Academy © 2024 Đã đăng ký Bản quyền.