AIで天気予報はどう変わった? GoogleのWeatherNextを自分のMacで動かしてみた

AIトレンド

はじめに

天気予報は、長いあいだ「スーパーコンピュータで物理の方程式を解く」仕事でした。地球全体を細かく区切り、空気の動きや熱の出入りを少しずつ計算していきます。1回の予報に大きな計算機と数時間がかかるのが当たり前でした。

ここ数年で、この常識が崩れつつあります。過去の大気の記録から学んだ AI が、同じような予報を1分もかからずに出せるようになったからです。2026年8月には、Google DeepMind が天気予報 AI「WeatherNext」のコードと学習済みの重み(AI の中身にあたる数値)を公開しました。誰でも手元で動かせる状態になったわけです。

そこでこの記事では、次の2つを1本にまとめます。

  • AI で天気予報の何が変わったのか(仕組みは、専門知識がなくても分かるように説明します)
  • 公開された WeatherNext の軽量版を、筆者の MacBook Pro で実際に動かした結果(画面の録画、予報の地図、かかった時間)

検証には、2024年10月にメキシコ湾で急発達したハリケーン「ミルトン」のデータを使いました。AI は、1日で一気に強くなったこのハリケーンを予報できたのでしょうか。

まずは全体像です。AI が置き換えたのは天気予報の「どの部分」なのかを、図で確認してください。

これまでの天気予報とAIの天気予報の流れを比べた図。観測といまの大気を作る部分は共通で、未来を計算する部分が物理の方程式からAIに置き換わる

図1:AI に置き換わったのは③の「未来を計算する」部分だけ。観測から「いまの大気」を作る部分は今も同じです

この記事の確認範囲

  • 確認日:2026年10月3日
  • 検証した機械:MacBook Pro(Apple M5 Max、CPU 18コア、メモリ 128GB、macOS 26.6.2)
  • ソフト:Python 3.12.15、JAX 0.11.2、WeatherNext(GitHub の 2026年9月4日のコミット f2f2c51)、metaljax 0.11.9、jax-mps 0.11.0
  • 使ったモデル:WeatherNextCyclones_Mini(1度、2023年までのデータで学習した版)
  • 想定読者:天気や AI に興味があり、ターミナルでコマンドを打ったことがある人。仕組みの章はコマンドを使わない人でも読めます

天気予報は、もともとどう作られているのか

AI の話に入る前に、従来の天気予報(数値予報)の作り方を押さえておきます。ここが分かると、AI が何を置き換えたのかがはっきりします。

数値予報では、地球の大気を縦横高さのマス目に区切ります。各マスは気温・風・湿度・気圧といった値を持っています。そして、空気の動きや熱の出入りを表す物理の方程式で、数分きざみに少し先の状態を計算します。これを何千回も繰り返して、数日先の大気を求めます。

雲のでき方や小さな乱れのように、マスより小さい現象は方程式で直接は解けません。そこで、近似の式(パラメタリゼーション)で補います。予報の精度を上げるにはマスを細かくする必要があり、そのぶん計算量が一気に増えます。これが、天気予報にスーパーコンピュータが必要だった理由です。

一方の AI モデルは、方程式を解きません。過去数十年分の大気の記録を使い、「ある時刻の大気から、6時間後の大気がどうなるか」の例を大量に見せて学習させます。予報するときは、学習した変わり方を6時間ずつ当てはめていくだけです。

2つのやり方の違いを、図で並べました。左右で「少し先の出し方」がどう違うかに注目してください。

物理モデルとAIモデルの比較図。物理モデルは方程式で数分きざみに計算し、AIモデルは過去の記録から6時間後への変わり方を学ぶ

図2:どちらも「少し先を計算して、それを次の出発点にする」を繰り返す。違うのは少し先の出し方

ここで大事な点が1つあります。AI も、出発点となる「いまの大気」は自分では作れません。世界中の観測をまとめて地球全体の状態に仕上げる工程(データ同化)は、これまでどおり物理モデルの仕組みで行われています。AI は「いまの大気」を受け取って、その先を速く計算する役です。従来の仕組みを全部置き換えたわけではありません。

AI の天気予報、この3年で何が起きたか

AI の天気予報は、研究から実際の予報業務へ、驚くほどの速さで進みました。主な出来事を年表にまとめます。

2023年から2026年までのAI天気予報の年表。GraphCast、GenCast、ECMWFのAIFS運用開始、WeatherNext 2、気象庁の発表、コードと重みの公開

図3:研究の成果(論文)から、実際の予報業務、そして誰でも動かせる公開へ

年表の出来事を、もう少し詳しく見ていきます。

時期出来事ポイント
2023年11月Google DeepMind が GraphCast を Science 誌に発表10日先の予報を TPU(Google の AI 用チップ)1台で1分未満。欧州の物理モデル HRES より正確だった項目が、1,380項目のうち9割超
2024年12月GenCast を Nature 誌に発表少しずつ違う未来を何通りも出す「アンサンブル予報」を AI で実現(15日先)
2025年2月25日欧州中期予報センター(ECMWF)が AI モデル AIFS の運用を開始国際的な予報センターが、AI モデルを正式な予報業務に組み込んだ初めての例
2025年11月WeatherNext 2 を発表新方式 FGN を採用。前世代より8倍速く、99.9%の項目と予報時間で前世代を上回る。Google 検索や Pixel の天気にも使われている
2026年6月26日気象庁が AI 気象予測モデルの開発を発表(報道による)2030年ごろの実用化が目標
2026年8月6日WeatherNext のコードと重みを GitHub で公開台風予報の論文が Nature 誌に掲載されたのに合わせて公開。重みのライセンスは商用利用も認める形に

特に最後の公開が、この記事のきっかけです。Google DeepMind によれば、WeatherNext の台風予報は従来より1日以上早く、進路・強さ・風の広がりを同じ精度で予報できるとされています。2025年のハリケーンシーズンには、米国ハリケーンセンター(NHC)が実際の予報に使っていました。

公開された GitHub のリポジトリが下の画面です。赤枠のとおり、ライセンスは Apache 2.0 で、README の冒頭に WeatherNext 2 の説明があります。

GitHubのgoogle-deepmind/weathernextリポジトリのトップページ。リポジトリ名、Apache-2.0ライセンス、WeatherNext 2の説明に赤枠

公式リポジトリ google-deepmind/weathernext(2026年10月3日に撮影)

リポジトリには、目的の違う3種類のモデルが入っています。今回 Mac で動かすのは、表のいちばん下の Mini です。

モデル細かさ内部の点の数パラメータ数公式が想定する計算機
WeatherNext 2(本番用)0.25度(約28km)40,962点約1.8億H100 などの大きな GPU、TPU v5p
WeatherNext Cyclones0.25度40,962点約1.8億同上
WeatherNext Cyclones Mini1度(約111km)10,242点約5,700万P100 クラスの GPU、無料の Colab TPU(v5e-1)

パラメータ数と点の数は、筆者が設定ファイルと重みから数えた値です。Mini は「手元の計算機で試すための軽量版」で、公式も本番用と同じ精度は期待しないよう書いています。

GNN(グラフニューラルネットワーク)とは何か

WeatherNext の仕組みを理解する鍵が GNN(グラフニューラルネットワーク) です。名前は難しそうですが、考え方はシンプルです。

「グラフ」は点と線のつながり

ここでいうグラフは、棒グラフや折れ線グラフのことではありません。点と、それをつなぐ線のことです。身の回りにもたくさんあります。

  • 路線図:駅が点、線路が線
  • SNS:人が点、フォローの関係が線
  • 分子:原子が点、原子どうしの結合が線

「何と何がつながっているか」が大事なデータは、このグラフの形で表せます。GNN は、このグラフの形のデータを扱うのが得意な AI です。

GNN は伝言ゲームをしている

GNN の中で起きていることは、伝言ゲームにたとえると分かりやすくなります。各点が線でつながった隣と情報を交換し、受け取った情報で自分を更新します。これを何回か繰り返すと、遠くの点の情報まで届きます。下の図で、オレンジ色の情報が西から東へ広がる様子を追ってください。

GNNのメッセージパッシングの説明図。西の地点の低気圧の情報が、隣、隣の隣へと伝わり、数回で東の地点に届く

図4:1回目は隣だけ、2回目は隣の隣、と情報が広がっていく

天気は「隣の影響を受けて変わる」ものです。西に低気圧があれば、やがて自分の場所にも雨雲が来ます。隣と情報をやり取りして次の状態を決める GNN の仕組みは、大気の動き方とよく似ています。

なぜ画像の AI ではなく GNN なのか

写真や画像を扱う AI は、データが縦横にきれいに並んだマス目であることを前提にしています。ところが地球は球です。世界地図のようなマス目で区切ると、北極や南極に近いほどマスが細くなり、点が極端に密集してしまいます。

GNN は点の置き方が自由です。そのため、球の表面にほぼ同じ間隔で点を並べられます。WeatherNext は、正二十面体(サッカーボールのような多面体)の三角形を細かく割っていく方法で点を置いています。左右の地球を見比べてください。

緯度経度のマス目とWeatherNextが使う正二十面体メッシュの比較。マス目は極で点が密集し、メッシュはほぼ均等。Miniは10,242点、本番用は40,962点

図5:入力と出力は左のマス目(今回は65,160点)、予報の計算そのものは右のメッシュで行う

点の数は「10×4の分割回数乗+2」で決まります。Mini は5回分割で10,242点、本番用は6回分割で40,962点です。Mini では、点と点の間隔がおよそ200km余りになります。

WeatherNext 2 は「GNN+グラフ上の Transformer」

2023年の GraphCast は、図4のような伝言ゲーム(メッセージパッシング)だけでできた、純粋な GNN でした。WeatherNext 2 はそこから一歩進んでいます。公開されたコードを読むと、次の3段構えになっていました。

  1. マス目からメッシュへ:GNN で、近くのマス目の情報をメッシュの点に集める
  2. メッシュの上で更新:各点が、メッシュ上で16歩以内(数千km圏)の点に「注目」して情報を混ぜる。これを16層繰り返す。ChatGPT などと同じ Transformer の仕組みを、グラフ上の近所に絞って使っている
  3. メッシュからマス目へ:GNN で、メッシュの情報を元のマス目の各点に配り直す

ここに、WeatherNext 2 ならではの工夫が加わります。モデルに小さな乱数(ノイズ)も入れるのです。乱数を変えると、少しずつ違う未来が出てきます。こうして「ありうる未来」を何通りも出すのが アンサンブル予報 です。公式はこの方式を FGN(Functional Generative Network)と呼んでいます。

6時間先を計算する流れを図にしました。番号の順に追ってください。

WeatherNext 2 Miniが6時間先を計算する流れ。マス目のデータをGNNでメッシュへ移し、Transformerで16層更新し、GNNでマス目に戻す。ノイズでアンサンブルを作り、20回繰り返して5日先まで

図6:出力を次の入力にして6時間ずつ進める(自己回帰)。20回で5日先まで

一言でまとめると、WeatherNext 2 は「つながった近所と情報を交換しながら、地球全体の6時間後を予測する AI」です。この仕組みが本当に手元で動くのか、ここから確かめていきます。

自分の Mac で WeatherNext 2 Mini を動かす

公式の推奨は TPU(Google のクラウドにある AI 用チップ)で、Mac は想定外の環境です。公式のデモは Google Colab 用のノートブックとして配られています。今回はその中身を、Mac のターミナルで順に実行しました。全体の流れは次のとおりです。

MacでWeatherNext 2 Miniを動かすまでの5ステップ。Python環境を作る、WeatherNextを入れる、重みとデータを落とす、attentionを切り替える、結果を地図にする。GPUを使う場合はmetaljaxかjax-mps

図7:筆者が実際に行った手順。GPU(右下)は任意

ステップ1・2:作業フォルダと Python 環境を作る

まず作業用のフォルダを作り、公式リポジトリを取得します。Python の環境づくりには uv(高速なパッケージ管理ツール)を使いました。公式の setup.py は Python 3.10〜3.11 を想定していますが、3.12 でも問題なく動きました。

# 作業フォルダを作って公式リポジトリを取得する
mkdir weathernext-lab && cd weathernext-lab
git clone https://github.com/google-deepmind/weathernext.git

# Python 3.12 の仮想環境を作って有効にする(uv は brew install uv で入る)
uv venv -p 3.12 .venv
source .venv/bin/activate

# WeatherNext 本体と、足りなかった部品を入れる
uv pip install -e ./weathernext h5py "pandas<3"

h5py と pandas<3 は、公式の依存関係だけでは足りなかったものです。h5py がないとサンプルデータを読めません。pandas 3 だと、台風の進路を取り出すところでエラーになりました(詳しくは後半のトラブルシューティングで説明します)。

ステップ3:重みとサンプルデータを落とす

学習済みの重みとサンプルデータは、Google Cloud の公開バケットに置かれています。ログインは不要で、curl だけで取得できます。

mkdir data && cd data
B=https://storage.googleapis.com/dm_graphcast/weathernext2

# Mini の重み(227MB)。ファイル名の「<」は %3C と書く
curl -o WeatherNextCyclones_Mini_2024.npz "$B/params/WeatherNextCyclones_Mini_%3C2024.npz"

# 2024年10月7日 0時(世界時)から5日分のサンプルデータ(1度、580MB)
curl -o hres_1p0_steps20.nc "$B/dataset/source-hres_forecast_init-2024-10-07%2000:00:00_res-1.0_levels-13_steps-20.nc"

# 台風・ハリケーンの実際の進路データ(米国海洋大気庁の IBTrACS、23MB)
curl -O https://www.ncei.noaa.gov/data/international-best-track-archive-for-climate-stewardship-ibtracs/v04r01/access/netcdf/IBTrACS.ALL.v04r01.nc
cd ..

サンプルデータの日付は、公式があらかじめ用意したものです。この日、メキシコ湾ではハリケーン「ミルトン」が発達を始めていました。好きな日付で予報するには、その日の初期値(ERA5 や HRES のデータ)を自分で用意して形を整える必要があります。今回はサンプルデータだけを使いました。

ステップ4:予報を実行するスクリプト

公式デモのノートブックから、Colab 専用の部分(Colab の認証、Google Cloud Storage からの読み込み、画面のつまみなど)を外して、予報の部分だけを1本のスクリプトにしました。ファイル名は run_wn2_mini.py です。weathernext-lab フォルダの中に保存してください。

"""WeatherNext 2(Cyclones Mini, 1度)を Mac で動かして時間を測るスクリプト。

公式デモ docs/weathernext2/wn2_demo.ipynb の手順を、Colab 専用の部分
(google.colab・GCS クライアント・ウィジェット)を外してそのまま並べたもの。

使い方:
  python run_wn2_mini.py --members 4 --out out/cpu_m4.nc
"""
import argparse, dataclasses, json, logging, os, platform, time, warnings

warnings.filterwarnings("ignore")  # 研究コード由来の警告が多いので画面からは隠す
logging.getLogger().setLevel(logging.ERROR)

import haiku as hk
import jax
import numpy as np
import xarray

from weathernext.utils import checkpoint, data_utils, fiddle_config_io, rollout
from weathernext.weathernext2 import fgn

p = argparse.ArgumentParser()
p.add_argument("--data", default="data/hres_1p0_steps20.nc")
p.add_argument("--weights", default="data/WeatherNextCyclones_Mini_2024.npz")
p.add_argument("--members", type=int, default=2, help="アンサンブルの数")
p.add_argument("--steps", type=int, default=0, help="予報するステップ数(0=データにある全部)")
p.add_argument("--attention", default="triblockdiag_mha")
p.add_argument("--config", default="WeatherNextCyclones_Mini", help="WeatherNextCyclones で本番用(0.25度。Mac では重すぎる)")
p.add_argument("--out", default="")
p.add_argument("--log", default="")
a = p.parse_args()

log = {"backend": jax.default_backend(), "devices": [str(d) for d in jax.devices()],
       "jax": jax.__version__, "machine": platform.machine(), "members": a.members}
print(f"[env] JAX {jax.__version__} / backend={log['backend']} / devices={log['devices']}")

t = time.time()
example_batch = xarray.load_dataset(a.data).compute()
config = fiddle_config_io.get_fiddle_config_by_name(f"weathernext2/configs/{a.config}")
with open(a.weights, "rb") as f:
    ckpt = checkpoint.load(f, fgn.CheckPoint)
log["load_sec"] = time.time() - t
n_params = sum(x.size for x in jax.tree_util.tree_leaves(ckpt.params))
log["params"] = int(n_params)
print(f"[load] データと重みの読み込み {log['load_sec']:.1f} 秒 / パラメータ {n_params:,} 個")
print(f"[data] 初期時刻 2024-10-07 00UTC 前後 / 格子 {example_batch.sizes['lat']}x{example_batch.sizes['lon']} "
      f"/ 気圧面 {example_batch.sizes['level']} 層 / 変数 {len(example_batch.data_vars)} 種類")

n_time = example_batch.sizes["time"]
max_steps = n_time - 2
steps = a.steps if a.steps else max_steps
eval_inputs, eval_targets, eval_forcings = data_utils.extract_inputs_targets_forcings(
    example_batch, target_lead_times=slice("6h", f"{steps*6}h"), **dataclasses.asdict(config.task))
print(f"[task] 入力 {dict(eval_inputs.sizes)} → 予報 {steps} ステップ(6時間ごと・{steps*6} 時間先まで)")

tk = config.predictor_kwargs["noisy_function_kwargs"]["mesh_model_ctor"].keywords["transformer_kwargs"]
tk["attention_type"] = a.attention  # TPU 専用の splash attention を CPU/GPU 向けに切り替え
log["attention"] = a.attention
config_inference = fgn.PredictorConfig(
    task=config.task, predictor_constructor=config.predictor_constructor,
    predictor_kwargs=config.predictor_kwargs, predictor_wrappers=config.predictor_wrappers[:-1])


@hk.transform
def run_forward(inputs, targets_template, forcings):
    predictor = fgn.construct_predictor(config_inference)
    return predictor(inputs, targets_template=targets_template, forcings=forcings)


run_forward_jitted = jax.jit(
    lambda rng, inputs, targets_template, forcings: run_forward.apply(
        ckpt.params, rng, inputs, targets_template, forcings))

rng = jax.random.PRNGKey(0)
step_times, chunks = [], []
for m in range(a.members):
    r = jax.random.fold_in(rng, m)
    t_member = time.time()
    t_prev = t_member
    member_chunks = []
    for k, chunk in enumerate(rollout.chunked_prediction_generator(
            predictor_fn=run_forward_jitted, rng=r, inputs=eval_inputs,
            targets_template=eval_targets * np.nan, forcings=eval_forcings,
            num_steps_per_chunk=1)):
        chunk = chunk.as_numpy()  # 計算が終わるまで待つ(JAX は非同期で返すため)
        now = time.time()
        step_times.append({"member": m, "step": k + 1, "sec": now - t_prev})
        print(f"[run] メンバー{m+1}/{a.members} ステップ {k+1:2d}/{steps}(+{(k+1)*6:3d}h) {now - t_prev:6.2f} 秒")
        t_prev = now
        member_chunks.append(chunk)
    pred = xarray.concat(member_chunks, dim="time").expand_dims(sample=[m])
    chunks.append(pred)
    print(f"[run] メンバー{m+1} 完了 {time.time() - t_member:.1f} 秒")

predictions = xarray.concat(chunks, dim="sample")
first = [s["sec"] for s in step_times if s["member"] == 0 and s["step"] == 1][0]
rest = [s["sec"] for s in step_times if not (s["member"] == 0 and s["step"] == 1)]
log.update(first_step_sec=first, steady_step_sec=float(np.median(rest)) if rest else None,
           total_sec=float(sum(s["sec"] for s in step_times)), steps=steps, step_times=step_times)
steady = f"{log['steady_step_sec']:.2f}" if rest else "-"
print(f"[sum] 1回目(コンパイル込み) {first:.1f} 秒 / 2回目以降の中央値 {steady} 秒/ステップ"
      f" / 合計 {log['total_sec']:.1f} 秒")
if a.out:
    os.makedirs(os.path.dirname(a.out) or ".", exist_ok=True)
    predictions.to_netcdf(a.out)
    print(f"[save] {a.out}")
if a.log:
    json.dump(log, open(a.log, "w"), ensure_ascii=False, indent=1)

公式デモから変えた点は、次の3つだけです。

  • 注目(attention)の計算方法を切り替えた:設定ファイルの初期値 splash_mha は TPU 専用で、CPU では動きません。公式デモが GPU 向けに案内している triblockdiag_mha に変えています
  • アンサンブルを1本ずつ順番に計算する:公式は複数のチップに分けて同時に計算しますが、Mac は計算装置が1つなので順番に回します
  • 1ステップごとに完了を待って時間を測る:JAX は計算の完了を待たずに先へ進むため、そのままでは正しい時間が測れません

実行してみる(CPU)

準備ができたら実行します。まずは公式手順そのままの CPU で、5日先までの予報を1本計算します。

# weathernext-lab フォルダで実行する
python run_wn2_mini.py --members 1

実行中の画面を録画しました。録画は4倍速です。6時間先の予報が1つずつ積み上がっていく様子を見てください。

MacのターミナルでCPU版を実行した録画。データファイルの一覧を表示したあと、20ステップの予報が1ステップ約5秒で進み、合計115秒で完了

CPU での実行(4倍速)。1回目はコンパイル込みで約10秒、2回目以降は1ステップ5〜6秒、5日分で約2分

最初の1ステップだけ約10秒かかっているのは、JAX がモデルを機械語に変換(コンパイル)しているためです。2回目以降は1ステップ(6時間分)を5〜6秒で計算し、5日先までの予報が約2分で出ました。メモリ使用量は最大でも約13GBで、128GB のうちのごく一部です。

これは「スーパーコンピュータで数時間」とはまったく違う世界です。もちろん、本番用より粗い Mini での話です。それでも、地球全体の5日先の天気が、ノートパソコン1台で2分で計算できました。

検証結果:AI はハリケーン・ミルトンを予報できたか

ここからは、計算した予報の中身を見ていきます。乱数を変えて4本(アンサンブル4メンバー)を計算し、地図にしました。

地球全体の5日予報

まず、地球全体の様子です。下のアニメーションは、Mac で計算した地上の風の強さ(色)と海面気圧(青い線)です。

Macで計算した地球全体の5日予報のアニメーション。地上10mの風の強さと海面気圧。ミルトン、カーク、レスリー、バリジャットの位置にラベル

Mac で計算した地球全体の予報(メンバー1)。ラベルは AI が追跡した熱帯低気圧の位置

初期時刻の時点で、地球上には熱帯低気圧が5つありました。大西洋のミルトン・カーク・レスリー、西太平洋のバリジャット、南インド洋のアンチャです。AI はこれらの渦を5日間追い続け、南半球の偏西風帯で低気圧が次々と東へ進む様子も描いています。

ミルトン付近を物理モデルと比べる

次に、ミルトン付近を拡大します。左が Mac で計算した AI の予報、右が比較用に、サンプルデータに入っている物理モデル HRES(欧州中期予報センターの高解像度モデル)の予報です。黒線がミルトンの実際の進路、オレンジ線が AI の予報した進路です。

ミルトン付近の海面気圧のアニメーション。左はMacで計算したAIの予報、右は物理モデルHRESの予報。黒線は実際の進路、オレンジ線はAIの予報進路

ミルトン付近の海面気圧。左右とも、上陸の数時間前にはフロリダ西岸に低気圧の中心がある

AI の低気圧は、メキシコ湾を東へ進んでフロリダ半島に向かい、大西洋へ抜けていきます。動きは物理モデルとよく似ています。

ただし、中心の気圧は実際よりずっと高く(弱く)見えます。1度のマス目はおよそ100km四方です。ミルトンのような小さく強いハリケーンの中心は、このマス目の中に平均されて埋もれてしまいます。これは AI だけでなく、1度に粗くした物理モデルの図でも同じです。

進路:4本とも実際の進路に沿った

ミルトンの進路を4本並べました。公式の「進路の取り出し」機能(tracker)を使い、AI の出力から渦の位置を拾っています。黒が実際の進路です。

ハリケーン・ミルトンの進路の比較図。MacでAIが予報した4本の進路と実際の進路がメキシコ湾からフロリダ半島を横切って大西洋へ抜ける

AI の予報4本と実際の進路(米国海洋大気庁の IBTrACS)。初期時刻は2024年10月7日9時(日本時間)

4本ともメキシコ湾を東北東へ進み、フロリダ半島を横切るという大筋を捉えていました。実際の位置とのずれは、次のとおりです。

初期時刻から実際の位置とのずれ(4本)参考:1度のマス目
24時間後約10〜80km約100km
48時間後約90〜180km約100km
72時間後約70〜140km約100km
96時間後約60〜380km(1本だけ大きくずれた)約100km

3日先までなら、ずれはマス目1〜2個分に収まっています。4日目に1本が大きく離れたのは、ミルトンが勢力を落として温帯の低気圧に変わっていく時期です。

一方で、本番用ではない Mini の限界もはっきり出ました。「気圧がいちばん低い場所を追う」という同じ簡単な方法で比べると、48時間後のずれは AI(Mini)で約110〜150km、サンプルデータの物理モデル HRES で約10kmでした。サンプルの HRES は、もともと0.25度の細かい予報を1度に粗くしたものと考えられます。比べる条件はそろっていませんが、Mini が世界最高水準の物理モデルに及ばないことは確かです。公式も、Mini は本番用と同じ性能を期待しないよう書いています。

強さ:「急発達」を AI も予報した

ミルトンで最も驚かれたのは、発達の速さです。初期時刻に 981hPa だった中心気圧は、わずか24時間後に 902hPa まで下がりました。最大風速は 75ノットから145ノット(秒速約75m)になっています。このような急発達は、物理モデルでも予報が難しい現象です。

公式の tracker は、マス目の気圧とは別に、AI が直接予報する「台風の強さ」の出力も読み取ります。その値を実際と比べたのが下のグラフです。

ミルトンの中心気圧と最大風速の時間変化。実際は24時間で981から902hPaに急発達。AIの4本も930〜950hPa台まで発達を予報

中心気圧(左、下ほど強い)と最大風速(右)。黒が実際、色の線が AI の4本

AI の4本は、いずれも1日で 930〜950hPa 台まで発達すると予報していました。4本のうち最も強い1本は、2日後に 916hPa まで下がっています。実際の 902hPa には届かないものの、「これから急に強くなる」という大事な信号は出せていました。ノートパソコンで2分の計算としては、十分に意味のある結果です。

なお、これは1つのハリケーン、1回の予報だけを見た結果です。AI の実力を測るには、何百もの事例で平均をとる必要があります。公式の論文では、Mini を含む各モデルの成績がまとめられています。

Mac の GPU で速くする(metaljax・jax-mps)

CPU の約2分でも十分速いのですが、M5 Max には強力な GPU があります。ところが、Apple 製の JAX 用プラグイン(jax-metal)は更新が止まっているとされ、今回は試していません。代わりに、コミュニティが作った2つのプラグインを試しました。

プラグイン仕組み状態(2026年10月時点)
metaljaxApple の機械学習ライブラリ MLX を同梱し、Metal(Mac の GPU 機能)で実行ベータ版。PyPI から入る
jax-mpsJAX のプログラムを MLX の命令に置き換えて実行実験的。PyPI から入る
metal-pjrt-pluginXLA(JAX の計算エンジン)の GPU 用の仕組みを Metal に移植PyPI 版がなく、自分でビルドが必要(初回1〜2時間とされる)。今回は未検証

WeatherNext のようなモデルは、特殊な計算(まばらな行列の計算や独自の注目の計算)を使います。プラグインがそれらに対応しているとは限らないため、ここは「動けば幸運」くらいの気持ちで試しました。

入れ方:作業場所を分けて、環境変数で切り替える

プラグインどうしがぶつからないように、仮想環境をそれぞれ別に作りました。

# metaljax 用の環境
uv venv -p 3.12 .venv-metaljax
VIRTUAL_ENV=.venv-metaljax uv pip install -e ./weathernext h5py "pandas<3" metaljax

# jax-mps 用の環境
uv venv -p 3.12 .venv-jax-mps
VIRTUAL_ENV=.venv-jax-mps uv pip install -e ./weathernext h5py "pandas<3" jax-mps

# 実行するときは、環境変数で GPU を指定する(スクリプトは CPU と同じ)
JAX_PLATFORMS=metal .venv-metaljax/bin/python run_wn2_mini.py --members 1
JAX_PLATFORMS=mps   .venv-jax-mps/bin/python  run_wn2_mini.py --members 1

結果は、どちらもスクリプトを1行も変えずに動きました。metaljax で実行した画面がこちらです。1行目の backend=metal が、GPU で動いている印です。

metaljaxでGPU実行した録画。jax 0.11.2とmetaljax 0.11.9を確認し、backend=metalで20ステップが1ステップ約1.6秒で進み約37秒で完了

metaljax(GPU)での実行(等倍)。録画ソフトも GPU を使うため1ステップ約1.6秒。録画なしでは約1.2秒だった

速さの比較:GPU は CPU の約5〜6倍

5日先までの予報を4本ずつ、3つの方法で計算しました。筆者側のほかの計算は走らせず、録画もしない状態で測っています。右のグラフは、実行中の CPU と GPU の使用率を記録したものです。

速さの比較と使用率のグラフ。5日先までの予報1本がCPUで126秒、metaljaxで26秒、jax-mpsで20秒。CPU版はCPUを約半分、GPU版はGPUを8〜9割使う

5日先までの予報1本にかかった時間(4本の平均)と、実行中の使用率

数字を表にまとめます。

方法1ステップ(6時間分)5日先までの予報1本4本の合計メモリ使用量の最大
CPU のみ(公式手順そのまま)5.5〜6.3秒約126秒503秒約12.7GB
GPU:metaljax約1.2秒約26秒104秒約13.7GB
GPU:jax-mps約1.0秒約20秒81秒約19.7GB

GPU にすると、CPU の約4.8〜6.2倍速くなりました。CPU は長く回すと少しずつ遅くなり(1ステップ5.5秒→6.2秒)、熱の影響とみられます。GPU はほぼ一定でした。

速くても、答えが変わっては意味がありません。そこで、GPU で計算した予報と CPU で計算した予報を、地球全体で比べました。5日後の時点でも、両者の差は気温で約0.002℃、海面気圧で約0.002hPa でした。予報としては同じ答えと言ってよい差です。

本番用(0.25度)は Mac で動くか

ついでに、本番用と同じ細かさのモデル(WeatherNext Cyclones、0.25度、約1.8億パラメータ)も試しました。結果は次のとおりです。

  • metaljax:計算の途中で「メモリの上限(96GB)を超える」として止まりました。このプロセスだけで約65GBを確保していました
  • CPU:6時間先の1ステップだけは計算できましたが、コンパイル込みで約5分かかりました。メモリの使用量は物理メモリ(128GB)を超え、macOS が圧縮やディスクへの退避でしのいでいる状態でした

15日先までの予報には60ステップが必要です。128GB の Mac でも、本番用は「動かせなくはないが、実用にはならない」というのが結論です。手元で遊ぶなら Mini、本格的に使うなら公式どおり TPU や大きな GPU、と考えておくのがよさそうです。

トラブルシューティング

今回の検証で実際に出たメッセージと対処を、図と表にまとめました。エラーが出たら、まず画面のメッセージと見比べてください。

トラブルシューティングの対応表。h5py不足、CPUでのsplash attention、pandas 3、時間が速すぎる、100m風の変数がない、metaljaxのメモリ不足の6つと対処

図8:今回の検証で実際に表示されたメッセージ6つと、その対処

コマンドをコピーできるように、表でも載せておきます。

出たメッセージ原因対処
ImportError: No module named 'h5py'サンプルデータ(.nc)を読む部品が入っていないuv pip install h5py
ValueError: Only interpret mode is supported on CPU backend.TPU 専用の注目計算 splash_mha のまま実行したスクリプトの attention_type を triblockdiag_mha にする
ValueError: invalid error value specified進路の取り出し(ibtracs_netcdf_to_csv.py)が pandas 3 に未対応uv pip install "pandas<3"(今回は 2.3.3 になった)
2ステップ目が0.01秒など、速すぎるJAX は計算の完了を待たずに次へ進む結果を as_numpy() などで NumPy に変換してから時間を測る
KeyError: '100m_u_component_of_wind'WeatherNext 2 本体は高度100mの風が必要だが、サンプルデータに入っていないサンプルデータでは Cyclones か Mini の設定を使う
RESOURCE_EXHAUSTED: metaljax out of memory本番用0.25度のモデルは Mac のメモリに収まらないMini(1度)に戻す

このほか、実行中に WARNING:absl:... や FutureWarning といった警告がたくさん表示されます。研究用のコードによくある注意書きで、予報の結果には影響しませんでした。スクリプトでは画面が見やすいように非表示にしています。

まとめ

AI で天気予報の何が変わり、それが手元でどこまで動くのかを、実際に Mac で確かめました。要点を振り返ります。

  • AI が置き換えたのは「いまの大気から未来を計算する」部分。観測から「いまの大気」を作る部分は、今も従来の仕組みが担っている
  • WeatherNext 2 は、地球を正二十面体のメッシュで覆い、GNN とグラフ上の Transformer で6時間ずつ未来を計算する。乱数を加えて、ありうる未来を何通りも出す
  • 2026年8月に公開された軽量版(Mini、1度)は、M5 Max の MacBook Pro でCPU だけで5日予報1本が約2分、メモリは約13GBで動いた
  • コミュニティ製の metaljax・jax-mps を使うと、Mac の GPU で約20〜26秒。結果は CPU とほぼ同じだった
  • ハリケーン・ミルトンでは、4本とも進路の大筋と「1日での急発達」を捉えた。ただし強さは控えめで、物理モデル HRES と比べると位置の精度は劣った
  • 本番用(0.25度)は 128GB の Mac でもメモリが足りず、実用にはならない

天気予報の AI は、もう研究室の中だけのものではありません。ノートパソコンで「地球の5日後」を計算して、その出来を自分の目で確かめられます。

次の一歩としては、次のようなことを試すと理解が深まります。

  1. 乱数を変えてアンサンブルを8本、16本と増やし、予報のばらつきがどう広がるかを見る
  2. 公式の Colab ノートブック(無料の TPU v5e-1)で同じ予報を動かし、Mac との速さを比べる
  3. WeatherBench2 のデータを使い、別の日付の初期値で予報してみる
  4. 実際の予報業務で使われる WeatherNext 2 の出力を、Google Cloud や Open-Meteo の API で取得して比べる

最後に注意です。WeatherNext は研究用のモデルで、公式の気象情報の代わりにはなりません。防災の判断には、必ず気象庁などが発表する情報を使ってください。

参考リソース

PR

生成AIを体系的に学びたい方へ

「DMM 生成AI CAMP 学び放題」は、ChatGPTなどの生成AIを学べる月額制のオンライン学習サービスです。仕事への活用に向けて継続的に学びたい方は、公式サイトでコース内容や入会条件をご確認ください。

DMM 生成AI CAMP 学び放題

リンク先は公式サイトです。

AIトレンドAI入門AI最新情報
Takuyaをフォローする