AI に来月のセッション数を予測させて実績で検算する:GA4 公開サンプルで「前週同曜日」と誤差率を比べた

GA4 公開サンプルの 11〜12 月の日別セッション数を AI に渡し、1 月 31 日分を予測させました。隠した実績で検算した MAPE は 14.1% と 17.5% で、前週同曜日の 21.9% より良く、4 週曜日平均の 15.5% とは引き分けでした。

9分で読めます Data
過去の実績の折れ線が境界線の手前で止まり、その先の隠した期間で AI の予測の点線と実績の実線が並び、2 本の差を誤差として測るイメージ
この記事は AI が下書きを補助し、運営者が内容を確認して公開しています。

GA4 のセッション数を月ごとに追っていて、「来月はどれくらい?」と聞かれたときに AI へ予測を頼んだことがある方向けの記事です。AI の予測がどれくらい外れるのかを、公開サンプルデータで実際に答え合わせしました。読み終わると、同じ手順で自分のデータの予測を検算し、「この予測は 15% 前後ずれうる」と幅を添えて報告できるようになります。

この記事で分かること:

  • AI に 2 か月分の日別セッション数を渡して翌月 31 日分を予測させたとき、実績との誤差率(MAPE)がいくらだったか
  • AI の予測は、「前週同曜日」「4 週の曜日別平均」という素朴な予測より良いのか悪いのか
  • 年末年始のような特別な日に、どの方法がどう外れたか
  • 予測を検算する SQL と、つまずきやすい点

ざっくり結論

先に結果を書きます。AI(Claude Sonnet)に同じ質問を 2 回して、1 月の MAPE は 1 回目が 14.1%、2 回目が 17.5% でした(筆者が実績と突き合わせて計算)。

予測方法MAPE(31 日の平均誤差率)1 日の最大誤差率1 月合計のずれ
AI 1 回目14.1%40.0%(1/6)−14.9%
AI 2 回目17.5%41.7%(1/6)−18.6%
前週同曜日(12 月最後の週を繰り返す)21.9%46.4%(1/6)−23.6%
4 週曜日平均(12 月最後の 4 週の曜日別平均)15.5%92.9%(1/1)+9.5%

AI は前週同曜日には 2 回とも勝ちましたが、4 週曜日平均とは 1 勝 1 敗でした。同じ質問でも 2 回の答えで MAPE が 3.4 ポイント動いたので、「AI のほうが確実に当たる」とは言えない、というのがこの検証の結論です。

2021 年 1 月の日別セッション数の折れ線グラフ。実績、AI 1 回目、前週同曜日、4 週曜日平均の 4 本を比べると、AI は三が日の低さを当てたが 1/4 以降は実績より低めに出続け、4 週曜日平均は元日を 4,458 と大きく上に外している

図 1 のとおり、AI(1 回目)のオレンジの線は三が日では実績とほぼ重なりますが、休み明けからは実績の下を走り続けました。

予測方法ごとの MAPE と 1 日の最大誤差率を並べた棒グラフ。MAPE は AI 1 回目 14.1%、AI 2 回目 17.5%、前週同曜日 21.9%、4 週曜日平均 15.5%。最大誤差率は 4 週曜日平均の 92.9% が突出している

図 2 のとおり、平均の誤差(MAPE)と 1 日だけの最大の誤差は、順位が一致しません。4 週曜日平均は平均では AI と並びますが、元日だけは 9 割以上外しています。

なぜ「検算」が必要なのか

AI に「来月を予測して」と頼むと、もっともらしい数字と理由が返ってきます。しかし、その数字がどれくらい外れうるのかは、答えの文章からは分かりません。

上司に予測値を出すときに「誤差はこれくらい」と添えるには、過去のデータで一度試して、外れ方を測っておく必要があります。これを ホールドアウト検証(答えが分かっている期間をわざと隠しておき、予測を出させた後で答え合わせする方法)と呼びます。

比べる相手も必要です。AI を使わずに出せる素朴な予測より悪いなら、AI に頼む意味は小さくなります。そこで今回は、表計算でも作れる 2 つの素朴な予測を並べました。

データ: 日別セッション数の作り方

使ったのは、Google が公開している GA4 のサンプルデータ ga4_obfuscated_sample_ecommerce です。Google のグッズを売るオンラインストアの記録を加工したもので、2020 年 11 月 1 日から 2021 年 1 月 31 日までの 3 か月分が入っています(Google for Developers)。

ただし 難読化(個人や実際の数値が分からないように加工すること)されているため、内部の整合性が少し制限されることがある、と公式に書かれています。GA4 の実際の画面の数字とは比べられない点に注意してください。

セッションの数え方

GA4 では、session_start イベント(セッションの始まりを表す記録)が ga_session_id(セッション ID)を作ります。この ID はセッションが始まった時刻の秒の値なので、公式は user_pseudo_id(ブラウザごとの匿名の利用者 ID)と組み合わせて数えることを勧めています(Google アナリティクス ヘルプ)。

筆者がこのサイトの運用で以前試した記録でも、ga_session_id だけで数えると、同じ秒に始まった別の利用者が 1 つのセッションにまとめられてしまうことを確認しました。このサンプルでは、同じ ga_session_id を最大 3 人の user_pseudo_id が持っていました。

次の SQL が、公式の考え方に沿った日別セッション数の例です。

-- 日別セッション数(user_pseudo_id と ga_session_id の組で数える)
SELECT
  PARSE_DATE('%Y%m%d', event_date) AS d,
  COUNT(DISTINCT CONCAT(
    user_pseudo_id, '-',
    CAST((SELECT value.int_value FROM UNNEST(event_params)
          WHERE key = 'ga_session_id') AS STRING)
  )) AS sessions
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20201101' AND '20210131'
GROUP BY d
ORDER BY d;

調査担当がこの考え方の SQL を dry run(実行せずに、読み込む量だけを見積もる機能)にかけると、処理量は 982,194,818 バイト(約 0.98 GB)でした。BigQuery のオンデマンド料金は毎月 1 TiB まで無料なので、この量なら無料枠に収まります(Google Cloud の料金ページ)。

なお GA4 の画面は HyperLogLog++(大量のデータの種類数を少ない計算で推定する方法)でセッション数を推定するため、BigQuery で正確に数えた値とはわずかにずれることがあります(Google アナリティクス ヘルプ)。

3 か月の全体像

結果は 92 日分になりました。最初の 2 か月を 学習期間(AI に見せる期間)、最後の 1 か月を 検証期間(答え合わせのために隠す期間)に分けます。

期間日数合計セッション数特徴
学習期間 2020/11/1〜12/3161 日242,356最大は 12/8 の 7,588、最小は 11/8 の 2,170
検証期間 2021/1/1〜1/3131 日118,618元日 2,311 から 1/6 に 6,002 まで急に増える

12 月上旬に年末商戦の山があり、12/24〜12/27 と 12/31 は 2,629〜2,804 まで下がり、間の 12/28〜12/30 も 3,215〜3,439 にとどまりました。1 月は元日が 2,311 と最も低く、1/5 に 4,495、1/6 に 6,002 と、休み明けに大きく戻りました。

手順: AI への質問文

予測の手順の全体は図 3 のとおりです。いちばん大事なのは、検証期間の 1 月の数字を AI に一切見せないことです。

日別セッション数を学習期間の 11〜12 月と検証期間の 1 月に分け、学習期間だけを AI に渡して予測表を受け取り、隠しておいた 1 月の実績と日付で結合して MAPE を計算し、素朴予測 2 種と比べる流れ図

AI には、次の質問文を送りました。61 行の表(列は date,weekday,sessions)だけを省略し、それ以外は送ったとおりに載せます。答えの形を CSV に決めておくと、後で SQL や表計算に取り込みやすくなります。

あなたはウェブサイトのアクセス解析の担当者です。ファイルやツールは使わず、この文章だけを根拠に答えてください。

次の表は、ある EC サイト(Google のグッズを売るオンラインストア)の、2020 年 11 月 1 日から 12 月 31 日までの日別セッション数です。列は「日付,曜日,セッション数」です。

```csv
date,weekday,sessions
2020-11-01,日,2625
(中略: 61 行)
2020-12-31,木,2629
```

質問: 2021 年 1 月 1 日から 1 月 31 日までの 31 日分の日別セッション数を予測してください。

答え方:
1. 最初に、予測を次の形の CSV コードブロック 1 つで出してください。31 行ちょうど、値は整数にしてください。
```csv
date,sessions
2021-01-01,....
```
2. その後に「根拠」という見出しで、どう考えて予測したか(曜日の傾向、年末年始の扱い、水準の見立て)を 5 文以内で書いてください。

質問文では「Google のグッズを売るオンラインストア」と店名が分かる形で伝えました。このため、AI がこの公開サンプルについて前から知っていた内容が予測に混ざった可能性は消せません。自分のデータで試す場合は、店名を伏せて聞くと、この心配を減らせると考えられます。

実行には Claude Code の claude -p --model sonnet を使い、ファイルを読む機能などのツールをすべて外しました。こうしないと、AI が手元のファイルから 1 月の実績を読んでしまうおそれがあるからです。同じ質問文を 2 回送り、2 回とも 31 行の CSV と根拠が返ってきました。

AI の答え(要点)

1 回目の根拠の一部を原文のまま載せます。

この予測では、1月1日〜3日を元日と三が日の低さ(約2,300〜2,600件)とみて、
4日の仕事始めから平日が3,500件台へ戻ると見ました。
1月中旬以降は、11月前半(平日3,300〜4,000件、週末約2,200〜2,400件)と
12月下旬の中間にあたる水準を想定しています。

2 回目も考え方はほぼ同じで、根拠には「セール期だった11月末〜12月中旬の水準(5,000件超)には戻らないと見ています」と書かれていました。予測の CSV では、1/11 以降の月〜木を 3,500〜3,700、金曜を 3,200 と置いています。どちらも 1/11 以降は、同じ曜日の形を毎週繰り返す予測になっています。

比べる素朴な予測 2 種

AI と比べるために、表計算でも作れる予測を 2 つ用意しました。どちらも 12 月 31 日までの実績だけを使い、1 月の値は見ていません。

名前作り方例: 1/1(金)の予測
前週同曜日12/25〜12/31 の同じ曜日の値を、1 月の毎週に繰り返す12/25(金)の 2,648
4 週曜日平均12/4〜12/31 の 4 週間について、曜日ごとに 4 日の平均を取る12/4・11・18・25 の平均 4,458.25

参考として、1 月の毎日を「7 日前の実績」で予測する方法も計算しました。この方法は 1 月の実績を毎日見ながら更新できるので条件が違い、MAPE は 11.6% でした。この例では、月初に 1 回だけ出す予測より、毎週見直せる予測のほうが誤差が小さくなりました。

検算: 実績との突き合わせと MAPE

MAPE(平均絶対パーセント誤差。予測が実績から何 % ずれたかを日ごとに出して平均した値)の計算は図 4 のとおりです。

MAPE の計算の構造図。1/6 の実績 6,002 と AI 予測 3,600 から誤差率 40.0% を出し、31 日分を平均して MAPE 14.1% になる流れと、実績が小さい元日は同じくらいのずれでも誤差率が 92.9% まで膨らむ注意を並べている

例えば 1/6 は、実績が 6,002、AI 1 回目の予測が 3,600 でした。差の 2,402 を実績の 6,002 で割ると 40.0% になります。これを 31 日分そろえて平均したものが MAPE です。

BigQuery で計算する場合は、日別セッション数を daily という表に、AI の答えを ai_pred(列は d と pred)という表に読み込んでおき、次の SQL を使います。

WITH test AS (
  SELECT d, sessions FROM daily
  WHERE d BETWEEN '2021-01-01' AND '2021-01-31'
),
base AS (
  SELECT d, sessions FROM daily
  WHERE d BETWEEN '2020-12-04' AND '2020-12-31'
),
pred_prev_week AS (  -- 前週同曜日(12/25〜12/31 の同じ曜日)
  SELECT t.d, b.sessions AS pred
  FROM test t JOIN base b
    ON b.d >= '2020-12-25'
   AND EXTRACT(DAYOFWEEK FROM b.d) = EXTRACT(DAYOFWEEK FROM t.d)
),
pred_4wk AS (  -- 4 週曜日平均
  SELECT t.d, AVG(b.sessions) AS pred
  FROM test t JOIN base b
    ON EXTRACT(DAYOFWEEK FROM b.d) = EXTRACT(DAYOFWEEK FROM t.d)
  GROUP BY t.d
),
preds AS (
  SELECT 'ai' AS method, d, pred FROM ai_pred
  UNION ALL SELECT 'prev_week', d, pred FROM pred_prev_week
  UNION ALL SELECT '4wk_avg', d, pred FROM pred_4wk
)
SELECT
  method,
  COUNT(*) AS days,  -- 31 でなければ日付がずれている
  ROUND(AVG(ABS(t.sessions - p.pred) / t.sessions) * 100, 1) AS mape_pct,
  ROUND(MAX(ABS(t.sessions - p.pred) / t.sessions) * 100, 1) AS max_err_pct
FROM preds p JOIN test t USING (d)
GROUP BY method
ORDER BY mape_pct;

筆者は BigQuery の認証を設定していない環境で作業したため、この SQL は実行していません。代わりに、調査担当が BigQuery から出した日別セッション数の CSV を使い、同じ式を node で計算しました。前週同曜日 21.9%(最大 46.4%)、4 週曜日平均 15.5%(最大 92.9%)は、調査担当が先に出していた値と一致しました。

さらに、下の日別の表の数字から、別の担当が node で全 31 日を計算し直しました。AI 1 回目 14.1%、AI 2 回目 17.5%、前週同曜日 21.9%、4 週曜日平均 15.5% と、4 つとも同じ値になりました。

手でも確かめられるように、三が日の AI 1 回目を手計算すると次のとおりです。

日付実績AI 1 回目差(絶対値)誤差率(差 ÷ 実績)
1/12,3112,300110.48%
1/22,7342,40033412.22%
1/32,7912,6001916.84%
平均6.5%

3 日の誤差率を足すと 19.54% で、3 で割ると 6.5% です。後で出てくる図 5 の三が日の値(AI 1 回目 6.5%)と一致しました。

図 1 の値と AI 2 回目の予測を、日別に並べると次の表のとおりです。

日付実績AI 1 回目AI 2 回目前週同曜日4 週曜日平均
1/1(金)2,3112,3002,3002,6484,458.25
1/2(土)2,7342,4002,2002,6773,481.25
1/3(日)2,7912,6002,4002,6803,256.25
1/4(月)3,3733,5003,4003,3584,485.5
1/5(火)4,4953,7003,6003,4395,158.5
1/6(水)6,0023,6003,5003,2154,623.75
1/7(木)4,6683,5003,4002,6294,200
1/8(金)4,2663,2003,1002,6484,458.25
1/9(土)3,2682,5002,4002,6773,481.25
1/10(日)3,0052,6002,5002,6803,256.25
1/11(月)3,9583,7003,5003,3584,485.5
1/12(火)4,7303,9003,7003,4395,158.5
1/13(水)4,5773,8003,6003,2154,623.75
1/14(木)4,3743,7003,5002,6294,200
1/15(金)3,9413,3003,2002,6484,458.25
1/16(土)3,1832,6002,5002,6773,481.25
1/17(日)2,9912,7002,6002,6803,256.25
1/18(月)3,6163,7003,5003,3584,485.5
1/19(火)4,1903,9003,7003,4395,158.5
1/20(水)4,8183,8003,6003,2154,623.75
1/21(木)4,6973,7003,5002,6294,200
1/22(金)4,1013,3003,2002,6484,458.25
1/23(土)3,1442,6002,5002,6773,481.25
1/24(日)2,9772,7002,6002,6803,256.25
1/25(月)3,9193,7003,5003,3584,485.5
1/26(火)4,0993,9003,7003,4395,158.5
1/27(水)4,6063,8003,6003,2154,623.75
1/28(木)4,2283,7003,5002,6294,200
1/29(金)3,7993,3003,2002,6484,458.25
1/30(土)2,9082,6002,5002,6773,481.25
1/31(日)2,8492,7002,6002,6803,256.25

表を見ると、AI の予測は 31 日中、1 回目は 29 日、2 回目は 30 日で実績を下回っていました。1 月合計でも 1 回目は 101,000(実績より 14.9% 少ない)、2 回目は 96,600(18.6% 少ない)です。AI は 2 回とも、1 月は 12 月前半ほどには戻らず、ほぼ横ばいになると見立てていました。しかし実際の 1 月は 11 月前半より高い水準に戻っていました。

年末年始の特別な日で何が起きたか

1 月を 3 つの期間に分けて MAPE を出し直すと、方法ごとの得意・不得意がはっきりします(図 5、筆者計算)。

期間別の MAPE を比べた棒グラフ。1/1〜1/3 は AI 1 回目 6.5%、前週同曜日 6.9%、4 週曜日平均 45.6%。1/4〜1/10 は 21.2%、25.8%、14.3%。1/11〜1/31 は 12.8%、22.7%、11.5%

期間AI 1 回目AI 2 回目前週同曜日4 週曜日平均
1/1〜1/3(三が日)6.5%11.3%6.9%45.6%
1/4〜1/10(休み明けの週)21.2%22.9%25.8%14.3%
1/11〜1/31(通常の 3 週)12.8%16.5%22.7%11.5%

三が日は、AI が 2 回とも元日の 2,311 を 2,300 と当てました。4 週曜日平均は、年末商戦が残る 12 月の金曜日を平均に含むため、元日(金曜日)を 4,458 と見て 92.9% 外しています。

一方、1/6 の 6,002 は、AI の 2 回と前週同曜日が 40% 以上外しました(4 週曜日平均は 23.0%)。この日だけ急に増えた理由は、公開されている情報からは確認できませんでした。1/11 以降の通常の週では、4 週曜日平均が最も小さい誤差でした。

三が日の MAPE は、AI 1 回目が 6.5% で前週同曜日の 6.9% とほぼ同じでしたが、AI 2 回目は 11.3% で前週同曜日より外れました。どちらの回も、休み明けにどこまで戻るかという水準を低めに見積もっていました。

BigQuery の AI.FORECAST(TimesFM)の位置づけ

BigQuery には、TimesFM(Google が作った時系列予測用の AI モデル)で予測する関数 AI.FORECAST があります。予測する列(data_col)、日付の列(timestamp_col)、何日先まで予測するか(horizon)を指定して使います(Google Cloud ドキュメント)。

項目公式ドキュメントの記述
使えるモデルTimesFM 2.5(既定)と TimesFM 3.0(プレビュー)
horizon の範囲2.5 は 1〜10,000、3.0 は 1〜1024、既定は 10
必要なデータ最低 3 点。足りないと「The time series data is too short」のエラー
予測区間confidence_level の既定は 0.95。下限と上限の列が出る
料金BigQuery ML のオンデマンド料金。TimesFM 3.0 は 2026 年 12 月 1 日からトークン単位の料金

TimesFM 3.0 は 2026 年 10 月 7 日付で AI.FORECAST などから使えるようになった、プレビュー段階の機能です(BigQuery リリースノート)。トークン単位の料金では、データ 1 点が 1 トークンに相当します(Google Cloud の料金ページ)。

31 日分の予測は horizon の範囲に収まります。ただし今回は BigQuery の認証と課金の設定を確認できなかったため、AI.FORECAST は実行していません。精度の比較は、次の機会に同じ検算の手順で行う予定です。

予測区間(外れうる幅)を出せる点は、上司への報告で「幅」を添えたい場合に役立つと考えられます。

つまずきやすい点

1. 予測する期間の実績を、先に AI に見せない。 1 月の数字が質問文やファイルに混ざると、AI はそれを参考にしてしまい、検算の意味がなくなります。今回はツールを外して、ファイルを読めない状態で質問しました。

2. 日付で結合し、行数を数える。 AI の答えを「上から順に」並べて実績と比べると、1 行抜けただけで全部の日がずれます。日付の列で結合し、結合後に 31 行あるかを確かめると防げます。

質問文に曜日の列を入れておくと、AI が曜日を取り違えにくくなると考えられます。

3. MAPE は実績が小さい日に膨らむ。 誤差率は実績で割るので、元日のように実績が小さい日は、同じくらいのずれでも大きな % になります。図 4 のとおり、元日の 2,147 のずれは 92.9%、1/6 の 2,787 のずれは 46.4% でした。

MAPE だけでなく、1 月合計のずれも合わせて見ると判断しやすくなります。

4. 1 回の答えで AI の実力を決めない。 同じ質問でも、今回は MAPE が 14.1% と 17.5% に分かれました。2 回以上聞いて、ばらつきも含めて報告するのが安全です。

5. サンプルデータの数字は実在のサイトと比べられない。 難読化されたデータなので、ここで出た誤差率は「手順の練習」の結果です。自分のサイトでは、自分のデータで同じ検算をしてください。

まとめ

  • AI に 2 か月分を渡して 1 月を予測させると、MAPE は 14.1% と 17.5% でした。前週同曜日(21.9%)よりは良く、4 週曜日平均(15.5%)とは引き分けです。
  • AI は元日の落ち込みを当てた一方で、休み明けの戻りを低く見積もり、31 日中 29〜30 日で実績を下回りました。特別な日と通常の日で、得意な方法が入れ替わります。
  • 予測を出すときは、過去の期間を隠して一度答え合わせをし、「誤差率はこれくらい」と素朴な予測の値と並べて報告すると、外れ方の幅を説明できます。

次にやること

検算した予測をどう見せるかの参考には、ダッシュボードの一覧で、このサイトが公開データから作ったダッシュボードの例をご覧ください。セッション数や MAPE の SQL が定義どおりか、第三者の目で確かめたい場合は、BigQuery SQL レビューパックもご利用いただけます。

参考にした一次情報