요즘 기상학자들은 5일 동안의 일기예보 중 90%가 정확하다고 추정합니다. 예측은 일반적으로 두 가지 별도의 방법을 기반으로 합니다.
-
물리학 기반 접근 방식: 이러한 접근 방식은 압력, 구름의 움직임, 하늘 상태 등 측정 가능한 양을 통합하는 모델을 사용합니다. 이러한 모델은 향후 며칠 또는 몇 주 동안의 날씨를 예측하는 데 적합합니다.
-
물리학이 필요 없는(데이터 기반) 접근 방식: 이러한 접근 방식은 과거 데이터를 사용하여 예측할 수 있는 모델을 만듭니다. 이러한 모델은 최대 6시간 동안의 날씨를 예측하거나 현재 날씨를 예측하는 데 좋은 결과를 보여줍니다.
이 글에서는 접근 방식의 두 번째 범주에 대해 논의하겠습니다. 다양한 형식의 기상 데이터, 기계 학습을 활용하여 기상 예보를 수행하는 방법, 개발된 아키텍처가 유사한 문제를 해결하는 데 어떻게 도움이 될 수 있는지에 대해 논의할 것입니다.
기후 예측을 위한 데이터
물리학을 사용하지 않는 접근 방식은 과거 데이터를 사용하므로 먼저 사용 가능한 데이터를 살펴보겠습니다.
우리는 두 가지 주요 데이터 소스를 사용할 것입니다.
- 이미지 데이터: 이 데이터는 특정 지리적 영역의 레이더 또는 위성 이미지 형식을 취합니다. 강수량, 바람의 움직임, 습도를 예측하는 데 사용됩니다.
- 표 형식의 데이터 : 이 데이터는 온도, 습도, 풍속 등 측정 가능한 양을 기록하는 형식을 취합니다.
강력한 모델을 구축하려면 두 데이터 소스가 모두 중요하지만 단순화를 위해 전자(레이더 또는 위성에서 수집한 이미지 데이터)에 중점을 둘 것입니다. 이미지 데이터에 가장 일반적으로 사용되는 모델은 컨볼루셔널 신경망(CNN)입니다. ).
이 작업에 이어 U-Net 아키텍처를 사용하여 자체 Nowcasting 모델을 구축할 예정입니다.
건축학
기존 아키텍처에서 시작하는 것은 다음과 같은 여러 가지 이유로 도움이 됩니다.
아키텍처는 새로운 모델을 생성하기 위한 지침 역할을 합니다. 새로운 아키텍처를 만드는 사람들은 최종 결과를 얻기 위해 시행착오 접근 방식을 채택합니다. 최종 결과를 재사용하면 많은 시간을 절약할 수 있습니다.
사전 학습된 모델은 일반적으로 즉시 사용할 수 있습니다. 연구자들이 새로운 아키텍처를 게시할 때 일반적으로 훈련된 매개변수도 게시하므로 사용자는 처음부터 훈련/최적화하는 수고를 겪을 필요가 없습니다. 이는 매우 크고 리소스가 부족한 모델에 특히 유용합니다.
유명한 비전 아키텍처의 예는 다음과 같습니다.
- LeNet(60k 매개변수)
- AlexNet(60m 매개변수)
- VGG-16(138m 매개변수)
유넷
U-Net은 완전 컨벌루션 네트워크를 기반으로 하는 아키텍처입니다. 즉, 완전히 연결된 레이어가 없습니다. 의료 영상 분할 작업을 위해 처음 도입되었습니다. 이러한 결과는 연구자들이 이를 컴퓨터 비전의 다른 작업으로 확장하도록 영감을 주었습니다.
2019년에 Google은 U-Net 기반 아키텍처를 사용하여 강수량 예측 모델을 만들었습니다.
"U-Net"이라는 이름은 아키텍처의 "U" 모양에서 유래되었습니다.
우리는 세 가지 주요 구성 요소를 식별합니다.
-
계약/인코더: 입력 이미지를 더 작은 크기 표현으로 압축하는 컨볼루션/풀링 레이어의 연속입니다.
-
브리지/병목 현상: "U"의 하단 부분은 인코더와 디코더를 연결합니다. 일련의 컨볼루션 작업으로 구성됩니다.
-
디컨트랙팅/디코더: 병목 현상의 출력을 "압축 해제"하는 업컨볼루션 및 컨볼루션 레이어의 연속입니다.
U-Net의 아키텍처는 지금까지 자동 인코더처럼 보입니다. 그러나 차이점은 인코더와 디코더 사이를 통과하는 정보에 있습니다. 이 정보는 인코더의 컨볼루션 결과와 디코더의 업컨볼루션 결과를 연결하여 전달됩니다. 이 수정을 통해 해상도가 향상되고 모델이 공간적으로 더 정확한 출력을 출력할 수 있습니다(출력의 픽셀 위치가 더 정확해지며 연결을 포함하지 않은 모델에서 발생한 문제가 해결됨). 연결은 대칭적으로 수행됩니다.
강수량 현재 캐스팅을 위한 U-Net 모델 구축
이번 섹션에서는 위성영상을 통해 날씨를 예측하는 U-Net 모델을 구축해보겠습니다. Rain-Net이라는 사전 훈련된 모델을 사용하겠습니다.
아래 코드는 이 colab에서 사용할 수 있습니다.
먼저 기상 레이더 데이터 처리를 위한 오픈 소스 라이브러리인 wradlib를 설치합니다.
!pip install wradlib
import wradlib as wrl
그런 다음 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()
이미지를 가져온 후 wradlib의 vis.plot_ppi 메서드를 사용하여 데이터를 플롯합니다.
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개의 기본 빌딩 블록을 구성해 보겠습니다. 이러한 "빌딩 블록"은 이 구현에 따라 전체 아키텍처를 생성하는 데 사용됩니다.
첫 번째 블록은 연속적인 컨볼루셔널 레이어에 해당합니다. 우리는 이를 "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"(업컨볼루션 + 연결 + 컨볼루션)입니다.
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
구현을 자유롭게 가지고 놀고, 개선하고, 다른 용도로 사용하려는 경우 필요에 맞게 조정하세요.
이 모델을 훈련하는 데는 많은 시간이 걸릴 수 있습니다. 운 좋게도 U-Net 아키텍처를 기반으로 제작되었으며 현재 강수량 관측에 특화된 Rain-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)을 사용하여 강수량 현재 예측을 수행했습니다. 우리는 TensorFlow를 사용하여 구축한 U-Net 아키텍처를 사용했습니다. 우리는 위성 이미지를 예측하기 위해 사전 훈련된 모델을 로드했습니다.
이 구현은 여러 가지 방법으로 개선될 수 있습니다. 예를 들어:
-
데이터세트의 모델을 미세 조정합니다.
-
아키텍처에서 CBAM(Convolutional Block Attention Module)과 같은 주의 기반 모듈을 사용합니다.
참고자료
무료 워크숍에 오세요!
적응형 커리큘럼을 기반으로 업계 전문가가 안내하는 무료 워크숍을 통해 데이터 과학자로서의 경력을 시작해 보세요.