はじめに
これまで、除雪の完全自動化を実現するために、機械学習を用いて積雪深を識別する取り組みをしてきました。
(降雪量という言葉があるように積雪量もあるだろうと思っていたのですが、正しい用語としては積雪深だそうです。なのでこれからは積雪深と書いていきます)
今回から画像以外を入力とした学習をやってみたいなと思っていたところ、ちょうど気象庁のホームページに47都道府県の50年分の気象データが公開されていたので、これを使って簡単な天気予報ができないかと考えました。
現在ニュースで見るような天気予報の仕組みを調べてみたところ、地球大気や海洋/陸地を分割し、各観測所から送られてくるデータを用いる他、物理学や科学の法則に基づいて将来の天気状態を予報するというもののようです。
スケールがものすごく大きいので同じことをやるには無理がありますが、各地点のこれまでの気象データを用いれば個人でも予測することができると思いませんか?
今回やること
そこで除雪DXに向けて、過去の札幌市の気象情報から“どのくらい雪が積もるのか”を予測することができないか何週かに分けて考えてみます。
積雪深を得る方法として、入力が気温、湿度、降水量等の数値データとし、出力が積雪深となるように求めるには回帰による分析が良いかなと思いました。
回帰分析とは連続する値に対して、次の値を予測することができます。
例えば、売上高を予測することができます。

画像処理の画像を入力とした回帰は大学で触れたことがあるのですが、数値のみを入力とする回帰は初めてなので、探り探りやっていきます。
GraphCast
今回やろうとしている気象データに基づいて気候を予測するモデルを調べてみると、2024年12月にGoogle DeepMindがGraphCastという数値予報モデルを開発したというニュースを見つけました。
このGraphCastが従来の数値予報モデルよりもさらに高精度だそうです。

データ可視化
今回収集したデータは気圧、気温、湿度、降水量、降雪量、積雪深の6つのデータを約1年分収集しました。
収集したデータのうち、積雪深と相互に関係がある気象現象が何か可視化してみます。
seaborn
Pythonではデータ可視化のライブラリとしてmatplotlibが有名ですが、seabornというライブラリもあるみたいです。
seabornはmatplotlibよりも綺麗に簡単に可視化することができるライブラリということなので使ってみました。
さらにseabornにはヒートマップ関数というものがあるので、今回出力する積雪深と最も関係が強い要素が何かを可視化します。
from IPython.display import display
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import sys, os
weather_data_path = sys.argv[1]
out_dir_path = pathlib.Path(sys.argv[2])
if not os.path.exists(out_dir_path): os.mkdir(out_dir_path)
df = pd.read_csv(weather_data_path)
display(df.head()) #データ配列を確認
heat_map = df.corr(method="pearson")
sns.heatmap(heat_map, center=0, square = True, annot=True, cmap="OrRd",fmt="1.1f") #ヒートマップ関数
plt.savefig(out_dir_path/ 'heat_map.png', bbox_inches="tight")
これだけでデータの関係を可視化することができるのは便利ですね。

画像が小さくて見づらいかもしれないですが、一番右の積雪深(snow_depth)と最も関係が強い要素は降雪量(snow_falling)で0.4という値を得られました。
なので、今回は降雪量を入力として、出力が積雪深となるように方法を検討します。
scikit-learn
入力が降雪量で、出力が積雪深となるよう線形回帰で求めるにはscikit-learnというライブラリがあるようなので、これを用いていきます。
1 int_var = "snow_falling" #入力
2 out_var = "snow_depth" #出力
3
4 #入力/出力変数をデータフレーム化
5 x = df[[int_var]]
6 x.head()
7
8 y = df[[out_var]]
9 y.head()
10
11 #回帰モデル
12 model = LinearRegression() #線形回帰
13 model.fit(x, y)
scikit-learnで回帰モデルを実装する方法は12, 13行目だけでいいみたいです。
また、今回は降雪量のみを入力としているので、単回帰分析の式は以下となります。
yは積雪深、xは降雪量と5, 8行目で定義しているので、aとbを回帰分析で求めます。

aは切片で、xの値が0のときのyの値を示しています。bは回帰係数で、xの増減がyにどのくらい影響するか(直線の傾き)を示しています。

結果
今回収集した1年分の降雪量を入力とした結果、aの切片とbの回帰係数を以下のように求めることができました。
print('回帰直線の切片', model.intercept_)
print('回帰係数', model.coef_)
print('決定係数', model.score(x, y))
print('積雪深(式)', f'y = {model.coef_[0][0]:.2f}x + {model.intercept_[0]:.2f}')
while True:
try:
snow_fall = float(input("降雪量を入力してください(cm): "))
predicted_depth = predict_snow_depth(snow_fall, model)
print(f"予測される積雪深: {predicted_depth:.2f} cm")

得られた情報をもとに、2018年1月1日の札幌市の積雪深を求めてみます。
当時の降雪量が4cmとのことなので、xに代入すると、36.57cmとなりました。
が、実際には29cmの積雪だったそうです。
また、決定係数が0.14と出力されていますが、これはモデルの当てはまり度を表す統計量とのことなので、ほとんど当てはまらないという結果となりました。
考察としては入力値が降雪量だけでは判断材料には足らないということが示唆されたので、気温や湿度など次元数を増やして対応していくことで良い結果が期待できます。
終わりに
いかがでしたでしょうか。
今回作成したソースコードは僕のgithubから使用することができるので、ぜひ使ってみてください!
今回は単回帰分析による方法でしたが、次週は入力データを増やして線形重回帰分析による方法を行う予定です。
参考url




