以下の内容はhttps://shinyorke.hatenablog.com/entry/ai-matchup-ohtani-vs-ohtaniより取得しました。


「打者大谷は投手大谷からホームランを打てるか?」をAIはどう判断するか? - Geminiで作る野球解説AI Agent

菅野投手がまさかのロッキーズ行きで驚いている人です.

以前のブログで「野球の解説を生成AIにしてもらう時代がもうすぐやってくる」なんて紹介をしましたが, 実用できそうかつ, 2/26に「Baseball Play Study〜野球解説者AI Agent」という場所でお話させていただくものができたので紹介します.

ざっくりいうと,

「打者大谷は投手大谷からホームランを打てるか?」的な疑問をLLMとセイバーメトリクスでどうにかするアプリを作った.

というお話になります.

結論を待てない方はすぐ下の動画を見てください(倍速再生で良いので).

youtu.be

TL;DR

セイバーメトリクスの知識 × LLM(Gemini)で「AIと人間の役割分担」を実現した仮想対戦予測機能, めっちゃ使えそうな予感.

やったことは以下のとおりです.

  • 根拠となる数字はセイバーメトリクスを元にした数理モデル,対戦シナリオの解釈と分析はLLM(Gemini)に委ねるハイブリッドな設計と実装.
  • LLMに渡したデータを開示する「根拠データ表示」で透明性を担保.
  • 真剣分析/エンタメの2モードで,プロンプトのトーン指示だけで出力を切り替える.

これで「一定の根拠に基づく野球のAI解説」をどうにかできる所まで持ってきました的な話です.

こんな事ができた

論より証拠で例を見ましょう(≒いきなりオチです野球的には).

  • 投手オオタニサンVS打者オオタニサン
  • 山本由伸VSオオタニサン

打者大谷は投手大谷を打てるか?

AI曰く, 「投手オオタニサンが打者オオタニサンを打ち取る可能性が僅かに高い(打者が打つ確率が49.4%)」そうです.

AIが出してきた傾向

# AI分析レポート

## 総合予測(高)

1. 投手有利(確信度:中)

   投手大谷は高い奪三振能力と低い被長打率を誇り、特に打者大谷が苦手とする球種(Sweeper, Curveball)で高い効果を発揮するため、投手有利と予測します。

   ただし、打者大谷のSinker/Cutter攻略の可能性と一発の破壊力は無視できません。

## 球種別の攻略可能性

- (※データ記載なし)

## 推奨戦略

1. SinkerとCutterの積極的な狙い打ち  
   投手大谷のSinkerとCutterは被打率が非常に高く、奪三振率が低い傾向があります。特にCutterは打者大谷の得意球種でもあるため、甘く入った場合は積極的にスイングし、長打を狙うべきです。

2. Slider・Sweeper・Curveballの見極め  
   これらは非常に危険な球種であり、特にCurveballは打者大谷の最大の弱点です。ボール球は徹底して見送り、ストライクゾーンに来てもファウルで粘るなど、安易なスイングは避けるべきです。

3. カウントに応じたアプローチ  
   投手大谷は与四球率が低く、四球を選ぶことは容易ではありません。早いカウントでSinkerやCutterが来れば積極的に打ちに行き、追い込まれた場合はファストボール系で粘りつつ、変化球は捨てていくアプローチが有効です。

## 相手の脅威

圧倒的な奪三振能力が最大の脅威です。奪三振率35.4%は非常に高く、特にSlider(K%55.6%)、Sweeper(K%37.0%)、Curveball(K%69.2%)は打者大谷にとって大きな脅威となります。

また、与四球率4.3%と極めて低く、打者大谷が四球を選ぶ展開は期待しにくいでしょう。

さらに、被ISO 0.086という低い被長打率は、長打をほとんど許さないことを示しており、打者大谷の長打力を封じ込める可能性があります。

加えて、打者大谷が苦手とするSweeperやCurveballが投手大谷の得意球種と重なっている点も大きなリスク要因です。

完全に自分の感想(オピニオン)ですが, 「オオタニサンはオオタニサンのカーブとスイーパー打てないだろうな」ってのはわかります, スイーパーは投げないかもですが.

山本由伸は打者大谷と対戦するとどうなる?

投手オオタニサンより抑える可能性がありそう(山本由伸が53.4%の確率で打者オオタニサンを抑える予想).

Yoshinobu優秀(投手オオタニサンより)

評価はこんな感じです.

# AI分析レポート

## 総合予測(高)

1. 投手有利(確信度:中)

   山本投手の圧倒的な奪三振能力と被長打率の低さが、大谷選手の強力な打撃を上回る可能性が高いと判断します。

   ただし、大谷選手の一発の脅威は常に存在します。

## 球種別の攻略可能性

- 4-Seam Fastball(山本投手の主要球種)  
  山本投手は投球数991球と最も多く、被打率0.195、奪三振率31.6%と非常に効果的です。  
  大谷選手は打率0.265、三振率28.0%と極端に悪くはありませんが、山本投手の質の高い速球は打ち崩すのが容易ではなく、高めで空振りを奪われるリスクがあります。

- Split-Finger(山本投手の決め球)  
  山本投手は投球数709球、被打率0.132、奪三振率45.7%と最も強力な決め球です。  
  大谷選手は打率0.278、三振率16.7%と対一般的なSplitには悪くないものの、山本投手の落差と精度は別格で、三振リスクを大きく高めます。

- Curveball(山本投手の決め球)  
  山本投手は投球数491球、被打率0.196、奪三振率32.1%と高水準。  
  大谷選手は打率0.255ながら三振率48.9%と極端に高く、この球種は最大級の弱点となります。

- Cutter(攻略の糸口)  
  山本投手は投球数309球、被打率0.235、奪三振率11.8%と他球種より奪三振率が低め。  
  大谷選手は打率0.341、三振率19.5%と得意であり、カウント球は狙い目となります。

- Sinker(攻略の糸口)  
  山本投手は投球数209球、被打率0.244、奪三振率15.6%。  
  大谷選手は打率0.329と得意で、積極的に狙う価値があります。

- Slider(少球数だが高品質)  
  山本投手は投球数79球ながら被打率0.105、奪三振率21.1%と非常に効果的。  
  大谷選手は打率0.316と悪くありませんが、見極めが重要です。

## 推奨戦略

1. 狙い球の絞り込み  
   Split-FingerとCurveballは非常に危険なため無理に打ちにいかず、見極めを徹底します。特に低めのSplit-Fingerには手を出さない意識が重要です。

2. CutterとSinkerの積極的な狙い打ち  
   大谷選手が得意とし、山本投手の奪三振率が比較的低いCutterとSinkerを早いカウントから狙います。長打の可能性が高まります。

3. 高め4-Seam Fastballへの対応  
   山本投手は高め速球で目線を上げ、低め変化球で仕留める傾向があります。甘い高め速球は積極的に振りにいくべきです。

4. 四球の選択肢  
   ボール球には手を出さず、大谷選手の高いBB%を活かして四球で出塁することも重要な戦略です。

## 相手の脅威

山本投手の最大の脅威は圧倒的な奪三振能力です。奪三振率32.5%はリーグトップクラスであり、特にSplit-Fingerの奪三振率45.7%は驚異的です。大谷選手のK%(30.8%)を考慮すると、三振リスクは非常に高い状況です。

また、被ISO 0.101、被長打率0.282と長打をほとんど許さず、大谷選手の強打を封じる可能性があります。

さらに、4-Seam Fastball・Split-Finger・Curveballはいずれも被打率が低く、質の高い組み立てで打者を翻弄します。与四球率8.7%と制球力も優秀で、甘い球は限られます。

## 予想される対戦シナリオ

1. 投手有利(空振り三振)  
   高め4-Seam Fastballで目線を上げてカウントを整え、低めSplit-FingerやCurveballで空振り、または見逃し三振に仕留める展開が最も想定されます。

2. 打者有利(長打)  
   カウント球のCutterやSinker、甘く入った4-Seam Fastballを早いカウントで完璧に捉え、外野深くへの二塁打または本塁打を放つ展開。この場合、大谷選手の高いISOが発揮されます。

どっちの対戦シナリオも目に浮かびます.

おしながき

あらすじ

以前のブログで,Google GeminiとmarimoでMLB選手を検索・評価するAI Agentを作った話を書きました.

その後このAI Agentプロトタイプでは,

  • 選手個人のレポート出力に特化した機能を実装
  • 現実に対戦したことある選手同士の成績比較とレポート

といった機能を追加したりしました.

これらの機能の話をとあるタイミングで社内LTで話した後, こんな事を思いました.

対戦したことがない選手同士の対戦を予測できたりするんじゃね?

2026年はワールド・ベースボール・クラシック(WBC)の年でもありますし, このテーマいいんじゃないかなと.

パッと思いつくシナリオはいくつかあります.

シナリオ
違うリーグで対戦が少ない or 無い Paul Skenes (DET/AL) vs Shohei Ohtani (LAD/NL)
国際大会で同チーム 投手・山本由伸 vs 打者・大谷翔平(侍JAPAN)
ゲームじゃないとできない対決 投手・大谷翔平 vs 打者・大谷翔平

野球は太古のセイバーメトリクスの時代からデータがたくさんある, かつ今はトラッキングデータも大量にあるので予測はできそうですし, LLMでいい感じにできそうです.

という興味(と自分がこういう道具欲しい)というモチベーションでチャレンジしました.

ちなみにできることはBaseball Savantのデータとしてある範囲かつ自分が運用しているBigQueryにデータセットとしてある選手が対象(2023年以降のデータはある*1), NPBおよび昔のデータはないので「オオタニサンVS近藤健介」「山本由伸はイチローを抑えられるか」みたいなテーマはできません, あしからず.

技術スタック

技術スタックは以下のとおりです.

レイヤー 技術
デモアプリ Marimo
データ処理 Polars
可視化 Plotly
LLM Google Vertex AI (Gemini)
デプロイ Docker + Cloud Run

Marimoでのプロトタイプはこちらのブログ,Plotlyでいい感じに可視化した話はこちらのブログで詳しく解説しています.

本件はMarimoアプリを育てつつ, 昔作ったPlotly(というよりDash)のアプリを元に構築しています.

一応補足ですが, LLMはこんな感じで使っています.

  • AI AgentはすべてGemini. Gemini 2.5 Flash. これを選んだ根拠は「とりあえずシュッと使えそうだった」からです.
  • 企画・開発・デバッグはすべてClaude Codeに任せています, 恐ろしいことに自分でコード書いていません&全てSpec & Design Doc駆動開発です.

開発スタイルもLLMに全振りです.

やったこと

Claude Codeと壁打ちをし, 議論を繰り返した結果こんなアプローチになりました.

  • セイバーメトリクスの知識を元に「計算」と「LLMの解釈」を分離する設計を考える.
  • Design Docを書いてClaude Codeにひたすら実装してもらう.
  • 確率計算ロジック,LLMプロンプト,可視化,UIをVibe Codingで仕上げる.

それぞれ解説します.

設計の核心 - 計算と解釈を分離する

「オオタニサンVSオオタニサン」を実現する技術, 通称「仮想対戦モード」の肝は,

確率計算とLLM分析を明確に分離すること

でした, これは私の思想とAIとの壁打ちで決めました.

[予測を生成] ボタン押下
       │
       ├──→ 確率計算(同期・即時)
       │     ├─ 球種別有利度の計算
       │     ├─ 予想打率・三振確率の算出
       │     └─ 総合ゲージ位置の決定
       │
       └──→ LLM分析(非同期・スピナー表示)
              ├─ 5セクションのテキストレポート
              └─ 球種別の攻略シナリオ

なぜ分離したのか?ですが,

野球データの数理モデル,いわゆるセイバーメトリクスを私が把握していた

からです, LLMのトークンを消費して自由にやらせる以上に答えが求めやすいので.

出塁率,長打率,OPSといったよく知られた指標からFIP,wRAA(ちなみに今回は両方採用していない)といったマニアックな指標まで, 私は計算式と概念を理解しています.

これらの仕様をSpec/Desing Docで言語化, LLM(今回はGemini)には「このデータから対戦シナリオを描き出す」といった解釈と実装に注力してもらいました.

担当 処理内容 特徴
確率計算(Python) 球種別有利度,予想打率,三振確率,四球確率,長打確率 即座に結果が出る. 再現性がある.
LLM分析(Gemini) 総合予測,球種別攻略分析,戦略提案,対戦シナリオ 文脈を読み取った分析. 人間が読んで面白い.

「野球の知識」「セイバーメトリクスの見解」「エンジニアリングの経験」を元に, 「ここはコードで計算できる」「ここはLLMに任せたほうがいい」という線引きをしました.

以前のブログで書いた,

人間がやる解説とAIでいい感じに別けてやればいいじゃん

の思想を今回も貫きました.

確率計算ロジック

仮想対戦の確率計算では,投手と打者の球種別成績を突き合わせるアプローチを取りました, ちなみにこれはClaudeからの提案を自分がちょこっと手直ししたものになります(おそらく今後もチューニングが続くでしょう).

たとえば投手Aの「4シームの被打率」が.220で,打者Bの「4シームに対する打率」が.280だった場合,この対戦における4シームの予想打率は両者の平均.250あたりになるだろう,という考え方です.

各球種の投手有利度(0-100)を算出するコア関数はこうなります.

def _calc_pitch_advantage(pitcher_avg, batter_avg) -> float:
    """球種別の投手有利度(0-100)を計算する"""
    combined_avg = (pitcher_avg + batter_avg) / 2
    advantage = (0.250 - combined_avg) / 0.250 * 50 + 50
    return max(0, min(100, advantage))

ポイントは以下の通り.

  • 基準値.250: MLB平均打率相当*2の値を「五分五分」の基準として使う
  • 0-100スケール: 0が完全に打者有利,50が五分,100が完全に投手有利
  • 加重平均: 各球種の投球数で重み付けして総合ゲージを算出

初心者向けに具体例で説明するとこんな感じ.

[例] 4-Seam Fastball の場合

  投手の被打率: .220(投手優秀 → 打たれにくい)
  打者の打率:   .280(打者優秀 → よく打てる)

  combined_avg = (.220 + .280) / 2 = .250(ちょうどMLB平均)
  advantage = (0.250 - 0.250) / 0.250 * 50 + 50 = 50(五分五分)

[例] Slider の場合

  投手の被打率: .180(決め球として優秀)
  打者の打率:   .200(苦手球種)

  combined_avg = (.180 + .200) / 2 = .190
  advantage = (0.250 - 0.190) / 0.250 * 50 + 50 = 62(やや投手有利)

打率以外の指標も,同様に投手側と打者側の値を平均して算出します.

指標 計算方法 信頼区間
予想打率 (投手被打率 + 打者打率) / 2 ±.015
三振確率 (投手K% + 打者K%) / 2 ±3%
四球確率 (投手BB% + 打者BB%) / 2 ±2%
長打確率 (投手被ISO + 打者ISO) / 2 × 2 ±3%

たとえば,投手の被打率が.230,打者の打率が.270なら,予想打率は(.230 + .270) / 2 = .250となり,±.015を加えた.235 - .265がエラーバー付きの横棒グラフとして可視化されます.

「予想打率.235-.265」のように幅を持たせることで,「これは精密な予測ではなく,幅を持った見積もりです」という意図を視覚的に伝えています.

確率計算をいい感じに可視化したやつ.

エラーバーで信頼区間を表現. 球種別有利度は50%基準線で投手有利/打者有利を色分け , これはめちゃくちゃ見やすくていいなと思いました.

なお,正直に書いておくとこのモデルにはいくつかの限界があります.

  • 投打の左右の相性を考慮していない: 左投手vs左打者のような組み合わせの有利不利は未反映. 実装の複雑さと得られる精度向上のバランスを考慮し,現段階では見送りました
  • 球種別K%/BB%は総合ゲージに含まれない: 球種別の三振率や四球率はサンプルサイズが小さくなりがちで信頼性が低いため,現状は球種別打率のみで重み付けしています
  • サンプルサイズの問題: 投球数が極端に少ない球種(シーズン中に数球しか投げていない球種など)の成績は信頼性が低い
  • 投球のコース・打球のコースへの配慮なし: Baseball Savantのデータで十分できるのですが今回は含めていません
  • ボールの変化量, 速度変化: これもBaseball Savantのデータで十分できます, 「落差3cmのスプリットは打てないが, 2cmなら打てるかもしれない」みたいな分析は頑張ればできると思います

と言っても,現時点で球種レベルで投手と打者を突き合わせるアプローチは直感的にわかりやすく,「なぜこの予測になったのか」を説明しやすいメリットがあります.

完璧なモデルよりも解釈しやすいモデル(とプロダクトとしてのAI Agent開発)を優先した 意思決定は間違ってないなと思います, 我ながら.

加えて説明的なブログも書けているので完璧です.

LLM分析

LLMには計算で使ったのと同じ統計データをテキスト形式で渡します. プロンプトの構造はこんな感じです.

【投手データ(2025シーズン)】
## 通常統計
投手名: Gerrit Cole
被打数: 580, 被安打: 138, 被HR: 18, 奪三振: 195, ...

## セイバーメトリクス指標
被打率: .238, 被OBP: .295, K%: 33.6%, BB%: 6.2%, ...

## 球種別成績
4-Seam Fastball: 投球割合 35.2%, 被打率 .220, K% 28.5%
Sweeper: 投球割合 22.1%, 被打率 .185, K% 42.3%
...

【打者データ(2025シーズン)】
(同様の構造)

LLMには以下の5セクションでレポートを出力させます.

  1. 総合予測 - 投手有利/五分/打者有利 + 確信度(高/中/低) + 根拠
  2. 球種別の攻略可能性 - 投手の各球種が打者にどう効くか
  3. 推奨戦略 - メイン選手側(視点)へのアドバイス
  4. 相手の脅威 - 警戒すべきポイント
  5. 予想される対戦シナリオ - 典型的な打席展開

「視点」は選択した選手のポジションから自動決定されます. 投手を主役にしているなら投手視点のアドバイス,打者を主役にしているなら打者視点のアドバイスが生成されます.

確信度は「高/中/低」の3段階で,LLM自身がデータの十分性(サンプルサイズ,球種の多様性など)を判断して付与します. 確信度が低い場合は,ユーザーが結果を鵜呑みにしないための目安になります.

真剣分析 / エンタメモード

同じデータに対して,プロンプトのトーン指示だけを変えることで2つのモードを実現しています.

真剣分析モードの指示:

あなたはMLBのプロスカウトです.
客観的かつ冷静にプロフェッショナルとして分析してください.

エンタメモードの指示:

あなたはMLBの名物解説者です.
野球ファンを楽しませるように,ドラマチックでワクワクする表現で分析してください.
「夢の対決」「因縁の対決」のような盛り上げ方を意識してください.
ただし,分析の根拠はデータに基づいてください.

エンタメモードでも「分析の根拠はデータに基づいてください」という一文が入っています. 盛り上げつつもデタラメは言わないようにする,というバランスが大事です.

先程冒頭で菅野智之投手がロッキーズに移籍したという話題をしましたが, 元のオリオールズには入れ替わりで強打者ピート・アロンソ(メッツ)が加入しました.

この出会うこと無い(かもしれない)2人の対戦*3を「エンタメモード」で解説するとこうなりました(補足・架空の設定ですがデータでの根拠に基づいた推測です).

菅野VSピート・アロンソ

結果はお察しですが, エンタメモードの解説者はどうでしょう.

ちゃんと解説してくれてる

ちゃんと球種別に丁寧解説してますが, なんかエンタメ感あります.

命令口調なのは気の所為でしょうか

感想がもはやファンですw

北米の怪獣って呼んでましたっけ?w

アロンソは伊達に「北米の怪獣」と呼ばれているわけではありません。スガノが警戒すべき、アロンソの恐るべき強みを見ていきましょう!

LLMなりにあだ名を付けて盛り上げてくれたことは理解しました, エンタメ感すごい.

今回は極端な組み合わせでしたが, もっと競った相手だとそれなりに面白い結果になるかもしれません.

なお,LLMなので何らかの理由で失敗した場合(タイムアウト,レスポンス不正など)においても,

  • 確率計算によるゲージや棒グラフは正常に表示
  • 前述の通り「LLM頼り」だけでもないので分析アプリとして成立

というところでいい感じにしています.

透明性の担保

LLMが生成するレポートには必ず疑問がつきます.

本当にデータに基づいているのか?

この問題に対して,仮想対戦モードではLLMに渡したデータをそのまま開示する仕組みを入れました.

ネストされたアコーディオンの中に,投手データと打者データが格納されています. 普段は折りたたまれていますが,展開すればLLMが分析に使ったデータをすべて確認できます.

Geminiも適当に盛り上げているわけではないという証拠

菅野さんだけでなく, アロンソもちゃんとデータみてます.

こっちもちゃんと入っています

AI分析の透明性を担保することで,ユーザーが「この分析は信頼できそうだ」「ここの解釈はちょっと違うのでは」と自分で判断できるようになります.

とくに野球ファンはデータリテラシーが高い人が多いので,元データを見せることの価値は大きいです.

課題

いい感じに仮想対戦モードができたものの,実は課題は山積みです.

あえて2つに絞ると以下ですかね.

  • 計算モデルの精度
  • LLMの出力安定性

計算モデルの精度

前述の通り,左右の相性やBaseball Savantデータの活用,サンプルサイズの問題は未対応です.

現在は「解釈しやすさ」を優先していますが,

  • 左右別成績(プラトーンスプリット)の導入
  • Baseball Savantデータの活用(変化量とか)
  • サンプルサイズに応じた信頼区間の動的調整

個人的には左右別とデータ活用を優先して対応するつもりです, どっちも結果に影響するので.

LLMの出力安定性

前回のブログでも課題として挙げました.

今回もやはりLLMの出力が安定しない問題はあります, といっても前回よりマシですが...

特に仮想対戦モードでは,投手と打者の両方のデータを入力するのでプロンプトが長くなりがちで,レスポンスの品質にムラが出ることがあります.

ただし,確率計算とLLM分析を分離しているので,LLMがコケても計算結果(ゲージ・グラフ)は表示されるのでこの辺はプロダクト・PoCとしてどう設計するか?の思想でどうにか頑張ってます.

結び&今後

「打者大谷は投手大谷からホームランを打てるか?」をAIはどう判断するか? お楽しみいただけましたでしょうか?

セイバーメトリクスの知識 × LLM(Gemini)で「AIと人間の役割分担」を実現した仮想対戦予測機能, めっちゃ使えそうな予感.

これは自分でも可能性あると思いましたし, このまま本当にAIで解説やらせる未来は実現できそうと思いました.

技術ブログ的なまとめとしては,

  • 何でもかんでもLLMにやらせるんじゃなくて, 敢えてルールベースで縛ってハイブリッドでやるのはアリ(セイバーメトリクスとLLMの役割分け)
  • LLMの出力不安定はあるものだと思って設計する

これらはエンジニアリングの経験・スキルとドメイン知識(今回は野球)の総力戦でどうにかしました&きっと再現性ある学びなのでAI Agent開発の参考になれば幸いです.

ちなみに今後についてですが, 今はmarimoで作ってる野球解説AI Agentは「SPA + APIの王道なWebアプリケーションに作り変え」をします.

  • フロントエンドをTypeScript + Next.js
  • バックエンドをPython(FastAPI)
  • 引き続きCloud RunなどGoogle Cloud上でホスト

みたいな感じでお届けできればと思います, 一般公開できるかは怪しいですが...

Marimoで検証したハイブリッドアーキテクチャや可視化の設計思想はそのまま引き継ぎます.

とはいえできればMLB開幕前にはなんとかできたらと思いますので乞うご期待ください.

最後までお読みいただきありがとうございました!

関連エントリー

*1:もっと細かい話をするとレギュラーシーズンのみ. プレーオフのデータは集めていません.

*2:ちなみにこれは適当です, .250が基準値はなんとなく収まりがいいので採用.

*3:MLBファンの方は「結果は明確じゃね?」と突っ込みそうですが, これは技術ブログなので何卒お付き合いください🙏




以上の内容はhttps://shinyorke.hatenablog.com/entry/ai-matchup-ohtani-vs-ohtaniより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14