ปัจจุบันนักอุตุนิยมวิทยาประมาณการว่า 90% ของการพยากรณ์อากาศมีความถูกต้องในช่วง 5 วัน การทำนายที่เกิดขึ้นมักจะใช้สองวิธีแยกกัน:
-
วิธีการที่ใช้ฟิสิกส์: วิธีการเหล่านี้ใช้แบบจำลองที่รวมปริมาณที่วัดได้ เช่น ความกดอากาศ การเคลื่อนที่ของเมฆ สภาพท้องฟ้า... โมเดลดังกล่าวสามารถทำนายสภาพอากาศสำหรับวันหรือสัปดาห์ที่กำลังจะมาถึงได้ดี
-
แนวทางที่ปราศจากฟิสิกส์ (อิงตามข้อมูล): แนวทางเหล่านี้ใช้ข้อมูลในอดีตเพื่อสร้างแบบจำลองที่สามารถคาดการณ์ได้ แบบจำลองดังกล่าวแสดงผลลัพธ์ที่ดีในการพยากรณ์อากาศได้นานถึง 6 ชั่วโมงหรือที่เรียกว่าสภาพอากาศในขณะนี้
ในบทความนี้ เราจะพูดถึงแนวทางประเภทที่สอง เราจะพูดคุยถึงรูปแบบต่างๆ ของข้อมูลสภาพอากาศ วิธีใช้ประโยชน์จากการเรียนรู้ของเครื่องเพื่อดำเนินการสภาพอากาศในปัจจุบัน และวิธีที่สถาปัตยกรรมที่พัฒนาขึ้นจะเป็นประโยชน์ต่อการแก้ปัญหาที่คล้ายกันได้อย่างไร
ข้อมูลสำหรับการพยากรณ์สภาพภูมิอากาศ
เนื่องจากแนวทางที่ปราศจากหลักฟิสิกส์ใช้ข้อมูลในอดีต เรามาเริ่มด้วยการดูข้อมูลที่มีอยู่กันดีกว่า
เราจะใช้แหล่งข้อมูลหลักสองแหล่ง:
- ข้อมูลรูปภาพ: ข้อมูลนี้อยู่ในรูปแบบของภาพถ่ายเรดาร์หรือดาวเทียมของพื้นที่ทางภูมิศาสตร์ที่ระบุ ใช้ในการพยากรณ์ปริมาณฝน การเคลื่อนที่ของลม หรือความชื้น
- ข้อมูลแบบตาราง : ข้อมูลนี้อยู่ในรูปแบบของการบันทึกปริมาณที่วัดได้ เช่น อุณหภูมิ ความชื้น หรือความเร็วลม
แม้ว่าแหล่งข้อมูลทั้งสองมีความสำคัญต่อการสร้างแบบจำลองที่มีประสิทธิภาพ แต่เราจะมุ่งเน้นไปที่แหล่งข้อมูลเดิม (ข้อมูลภาพที่รวบรวมจากเรดาร์หรือดาวเทียม) ด้วยเหตุผลที่เรียบง่าย โมเดลที่มีข้อมูลรูปภาพที่ใช้บ่อยที่สุด ได้แก่ Convolutional Neural Networks (CNNs ).
หลังจาก งาน นี้ เราจะใช้สถาปัตยกรรม U-Net เพื่อสร้างโมเดล Nowcasting ของเราเอง
สถาปัตยกรรม
การเริ่มจากสถาปัตยกรรมที่มีอยู่มีประโยชน์หลายประการ เช่น:
สถาปัตยกรรมทำหน้าที่เป็นแนวทางในการสร้างแบบจำลองใหม่ ผู้ที่สร้างสรรค์สถาปัตยกรรมใหม่ๆ ใช้วิธีการลองผิดลองถูกเพื่อให้ได้ผลลัพธ์สุดท้าย การนำผลลัพธ์สุดท้ายกลับมาใช้ใหม่ทำให้เราประหยัดเวลาได้มาก
โดยปกติแล้วโมเดลที่ฝึกไว้ล่วงหน้าจะพร้อมให้ใช้งานได้ทันที เมื่อนักวิจัยเผยแพร่สถาปัตยกรรมใหม่ของพวกเขา พวกเขามักจะเผยแพร่พารามิเตอร์ที่ได้รับการฝึกอบรมด้วยเช่นกัน เพื่อให้ผู้ใช้ไม่ต้องประสบปัญหาในการฝึกอบรม/เพิ่มประสิทธิภาพตั้งแต่เริ่มต้น สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับ โมเดลที่มีขนาดใหญ่มากและกระหายทรัพยากร
ตัวอย่างสถาปัตยกรรมการมองเห็นที่มีชื่อเสียง ได้แก่ :
- LeNet (พารามิเตอร์ 60,000)
- AlexNet (พารามิเตอร์ 60m)
- VGG-16 (พารามิเตอร์ 138m)
ยูเน็ต
U-Net เป็นสถาปัตยกรรมที่ใช้เครือข่ายแบบ Convolutional เต็มรูปแบบ ซึ่งหมายความว่าไม่มีเลเยอร์ที่เชื่อมต่อกันอย่างสมบูรณ์ เปิดตัวครั้งแรกสำหรับงานการแบ่งส่วนภาพทางการแพทย์ ผลลัพธ์เหล่านี้เป็นแรงบันดาลใจให้นักวิจัยขยายไปสู่งานอื่นๆ ในด้านการมองเห็นคอมพิวเตอร์
ในปี 2019 Google ใช้สถาปัตยกรรม U-Net เพื่อสร้างแบบจำลองการพยากรณ์ปริมาณน้ำฝน
ชื่อ “U-Net” มาจากรูปตัว “U” ของสถาปัตยกรรม
เราระบุองค์ประกอบหลักสามประการ:
-
การทำสัญญา / ตัวเข้ารหัส: การสืบทอดของเลเยอร์การบิด/การรวมกลุ่มซึ่งบีบอัดรูปภาพอินพุตให้แสดงขนาดที่เล็กลง
-
สะพาน / คอขวด: ส่วนล่างของ "U" เชื่อมต่อตัวเข้ารหัสกับตัวถอดรหัส มันถูกสร้างขึ้นจากการดำเนินการแบบหมุนวนหลายชุด
-
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])
ตอนนี้เราได้โหลดข้อมูลของเราแล้ว มาโหลดโมเดลกันต่อไป
เราเริ่มต้นด้วยการนำเข้าคลาสที่เกี่ยวข้อง เราจะใช้ 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')
ขอแสดงความยินดีที่มาไกลขนาดนี้! ตอนนี้คุณสามารถใช้ Rain-Net เพื่อคาดการณ์และแสดงภาพได้
บทสรุป
ในบทความนี้ เราได้ใช้โมเดลการเรียนรู้ของเครื่อง (Rain-Net) เพื่อทำการตกตะกอนในขณะนี้ เราใช้สถาปัตยกรรม U-Net ซึ่งเราสร้างขึ้นโดยใช้ TensorFlow เราโหลดแบบจำลองที่ได้รับการฝึกมาล่วงหน้าเพื่อทำนายภาพจากดาวเทียม
การใช้งานนี้สามารถปรับปรุงได้หลายวิธี ตัวอย่างเช่น:
-
ปรับแต่งโมเดลบนชุดข้อมูลของคุณ
-
ใช้โมดูลที่อิงความสนใจ เช่น CBAM (Convolutional Block Attention Module) ในสถาปัตยกรรม
อ้างอิง
เชิญเข้าร่วมเวิร์คช็อปฟรีของเรา!
เริ่มต้นอาชีพของคุณในฐานะนักวิทยาศาสตร์ข้อมูลด้วยเวิร์กช็อปฟรี ซึ่งอิงตามหลักสูตรที่ปรับเปลี่ยนได้และได้รับคำแนะนำจากผู้เชี่ยวชาญในอุตสาหกรรม