การเร่งรัด Nowcasting ด้วยการเรียนรู้ของเครื่อง

ML
DL
CNN
พยากรณ์อากาศ
UNet
การเร่งรัด Nowcasting ด้วยการเรียนรู้ของเครื่อง cover image

ปัจจุบันนักอุตุนิยมวิทยาประมาณการว่า 90% ของการพยากรณ์อากาศมีความถูกต้องในช่วง 5 วัน การทำนายที่เกิดขึ้นมักจะใช้สองวิธีแยกกัน:

  1. วิธีการที่ใช้ฟิสิกส์: วิธีการเหล่านี้ใช้แบบจำลองที่รวมปริมาณที่วัดได้ เช่น ความกดอากาศ การเคลื่อนที่ของเมฆ สภาพท้องฟ้า... โมเดลดังกล่าวสามารถทำนายสภาพอากาศสำหรับวันหรือสัปดาห์ที่กำลังจะมาถึงได้ดี

  2. แนวทางที่ปราศจากฟิสิกส์ (อิงตามข้อมูล): แนวทางเหล่านี้ใช้ข้อมูลในอดีตเพื่อสร้างแบบจำลองที่สามารถคาดการณ์ได้ แบบจำลองดังกล่าวแสดงผลลัพธ์ที่ดีในการพยากรณ์อากาศได้นานถึง 6 ชั่วโมงหรือที่เรียกว่าสภาพอากาศในขณะนี้

ในบทความนี้ เราจะพูดถึงแนวทางประเภทที่สอง เราจะพูดคุยถึงรูปแบบต่างๆ ของข้อมูลสภาพอากาศ วิธีใช้ประโยชน์จากการเรียนรู้ของเครื่องเพื่อดำเนินการสภาพอากาศในปัจจุบัน และวิธีที่สถาปัตยกรรมที่พัฒนาขึ้นจะเป็นประโยชน์ต่อการแก้ปัญหาที่คล้ายกันได้อย่างไร

ข้อมูลสำหรับการพยากรณ์สภาพภูมิอากาศ

เนื่องจากแนวทางที่ปราศจากหลักฟิสิกส์ใช้ข้อมูลในอดีต เรามาเริ่มด้วยการดูข้อมูลที่มีอยู่กันดีกว่า

เราจะใช้แหล่งข้อมูลหลักสองแหล่ง:

  1. ข้อมูลรูปภาพ: ข้อมูลนี้อยู่ในรูปแบบของภาพถ่ายเรดาร์หรือดาวเทียมของพื้นที่ทางภูมิศาสตร์ที่ระบุ ใช้ในการพยากรณ์ปริมาณฝน การเคลื่อนที่ของลม หรือความชื้น

Satellite Image

  1. ข้อมูลแบบตาราง : ข้อมูลนี้อยู่ในรูปแบบของการบันทึกปริมาณที่วัดได้ เช่น อุณหภูมิ ความชื้น หรือความเร็วลม

Tabular Data

แม้ว่าแหล่งข้อมูลทั้งสองมีความสำคัญต่อการสร้างแบบจำลองที่มีประสิทธิภาพ แต่เราจะมุ่งเน้นไปที่แหล่งข้อมูลเดิม (ข้อมูลภาพที่รวบรวมจากเรดาร์หรือดาวเทียม) ด้วยเหตุผลที่เรียบง่าย โมเดลที่มีข้อมูลรูปภาพที่ใช้บ่อยที่สุด ได้แก่ Convolutional Neural Networks (CNNs ).

หลังจาก งาน นี้ เราจะใช้สถาปัตยกรรม U-Net เพื่อสร้างโมเดล Nowcasting ของเราเอง

สถาปัตยกรรม

การเริ่มจากสถาปัตยกรรมที่มีอยู่มีประโยชน์หลายประการ เช่น:

สถาปัตยกรรมทำหน้าที่เป็นแนวทางในการสร้างแบบจำลองใหม่ ผู้ที่สร้างสรรค์สถาปัตยกรรมใหม่ๆ ใช้วิธีการลองผิดลองถูกเพื่อให้ได้ผลลัพธ์สุดท้าย การนำผลลัพธ์สุดท้ายกลับมาใช้ใหม่ทำให้เราประหยัดเวลาได้มาก

โดยปกติแล้วโมเดลที่ฝึกไว้ล่วงหน้าจะพร้อมให้ใช้งานได้ทันที เมื่อนักวิจัยเผยแพร่สถาปัตยกรรมใหม่ของพวกเขา พวกเขามักจะเผยแพร่พารามิเตอร์ที่ได้รับการฝึกอบรมด้วยเช่นกัน เพื่อให้ผู้ใช้ไม่ต้องประสบปัญหาในการฝึกอบรม/เพิ่มประสิทธิภาพตั้งแต่เริ่มต้น สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับ โมเดลที่มีขนาดใหญ่มากและกระหายทรัพยากร

ตัวอย่างสถาปัตยกรรมการมองเห็นที่มีชื่อเสียง ได้แก่ :

  • LeNet (พารามิเตอร์ 60,000)

LeNet

  • AlexNet (พารามิเตอร์ 60m)

AlexNet

  • VGG-16 (พารามิเตอร์ 138m)

VGG-16

ยูเน็ต

U-Net เป็นสถาปัตยกรรมที่ใช้เครือข่ายแบบ Convolutional เต็มรูปแบบ ซึ่งหมายความว่าไม่มีเลเยอร์ที่เชื่อมต่อกันอย่างสมบูรณ์ เปิดตัวครั้งแรกสำหรับงานการแบ่งส่วนภาพทางการแพทย์ ผลลัพธ์เหล่านี้เป็นแรงบันดาลใจให้นักวิจัยขยายไปสู่งานอื่นๆ ในด้านการมองเห็นคอมพิวเตอร์

ในปี 2019 Google ใช้สถาปัตยกรรม U-Net เพื่อสร้างแบบจำลองการพยากรณ์ปริมาณน้ำฝน

ชื่อ “U-Net” มาจากรูปตัว “U” ของสถาปัตยกรรม

U-net Architecture

เราระบุองค์ประกอบหลักสามประการ:

  1. การทำสัญญา / ตัวเข้ารหัส: การสืบทอดของเลเยอร์การบิด/การรวมกลุ่มซึ่งบีบอัดรูปภาพอินพุตให้แสดงขนาดที่เล็กลง

  2. สะพาน / คอขวด: ส่วนล่างของ "U" เชื่อมต่อตัวเข้ารหัสกับตัวถอดรหัส มันถูกสร้างขึ้นจากการดำเนินการแบบหมุนวนหลายชุด

  3. Decontracting / Decoder : การสืบทอดของ upconvolutions และ convolution layer ซึ่ง "ขยาย" เอาต์พุตของคอขวด

สถาปัตยกรรมของ U-Net ดูเหมือนตัวเข้ารหัสอัตโนมัติจนถึงตอนนี้ อย่างไรก็ตาม ความแตกต่างอยู่ที่ข้อมูลที่ส่งผ่านระหว่างตัวเข้ารหัสและตัวถอดรหัส ข้อมูลนี้ถูกส่งผ่านโดยการเชื่อมโยงผลลัพธ์ของการโน้มน้าวใจจากตัวเข้ารหัสกับผลลัพธ์ของการโน้มน้าวใจของตัวถอดรหัส การปรับเปลี่ยนนี้ช่วยเพิ่มความละเอียด และช่วยให้แบบจำลองสามารถส่งออกเอาต์พุตที่มีความแม่นยำเชิงพื้นที่มากขึ้น (ตำแหน่งของพิกเซลในเอาต์พุตจะแม่นยำยิ่งขึ้น ซึ่งเป็นการแก้ปัญหาที่เกิดขึ้นในแบบจำลองที่ไม่มีการต่อข้อมูลเข้าด้วยกัน) การต่อข้อมูลทำได้แบบสมมาตร

การสร้างแบบจำลอง U-Net สำหรับการตกตะกอน Nowcasting

ในส่วนนี้เราจะสร้างแบบจำลอง U-Net เพื่อทำนายสภาพอากาศจากภาพถ่ายดาวเทียม เราจะใช้โมเดลที่ได้รับการฝึกล่วงหน้าชื่อว่า Rain-Net

โค้ดด้านล่างมีอยู่ใน colab นี้

ก่อนอื่นเราจะติดตั้ง wradlib ซึ่งเป็นไลบรารีโอเพ่นซอร์สสำหรับการประมวลผลข้อมูลเรดาร์สภาพอากาศ

!pip install wradlib
import wradlib as wrl

จากนั้นเราจะเขียนฟังก์ชันยูทิลิตี้ 2 รายการเพื่อดาวน์โหลดข้อมูลดาวเทียมจาก เซิร์ฟเวอร์ข้อมูลแบบเปิดของ 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

โปรแกรมอรรถประโยชน์เหล่านี้ทำให้เราสามารถดาวน์โหลดภาพดาวเทียมล่าสุด 4 ภาพ ซึ่งเป็นจำนวนภาพดาวเทียมที่เราต้องใช้ในการพยากรณ์ด้วยแบบจำลองที่เราฝึกไว้ล่วงหน้า

จากนั้นเราสามารถใช้ฟังก์ชั่นที่สร้างขึ้นเพื่อรับ 4 ภาพล่าสุด


RY_latest, RY_latest_timestep = download_data()

หลังจากได้รับรูปภาพแล้ว เราใช้วิธี vis.plot_ppi ของ wradlib เพื่อพล็อตข้อมูล

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

VIS Radar

ตอนนี้เราได้โหลดข้อมูลของเราแล้ว มาโหลดโมเดลกันต่อไป

เราเริ่มต้นด้วยการนำเข้าคลาสที่เกี่ยวข้อง เราจะใช้ TensorFlow ในบทความนี้

จาก tensorflow.keras.layers นำเข้าอินพุต, Conv2D, การเปิดใช้งาน, เชื่อมต่อ, Conv2DTranspose, MaxPool2D

จาก tensorflow.keras.models โมเดลการนำเข้า

มาสร้างบล็อคดั้งเดิม 3 แบบกัน "แบบเอกสารสำเร็จรูป" เหล่านี้จะถูกนำมาใช้เพื่อสร้างสถาปัตยกรรมทั้งหมด ตาม การนำไปปฏิบัติ นี้

บล็อกแรกสอดคล้องกับการสืบทอดของเลเยอร์ convolutional เราเรียกมันว่า "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

บล็อกที่สองใช้เพื่อสร้างจากส่วนตัวเข้ารหัส (บล็อกแบบหมุน + การรวมสูงสุด) เราเรียกมันว่า “encoder_block”

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

บล็อกที่สามและสุดท้ายคือ “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

เรารวมบล็อคส่วนประกอบเหล่านี้เพื่อสร้างโมเดล 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

คุณสามารถทดลองใช้งาน ปรับปรุง หรือปรับให้เข้ากับความต้องการของคุณได้ตามใจชอบ หากคุณต้องการใช้เพื่อสิ่งอื่น

การฝึกโมเดลนี้อาจใช้เวลานาน โชคดีที่มีแบบจำลองที่เรียกว่า Rain-Net ซึ่งสร้างขึ้นจากสถาปัตยกรรม U-Net และมีความเชี่ยวชาญในการตกตะกอนในขณะนี้

มาโคลนพื้นที่เก็บข้อมูล GitHub กันดีกว่า

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

จากนั้นเราจะดาวน์โหลดตุ้มน้ำหนักที่ฝึกไว้ล่วงหน้าสำหรับรุ่นนี้

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

ขั้นตอนต่อไปคือการสร้างแบบจำลองตามสถาปัตยกรรมที่พบในพื้นที่เก็บข้อมูล จากนั้นโหลดน้ำหนักที่ดาวน์โหลดมายังแบบจำลองนี้

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

รูปภาพที่เราดาวน์โหลดมีขนาด 900*900 พิกเซล เราจะปรับรูปร่างรูปภาพเหล่านี้ใหม่เพื่อให้ตรงกับอินพุตที่คาดหวังของ 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

จากนั้นเราจะสร้างฟังก์ชันที่ทำการทำนาย

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

จากนั้นเราจะเรียกใช้ฟังก์ชันนี้กับข้อมูลที่เราดาวน์โหลดมาก่อนหน้านี้

Y_pred = prediction(model, RY_latest)

เราสามารถวางแผนการทำนายและบันทึกเพื่อใช้ผลลัพธ์ที่บันทึกไว้เพื่อสร้างภาพ GIF ที่ช่วยให้เราเห็นภาพการทำนาย

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

ขอแสดงความยินดีที่มาไกลขนาดนี้! ตอนนี้คุณสามารถใช้ Rain-Net เพื่อคาดการณ์และแสดงภาพได้

บทสรุป

ในบทความนี้ เราได้ใช้โมเดลการเรียนรู้ของเครื่อง (Rain-Net) เพื่อทำการตกตะกอนในขณะนี้ เราใช้สถาปัตยกรรม U-Net ซึ่งเราสร้างขึ้นโดยใช้ TensorFlow เราโหลดแบบจำลองที่ได้รับการฝึกมาล่วงหน้าเพื่อทำนายภาพจากดาวเทียม

การใช้งานนี้สามารถปรับปรุงได้หลายวิธี ตัวอย่างเช่น:

  1. ปรับแต่งโมเดลบนชุดข้อมูลของคุณ

  2. ใช้โมดูลที่อิงความสนใจ เช่น CBAM (Convolutional Block Attention Module) ในสถาปัตยกรรม

อ้างอิง

เชิญเข้าร่วมเวิร์คช็อปฟรีของเรา!

เริ่มต้นอาชีพของคุณในฐานะนักวิทยาศาสตร์ข้อมูลด้วยเวิร์กช็อปฟรี ซึ่งอิงตามหลักสูตรที่ปรับเปลี่ยนได้และได้รับคำแนะนำจากผู้เชี่ยวชาญในอุตสาหกรรม


Career Services background pattern

บริการด้านอาชีพ

Contact Section background image

มาติดต่อกันกันเถอะ

Code Labs Academy © 2024 สงวนลิขสิทธิ์.