LoginSignup
138

More than 5 years have passed since last update.

posted at

updated at

【その1】DeepLearningを使って気象画像から天気予報をする

変更履歴

2016/8/31 AUC計算が「晴」だけしか見ていなかったので、修正

概要

DeepLearningでCNN(畳み込みニューラルネットワーク)といえば、画像処理がメインになるのに、画像処理に関する分析を全くやっていなかったので、今回は 気象画像から天気予報ができるか を検証してみたいと思います。

準備

気象画像の入手

気象画像は高知大学のサイトからぽちぽちダウンロードしました。2015年1月から2016年7月のデータを入手します。使ったのはこのような画像です。
なお、1時間ごとにデータがあるので、17時のデータを入手しました。

fe.16082717.jpg

出典: 高知大学・東京大学・気象庁提供

過去の天気の入手

過去の天気は気象庁のページから入手します。こちらも2015年1月から2016年7月までの日ごとの天気データです。場所は東京で、日中の天気を使用しました。

問題設定

問題としては「前日の17時の日本付近の気象画像から、次の日の晴・雨を予測する」です。
なお、気象庁の天気には「晴後雨」とか「曇」とかありますが、雨が含まれれば「雨」、それ以外は「晴」として扱い、二値分類問題としました。

前処理

明日の天気には、東京付近の雲の動きだけではなく偏西風等の影響もあるので、もっと広い範囲の気象画像が必要ですが、日本から遠く離れた場所の天気は不要でしょう。
なので、画像をトリミングして日本付近のデータにしてあげます。

import numpy as np
from PIL import Image
import datetime as dt

w = 640
h = 480
"""日本付近だけを切り取る設定"""
sw = 320
sh = 65
ew = 540
eh = 320
"""イメージ圧縮"""
is_comp = False

def get_mat(dates=[]):
    """

    :param dates:
    :return:
    """
    l = len(dates)
    if not is_comp:
        wr = ew - sw
        hr = eh - sh
    else:
        wr = 50
        hr = 50

    mat = np.zeros((l,3,wr,hr),dtype=np.float32)
    file_base = base_file_dir + "fe.%s" + base_hour + ".jpg"

    j = 0
    err_dates = []
    for ddd in dates:
        dd = dt.datetime.strptime(ddd,"%Y/%m/%d")
        dd_str = dd.strftime("%y%m%d")
        try:
            im = Image.open(file_base % (dd_str))
            im = im.crop((sw,sh,ew,eh))
            im = im.resize((wr, hr))
            mat0 = np.array(im)
            for i in range(0,3):
                mat[j,i,:,:] = mat0[:,:,i].T
            j += 1
        except:
            err_dates.append(ddd)
            print dd_str + " --> Error!!"
    return mat[0:j],err_dates

日付のリストを受け取って、画像をnumpyの行列にして返し、ついでにエラーが出た日付も返してあげます。
イメージオブジェクトimには画像が入りますが、numpyで行列に直した場合、(幅、高、チャネル)の順になるので、転置している点に注意が必要です。
ここでは、画像(480x640)から日本列島が入る範囲でトリミングを行っています。
以下のような感じ。

test02.jpg

行列にしたのちのデータは各セルに0-255までのデータが入るので、255で割って0から1のデータに変換します。

その後のCNNの学習時間の関係で、画像を圧縮することも考えましたが、今回はやめました。

CNNモデル

畳み込みニューラルネットワークのモデルは従前使用していたものを使用します。
このへんとかこのへんとかこのへんを参照ください。

パラメータ設定としては、以下のようにしています。

params = {"clm_dim":clm_dim,"in_channels":3,"out_channels":3,"row_dim":row_dim,"filt_clm":3,"filt_row":3,"pool_clm":3,"pool_row":3,"batchsize":200,"hidden_dim":500,"n_classes":2}

clm_dimとrow_dimは各画像の幅と高さに対応します。また、チャネル数はRGBなので3としています。また、max poolingを使用します。
なお、フィルタサイズとかプーリングサイズを大きくすると計算時間がかかるようになります。(はまった)

この設定でも手元のmacbook proでは非常に時間がかかります。なので、今回はepoch=50としました。

学習データとテストデータ

非常に計算時間がかかるので、学習データを2015/1/1から2015/12/31の1年間のデータ、テストデータを2016/1/1から2016/7/31までとしています。
これでも時間かかるけど。画像処理恐ろしい・・・

モデルの学習とテスト精度

学習の進み方とテスト精度は以下のような形になりました。
train_test.png

また学習精度としては伸びそうだけど、テスト精度が追いついていないなぁ。

テスト結果

AUCで 0.78 0.70 で各種指標が以下。

Precision Recall F-Score
0.54 0.67 0.6
0.83 0.74 0.78
平均 0.74 0.72 0.72

まぁざくっとやった割には結構いい感じではないでしょうか。
ただ、雨と予測したうち、実際に雨だったのは54%と低めです。

雨確率で降順に並べて、実績の雨の比率と晴の比率をプロットしてみましょう。

  • 雨累積 = (確率高い順での雨日数)/(合計雨日数)
  • 晴累積 = (確率低い順での晴日数)/(合計晴日数)

test_ruiseki.png

ちゃんとランダムではなく予測しているっぽい。
テストデータ中の実際の雨の比率は30%、晴の比率は60%なので、そうでしょう。

曇の扱い

精度が上がらない要因の一つに「曇」の扱いがあると思われます。
「晴れのち曇」の場合とか「曇一時雨」とかがあり、実際データ中の曇の比率は70%を超えます。(曇すぎ)
今回前者を晴、後者を雨として扱っています。そのため、微妙な状況というのはどちらかわからないのだと思われます。このへんは課題です。
ただ、今回の結果では、明らかな雨については結構な精度で当たっているようです。

三値分類にすると曇が支配的になってしまうので、難しい問題になります。

気象予報士さんはすごいですね。

今後

アルゴリズム的にはこれでいこうかなぁとは思っていますが、データについては、例えば前日の画像との差分を取るとか、ベースになる地図のピクセルを抜くとか考えられます。
ちょぼちょぼとやっていこうかなぁと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
138