第1章

公開されている気象データで気温を予測する

Web APIから東京の過去の気象データを取得し、翌日の最高気温を予測する回帰モデルを作って評価します。

この章で学ぶこと

  • Web APIからJSON形式のデータを取得する
  • 学習に使う特徴量と、予測したい目的変数を決める
  • 時系列の順序を守って学習用・テスト用データに分ける
  • 平均絶対誤差(MAE)と単純な予測を使ってモデルを評価する
  • 予測結果だけでなく、データの出所や限界も説明する

作るもの

Open-MeteoのHistorical Weather APIから東京の2022〜2025年の日別データを取得し、今日の気象から翌日の最高気温を予測するプログラムを作ります。

Web API → JSON → 表に変換 → 特徴量を作る
                              ↓
          結果を評価 ← 予測 ← モデルを学習

機械学習は、データに含まれる規則性をモデルに学習させ、未知のデータに対する分類や数値予測に利用する方法です。この章では、答えとなる数値を予測する回帰を扱います。

この演習のモデルは、気象機関の予報を置き換えるものではありません。機械学習の一連の流れを理解するための小さな実験です。

1. 実行環境を準備する

Python 3が使えるターミナルで、作業用フォルダーを作成します。Windows PowerShellでは次のように実行します。

mkdir ml-weather
cd ml-weather
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install requests pandas numpy scikit-learn matplotlib

macOS・Linuxでは、仮想環境を有効にする行を次のように変更します。

source .venv/bin/activate

仮想環境を使うと、この演習のライブラリをほかのPythonプロジェクトと分けて管理できます。

2. APIからデータを取得する

完成コードをダウンロードし、作業用フォルダーへ保存します。

完成コード:weather_temperature.pyをダウンロード

コード内では、緯度・経度、期間、必要な項目をパラメーターとしてAPIへ送ります。

params = {
    "latitude": 35.6762,
    "longitude": 139.6503,
    "start_date": "2022-01-01",
    "end_date": "2025-12-31",
    "daily": ",".join([
        "temperature_2m_max",
        "temperature_2m_min",
        "precipitation_sum",
        "wind_speed_10m_max",
    ]),
    "timezone": "Asia/Tokyo",
}
response = requests.get(API_URL, params=params, timeout=30)
response.raise_for_status()
payload = response.json()

latitude と longitude は東京付近の座標です。daily には、日ごとの最高・最低気温、降水量、最大風速を指定しています。日別データを指定するときは timezone も必要です。

raise_for_status() は、サーバーがHTTPエラーを返したときに処理を止めます。さらに完成コードでは daily が応答にあるかも確認し、誤った応答をそのまま学習に使わないようにしています。

取得したJSONはpandasの表へ変換し、weather_tokyo.csv に保存します。2回目以降はCSVを使うため、APIへ繰り返しアクセスしません。新しく取得し直したい場合だけ、このCSVを削除してください。

Historical Weather APIの値は、観測値と数値モデルを組み合わせた再解析データです。特定の気象台で直接観測した値と完全に同じとは限りません。利用時はデータの説明とライセンスも確認してください。

3. 学習用の表を作る

1行を1日のデータとし、次のように入力と正解を対応させます。

種類 この章で使う値
特徴量(モデルへの入力) 今日の最高・最低気温、降水量、最大風速、翌日の季節を表す値
目的変数(正解) 翌日の最高気温

翌日の正解は shift(-1) で1行手前へ移します。

frame["target_date"] = frame["time"].shift(-1)
frame["target_max_temperature"] = frame["temperature_2m_max"].shift(-1)

季節は年末から年始へ循環します。12月31日と1月1日が数値上も近くなるよう、翌日の日付をsinとcosの2つの値で表します。

frame["target_day_sin"] = np.sin(
    2 * np.pi * frame["target_date"].dt.dayofyear / 365.25
)
frame["target_day_cos"] = np.cos(
    2 * np.pi * frame["target_date"].dt.dayofyear / 365.25
)

未来を予測する時点で知ることのできない値を特徴量へ入れると、データリークが起こります。例えば「翌日の最低気温」を入力に使うと、本番ではまだ分からない情報を学習時だけ使うことになります。評価結果が不自然によくなるため、特徴量を決めるときは「予測時点で利用できるか」を必ず確認します。scikit-learnのデータリーク解説

4. 過去で学習し、未来で評価する

ランダムに行を分けると、未来のデータが学習側へ混ざります。この章では日付順の前半80%を学習用、後半20%をテスト用にします。

split_at = int(len(dataset) * 0.8)
train = dataset.iloc[:split_at]
test = dataset.iloc[split_at:]

モデルには複数の決定木の予測を組み合わせる RandomForestRegressor を使います。random_state を固定すると、同じ環境で結果を再現しやすくなります。

model = RandomForestRegressor(
    n_estimators=300,
    max_depth=12,
    min_samples_leaf=3,
    random_state=42,
    n_jobs=-1,
)
model.fit(train[feature_names], train["target_max_temperature"])
prediction = model.predict(test[feature_names])

fit が規則性を学習し、predict がテストデータの答えを予測します。テストデータは学習や設定の調整には使いません。

5. モデルを評価する

プログラムを実行します。

python weather_temperature.py

初回はインターネットへの接続が必要です。実行すると、学習期間・評価期間と2種類のMAEが表示され、weather_prediction.png が作られます。

MAE(平均絶対誤差)は、予測と正解の差の絶対値を平均したものです。例えばMAEが 2.1 ℃ なら、予測は正解から平均で約2.1 ℃ずれたと読めます。0に近いほどよい指標です。mean_absolute_errorの仕様

この章では、機械学習モデルと次の単純予測を比べます。

明日の最高気温 = 今日の最高気温

複雑なモデルでも、単純予測よりMAEが大きければ改善したとはいえません。データの期間やライブラリのバージョンにより数値は変わるため、特定の正解率ではなく、同じテスト期間で公平に比較できているかを確認してください。

6. 結果を読み解く

作成されたグラフには、評価期間の最後の60日について、実際の最高気温とモデルの予測が表示されます。次の点を観察します。

  1. 気温が急に変わった日に誤差が大きくないか
  2. 実際の値より予測の線が滑らかになっていないか
  3. 機械学習モデルのMAEが単純予測より小さいか
  4. 4年間というデータ量と東京だけのデータで、どこまで一般化できるか

誤差が大きいこと自体は失敗ではありません。どのような場面で間違えるかを調べ、次の特徴量やデータ収集につなげることが評価の目的です。

トラブル対処

症状 確認すること
ModuleNotFoundError 仮想環境を有効にし、pip install を実行したか
APIへの接続エラー インターネット接続、URL、プロキシ設定。少し時間を置いて再実行する
APIの項目を変えたのに結果が変わらない 保存済みの weather_tokyo.csv を削除してから再実行する
グラフの日本語で警告が出る サンプルのグラフ内は英語表記。変更する場合は日本語フォントも設定する
MAEが例と一致しない 取得データやライブラリの版によって変わる。期間と比較条件を確認する

やってみよう

  1. 緯度・経度を自分の地域へ変更し、東京とのMAEを比較してください。
  2. relative_humidity_2m_mean など別の項目をAPIと特徴量へ追加し、単純予測との差が改善するか確かめてください。
  3. 学習期間を短くしたとき、評価結果がどう変化するか説明してください。
  4. 「翌日の降水量」を予測する場合、回帰と「雨か雨でないか」の分類のどちらが目的に合うか考えてください。

データや特徴量を増やす前に、それが予測時点で取得できる情報か、利用条件に問題がないかも記録しましょう。