次の一投の行方を予測! プロ野球データ分析チャレンジ

ストライク? ヒット? それともホームラン!?

賞金: 100,000 参加ユーザー数: 384 3年弱前に終了
※2021/4/9,10にデータダウンロードされた皆さま

上記期間のtrain_data.csv, test_data.csvにおいて、totalPitchingCount=1となるデータのバッティングカウント(B,S)に誤りがございました。
totalPitchingCount=1においてはB=0, S=0が正となります。
該当データをダウンロードされている方は、誠に恐れ入りますが、totalPitchingCount=1のB,SについてB=0, S=0と修正いただくか、再ダウンロード対応いただけますと幸いです。
お手数おかけいたしますが、何卒よろしくお願いいたします。

課題背景・目的

テクノロジーの進展により、近代野球におけるデータ活用はチーム編成や戦術を決めるうえで欠かせないものとなりました。

例えば、NPB(日本プロ野球機構)では、ヤクルトスワローズを率いていた野村克也監督が1990年代にID(Important Data)野球を提唱し、新しい取り組みを次々と実践していきました。
一例として、先発投手として当時成績の厳しかった江夏をリリーフ投手として抜擢、選手の特性に応じたチーム編成を行いました。またチームミーティングについては、従来の根性論に近い形式ではなく、投球分析に基づいた戦略を監督から選手に伝える場とするなど、運営方法までも大きく変革しました。

その結果、ヤクルトスワローズは1992、1993年と2年連続での優勝を手にしました。現在では、横浜DeNAベイスターズがデータ分析の専門部隊を結成するなど、データ活用はNPBの文化として強く根付いています。

        

MLBにおいても、1990年代後半のビリー・ビーンGMによるセイバーメトリクスという手法により、彼の率いるオークランド・アスレチックスは強豪チームの仲間入りを遂げました。
その活躍を描いた書籍「マネーボール」は大ヒットし、映画化までされています。

          


今回、こうした野球のデータ活用に親しんでいただくため、プロ野球の試合データを用いたコンペを設計しました。

本コンペでは、一球ごとの投球データ(球速・球種等)と試合状況・対戦者情報より、ストライク・アウト・ホームランといった投球結果を予測するモデル開発にチャレンジいただきます。
「打った」「点が入った」といった視点で試合を見るだけではなく、選手交代・配球など、意思決定の裏側にあるデータを知ることで、普段とは違った角度からも野球をお楽しみいただければ幸いです。



本コンペティションの特徴

今回のコンペでは、訓練データとして、球種、投球の速度、打球の距離や方角といった情報が与えられています。
これらのデータは、投球が行われるまでは未確定の情報となるため、テストデータからは除外されています。

本コンペを通じて、テストデータに含まれていない情報についても活用したモデル開発に親しんでいただけますと幸いです。

また、ストライクやファールに比べて2塁打やホームランといった打球は非常に数が少なくなります。このような不均衡データを用いていることも、本コンペの特徴です。


参考文献

■野球×データ分析

セイバーメトリクス入門  脱常識で野球を科学する
セイバーメトリクスの落とし穴~マネー・ボールを超える野球論~ (光文社新書)

■機械学習

Pythonで動かして学ぶ! Kaggleデータ分析入門 (AI & TECHNOLOGY)
Kaggleで勝つデータ分析の技術

ダウンロード

データをダウンロードするにはログインまたはユーザー登録して下さい

※2021/4/9,10にデータダウンロードされた皆さま

上記期間のtrain_data.csv, test_data.csvにおいて、totalPitchingCount=1となるデータのバッティングカウント(B,S)に誤りがございました。
totalPitchingCount=1においてはB=0, S=0が正となります。
該当データをダウンロードされている方は、誠に恐れ入りますが、totalPitchingCount=1のB,SについてB=0, S=0と修正いただくか、再ダウンロード対応いただけますと幸いです。
お手数おかけいたしますが、何卒よろしくお願いいたします。

概要

コンペに使用するデータは3つに分けられます。

  • 訓練データ(train_data.csv)
  • テストデータ(test_data.csv)
  • 試合情報データ(game_info.csv)

訓練データ、テストデータには、それぞれ20,400件、33,808件のデータ含まれます。
データには、各投球時の試合状況とその結果が含まれています。
訓練データでは投球結果に関して、球種、投球の速度、打球の距離や方角といった情報が与えられていますが、投球が行われるまでは未確定の情報となるため、テストデータからは除外されています。

データの形式

訓練データ/テストデータ

column name example description exist on test data?
totalPitchingCount 1 各打席の投球が何球目か yes
B 0 ボールカウント yes
S 1 ストライクカウント yes
O 0 アウトカウント yes
b1 False 1塁にランナーがいるか yes
b2 True 2塁にランナーがいるか yes
b3 True 3塁にランナーがいるか yes
pitcher - ピッチャー名(NaNを含む) yes
pitcherHand L 右投げか左投げか yes
batter - バッター名(NaNを含む) yes
batterHand R 右打ちか左打ちか yes
gameID 20202173 試合ID yes
inning 1回表 イニング yes
pitchType ストレート 球種 no
speed 149km/h 投球速度 no
ballPositionLabel 内角低め 投球位置 no
ballX 17 投球のX座標(1-21) no
ballY J 投球のY座標(A-K) no
dir S 打球方向(A-Z) no
dist 38.3 打球距離 no
battingType B 打球種類(B:バント, G:ゴロ, P:ポップフライ, F:フライ, L:ライナー) no
isOuts True 投球結果がアウトか no
y 1 投球結果(0:ボール, 1:ストライク, 2:ファウル, 3:アウト, 4:シングルヒット, 5:二塁打, 6:三塁打, 7:ホームラン)

batter、pitcherは、元データが一部欠損していたことにより、一部NaNとなっています。

試合情報

column name example description
startTime 18:00 試合開始時間
bottomTeam DeNA 後攻チーム名
topTeam 広島 先攻チーム名
place 横浜 試合会場
startDayTime 2020-06-19 18:00:00 試合開始日時
gameID 20202173 試合ID
目標

テストデータセットの投球時の状況に関するデータにもとづき、投球結果の予測をしてください。
yの値は、0,1,2,3,4,5,6,7のいずれかになるように設定してください。

yの値 投球結果
0 ボール
1 ストライク
2 ファウル
3 アウト
4 シングルヒット
5 二塁打
6 三塁打
7 ホームラン
評価指標
  • モデルの予測性能はMacro-F1で評価されます。
    $precision_k = \frac{TP_k}{TP_k + FP_k}$
    $recall_k = \frac{TP_k}{TP_k + FN_k}$
    $F1_{macro} = \frac{1}{8}\sum_{k=0}^{7} \frac{2 * precision_k * recall_k}{precision_k + recall_k}$
    ここで$TP_k$, $FP_k$, $FN_k$は各クラスについてのTrue Positive, False Positive, False Negativeとします。
  • 評価値は0以上1以下の値をとり、精度が高いほど大きな値となります。
提出ファイルの形式

回答用のsubmission.csvを用意する(エントリーとヘッダー行を含む) 。
提出されたファイルに余分な行や列(idとy以外)が含まれていた場合はエラーとなります。

提出ファイルは以下の列のみを必ず含んでください:

  • id(テストデータセットのカラムと同じ順序)
  • y(投球の結果)

以下は提出ファイルの例です。
id,y
0,4
1,1
2,1
3,7
4,0

コンペティションルール

■Open Review Competition

本コンペでは、開催期間終了後 賞金対象者のコードを公開し、ユーザーの皆様にチーティング有無をレビューしていただき順位確定させる、オープンレビュー方式のコンペティションを行います。


賞金対象ユーザー

コンペ終了後1週間以内:
トピックにて、学習過程の分かるコードの公開をお願いいたします。 (簡易解説までつけていただけると助かります。)

コード公開後1週間:
レビュアー(ユーザー)より、チーティングの疑いに関するコメントがある場合は、ご回答をお願いいたします。
※チーティングとは無関係のコメント(ノウハウに関する質疑 等)についてもご回答いただけると幸いですが、順位確定の判断材料とは致しません。


レビュアー(ユーザーの皆様)
コード公開後1週間: 公開コードを確認いただき、チーティングが疑われる場合は、トピックを通して質疑の投稿をお願いいたします。

レビュアーからの質疑と、回答状況をふまえて、最終的に運営側で順位確定を判断します。

■順位決定ロジック
  1. コンペ期間中はPublicリーダーボード(以下LB)により暫定評価を、最終結果についてはPrivate LBにより評価します。
    ※ Private LBはコンペ終了と同時に表示されます
  2. スコアが同値の場合は、早い日時に提出いただいたユーザーが上位となります。
  3. コンペ終了後であっても、不正が発覚の際は、対象ユーザーは失格となり、全体の順位が繰り上がります。
  4. 順位繰上げにより賞金対象者となられた場合は、繰上げ日より一週間以内に、トピックにてコードを公開いただき、「Open Review Competition」と同様のフローにて順位を確定させていただきます。
■タイムライン

開始日 2021/4/9 0:00 JST
終了日 2021/6/20 24:00 JST

エントリー締め切り なし

■システム利用
  • 参加者ごとに1つのアカウントでご参加ください
  • チーム参加の場合は、最大5名までエントリー可能です
  • 1日あたり、最大5回までの提出が可能です
■禁止事項
  • ユーザー間での情報共有
    コンペティションに関連するコード・データを、チーム外のユーザーと共有することはできません。全参加者が利用できる場合に限り、共有可能です。
  • 外部データ/学習済みモデルの使用
    本コンペティションの基本情報/データから取得できるデータのみを用いてチャレンジして下さい。コンペ外データを用いて学習されたモデルの使用も禁止とします。
    ただし、トピック上で、運営より承認された外部データのみ、活用を許可いたします。承認プロセスについては、「外部データ/学習済みモデルの使用申請について」をご確認ください。

※コンペ期間中であっても、不正が疑われる場合は、運営より確認のためメール連絡させていただくことがございます。一週間以内にご回答いただけない場合も、不正と判断させていただきます。

■外部データ/学習済みモデルの使用申請について

原則外部データ/学習済みモデルの使用は禁止としておりますが、正解データの入手につながらない場合は、下記承認プロセスにより使用できることといたします。

  1. トピックを作成し、取得元情報とデータ/モデル(格納先URLも可)を添付
  2. 運営にて判断・承認

注)ただし、コンペ終了まで7日をきってからの申請は禁止とします

■運営からのお願い

公平性の担保、チーティング等の不正防止のため、予告なくルールの追加・変更を行う場合がございます。
ご不便をおかけすることもあるかと思いますが、サービス向上のためご了承ください。

FAQ

このコンペティションでは賞金はでますか?

はい。
最も精度の高い学習モデルを作成した優勝者には、賞金10万円を贈呈します。
順位確定までのプロセスについては、ルール「Open Review Competition」を参照ください。

チームで参加できますか?

可能です。チームページから作成いただけます。

どこでアカウントをつくればいいですか?

こちらから作成いただけます。

コンペティション参加にはアカウント登録が必要となりますのでご注意ください。

外部データ/学習済みモデルを使うことは可能ですか?

申請を行うことによって利用可能です。
ルール「外部データ/学習済みモデルの使用申請について」を参照ください。

コードを提出するにあたって Seed を固定する必要はありますか?

Seed を固定することが推奨です。
ただし、Seed を固定しなくても提出用コードとしては認めています。

概要

このチュートリアルでは、野球の試合における投球データに対して

  • データの読み込み
  • データの確認と前処理
  • Scikit-Learnを用いてRandomForestによる分類モデルの作成、学習
  • 提出用データの作成

を行います。

#環境確認
import pandas as pd
import numpy as np
import sklearn
!python3 --version
print(pd.__version__)
print(np.__version__)
print(sklearn.__version__)
import matplotlib
print(matplotlib.__version__)
Python 3.8.6
1.1.1
1.18.5
0.23.2
3.3.3

データのロード

まずはデータを読み込んで見ましょう。csvデータの読み込みは複数のやり方がありえますが、pandasread_csv関数はその中でも機能が豊富で、扱いやすいためこれを使います。
これを使うと、csvデータを読み込み、pandas.DataFrameにして返してくれます。

#データの読み込みと前処理
import pandas as pd
train_data = pd.read_csv("train_data.csv", index_col='id')
print(train_data.shape)
(20400, 23)

また、DataFrameには.head()というメソッドが定義されており、これを呼び出すとDataFrameの先頭の数行を確認できます。

train_data.head()

totalPitchingCount B S O b1 b2 b3 pitcher pitcherHand batter ... pitchType speed ballPositionLabel ballX ballY dir dist battingType isOuts y
id
0 1 0 0 0 False False False 今永 昇太 L ピレラ ... ストレート 149km/h 内角低め 17 J NaN NaN NaN NaN 0
1 2 1 0 0 False False False 今永 昇太 L ピレラ ... ストレート 149km/h 内角低め 14 I NaN NaN NaN NaN 1
2 3 1 1 0 False False False 今永 昇太 L ピレラ ... チェンジアップ 137km/h 外角高め 8 D NaN NaN NaN NaN 0
3 4 2 1 0 False False False 今永 昇太 L ピレラ ... スライダー 138km/h 内角中心 21 G NaN NaN NaN NaN 2
4 5 2 2 0 False False False 今永 昇太 L ピレラ ... チェンジアップ 136km/h 外角中心 7 F S 38.3 G False 4

5 rows × 23 columns

データの確認と前処理

訓練データに説明変数yの分布がどのようになっているか確認してみます。

train_data['y'].value_counts()
0    7544
1    5611
2    3562
3    2509
4     797
5     223
7     142
6      12
Name: y, dtype: int64

ボール、ストライク、ファイル、アウトが多く、バッターが出塁することはなかなか難しいようです。

続いて、下記のコードを使用して使用するデータ全体の概観を確認します。
各項目について欠損値以外('non-null')の値がどの程度含まれているか把握できます。また、データの形式についてもここで判別可能です。

train_data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 20400 entries, 0 to 20399
Data columns (total 23 columns):
 #   Column              Non-Null Count  Dtype  
---  ------              --------------  -----  
 0   totalPitchingCount  20400 non-null  int64  
 1   B                   20400 non-null  int64  
 2   S                   20400 non-null  int64  
 3   O                   20400 non-null  int64  
 4   b1                  20400 non-null  bool   
 5   b2                  20400 non-null  bool   
 6   b3                  20400 non-null  bool   
 7   pitcher             20400 non-null  object 
 8   pitcherHand         20355 non-null  object 
 9   batter              20400 non-null  object 
 10  batterHand          20355 non-null  object 
 11  gameID              20400 non-null  int64  
 12  inning              20400 non-null  object 
 13  pitchType           20400 non-null  object 
 14  speed               20400 non-null  object 
 15  ballPositionLabel   20400 non-null  object 
 16  ballX               20400 non-null  int64  
 17  ballY               20400 non-null  object 
 18  dir                 3642 non-null   object 
 19  dist                5166 non-null   float64
 20  battingType         3642 non-null   object 
 21  isOuts              5166 non-null   object 
 22  y                   20400 non-null  int64  
dtypes: bool(3), float64(1), int64(7), object(12)
memory usage: 3.3+ MB

データの形式を見ると、バッティングの結果に関するカラムに欠損値が多いようです。またこれらのデータは被説明変数yとともにテストデータでは与えられない変数となっています。

予測モデルの作成、学習

モデルに投入する目的変数(y)、説明変数(X)を作成します。今回は学習データとテストデータの両方で与えられるカラムを用いてモデルを作成します。

X = train_data[['B', 'S', 'O', 'b1', 'b2', 'b3']]
y = train_data['y']

いよいよ予測モデルの作成に入ります。
model.fit('説明変数','目的変数')と記述することでモデルの学習が可能となります。目的変数を説明変数の組み合わせで説明可能な回帰モデルを作成できます。

#scikit-learnライブラリをimport
import sklearn
from sklearn.ensemble import RandomForestClassifier

#線形回帰モデルのインスタンス化
model = RandomForestClassifier()

#予測モデルの作成
model.fit(X, y)
RandomForestClassifier()

分類モデルの評価

list(reversed(sorted(list(zip(model.feature_importances_, X.columns)))))
[(0.3209557774604652, 'S'),
 (0.2948133327526405, 'B'),
 (0.14942731837880008, 'O'),
 (0.08071108251796956, 'b1'),
 (0.0771053739782763, 'b2'),
 (0.07698711491184829, 'b3')]

RandomForestではfeature_importances_で特徴量の重要度を取得することができます。
どのベースにランナーがいるかという情報はあまり重要ではないようです。

モデルの評価

また、コンペの評価指標となるf1スコアを確認してみましょう。
今回は、sklearn.metricsに含まれるf1_scoreメソッドを使用します。
1に近いほど予測精度が高いことを表します。
モデルを元にした予測値は、model.predict('説明変数')で表します。

# F1スコアの出力
from sklearn.metrics import f1_score
y_true = y
y_pred = model.predict(X)
print(f1_score(y_true, y_pred, average='macro'))
0.15409650198369168

今回作成したモデルのF1スコアは15.4%程度でした。利用した説明変数の組み合わせの総数が高々400程度であることが原因と思われます。

テストデータに対する出力

最後に、作成したモデルを使用してテストデータでの投球の結果を予測します。

path_test = "test_data.csv"
test_data = pd.read_csv(path_test, index_col='id')
test_data.head()

totalPitchingCount B S O b1 b2 b3 pitcher pitcherHand batter batterHand gameID inning
id
0 2 1 0 0 False False False 遠藤 淳志 R 乙坂 智 L 20202564 2回表
1 1 0 0 0 False False False バンデンハーク R 西川 遥輝 L 20202106 3回裏
2 7 3 2 2 True False False スアレス R 堂林 翔太 R 20203305 9回裏
3 1 0 0 2 True False False クック R 井領 雅貴 L 20202650 3回裏
4 2 0 0 2 False False False 則本 昂大 R 安達 了一 R 20202339 2回表
test_X = test_data[['B', 'S', 'O', 'b1', 'b2', 'b3']]

先ほど使用したmodel.predict('説明変数')説明変数にテストデータの値を代入することで、テストデータの予測値を算出することができます。

下記のようにして、提出用のsubmission.csvを出力することが可能です。

#テスト結果の出力
test_predicted = model.predict(test_X)
submit_df = pd.DataFrame({'y': test_predicted})
submit_df.index.name = 'id'
submit_df.to_csv('submission.csv')

「次の一投の行方を予測!プロ野球データ分析チャレンジ」コンペティション参加規約

コンペティションへの参加に際しては、ProbSpace利用規約(以下、「利用規約」といいます。)に加え、本ProbSpace参加規約(以下「本規約」といいます。)に同意いただく必要があります。利用規約にて定義された用語は、本規約においても同様の意味で用いられるものとします。

第1条(適用)

  1. 参加者(第2条に定義します。)は、コンペティションに参加した時点で、本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールの一切に同意したものとみなされます。
  2. 本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールは、コンペティションの終了後も参加者に適用されます。

第2条(定義)
本規約において次の各用語の定義は、それぞれ以下に定めるとおりとします。

  1. 「本コンペ」とは、当社ウェブサイト上で開催されるAI開発又はデータ分析等に関するコンペティションのうち、本規約に紐づく特定のコンペティションを意味します。
  2. 「主催者」とは、当社またはユーザーのうち、本コンペを主催する者を意味します。また、本コンペが、当社の顧客又は提携先の企業、学校その他の団体等がスポンサードするものである場合は、当該団体等も主催者の定義に含まれます。
  3. 「参加者」とは、ユーザーのうち、主催者側以外の立場で本コンペに参加する方を意味します。
  4. 「成果物」とは、本コンペにおいて参加者により開発される学習済みモデル、そのソースコード及び乱数シード等の設定値を意味します。
  5. 「入賞者」とは、当社より本コンペに入賞した旨の通知を受けた参加者を意味します。
  6. 「知的財産権」とは、著作権(著作権法第27条及び第28条に定める権利を含みます。)、特許権、実用新案権、商標権、意匠権、その他のノウハウ及び技術情報等の知的財産権(それらの権利を取得し、又はそれらの権利につき登録等を出願する権利を含みます。)を意味します。

第3条(権利の帰属)

  1. 本コンペで発生した成果物に関する知的財産権は、参加者に帰属します。

第4条(入賞者の義務)

  1. 入賞者は、本コンペで公開した成果物を、MITライセンスを適用し、商用利用の許諾条項及び著作権人格権の包括的不行使条項をライセンス条項に付与した形式で、オープンソースソフトウェアとして公開する義務を負うものとします。その前提として、入賞者は、成果物について本項に基づく方法でオープンソース化する権利を有していることを当社に対して表明保証するものとします。
    ※第三者が、授業・研修・セミナー等で活用できるようにするための規約となります。ご理解のほどよろしくお願いいたします。
  2. 当社は、以下の3点の確認が完了した時点で、本コンペの賞金または商品を、入賞者に対して授与するものとします。
    1. 入賞者が、前項に基づいて成果物のオープンソース化を実施したこと
    2. 入賞者が、本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールの一切に違反していないこと
    3. 当社が定める方法による本人確認
  3. 当社は、入賞者が第1項に基づいてオープンソース化した成果物を、自由に商用利用することができます。

第5条(禁止事項)

  1. 参加者は、本コンペにおいて、以下の各号のいずれかに該当する行為を行ってはならないものとします。
    1. クラッキングやチート行為、なりすまし、盗用等の不正行為
    2. 第三者の知的財産権その他の権利を侵害する内容ないし態様で、参加者公開事項を公開する行為
    3. 主催者(当社以外の者に限ります。)に対する直接連絡、相談、依頼、勧誘、勧誘対応等の活動(但し、当社を介して当社が認めた方法により行うものは除きます。)
    4. 本コンペにおいて、当該コンペと直接関係のない成果物等を提出すること
    5. 本規約における参加者としての地位又は参加者としての権利義務について、譲渡、移転、担保設定、その他の処分をすること
    6. その他、本規約、参加ルール及び利用規約に違反する行為
  2. 参加者が前項に規定する禁止行為を行ったと当社が認める場合、当社は、当該参加者に事前に通知することなく、当該参加者の本コンペにおける失格処分、当社サービスの全部又は一部の利用停止、ユーザー登録の抹消、その他当社が必要と判断した措置をとることができるものとします。

第6条(本コンペの変更、中断、終了等)

  1. 当社は、参加者に事前の通知をすることなく本規約に基づく本コンペの開催内容の変更、本コンペの一時的な中断又は終了を行うことができます。
  2. 当社は、本条に基づき当社が行った措置により生じた結果及び損害について、一切の責任を負わないものとします。

第7条(損害賠償)

  1. 参加者は、本コンペに関連して、自らの責に帰すべき事由により、当社、主催者その他の第三者に損害を与えた場合には、その一切の損害(逸失利益、弁護士費用を含みます。)を賠償するものとします。
  2. 参加者が本規約の規定に違反したことにより主催者(当社を除きます。)その他の第三者が当社に対して何らかの訴え、異議、請求等がなされた場合において、当社から処理の要請がなされたときは、参加者は自己の責任と費用負担において、当社に代わって当該第三者との紛争を処理するとともに、当社がかかる訴え、異議、請求等により被った一切の損害(逸失利益、弁護士費用を含みます。)を賠償するものとします。

第8条(本規約の変更)
当社は、必要と判断した場合には、参加者に対して事前に通知する(本コンペにかかる当社ウェブサイト上での告知その他当社が適当と認める方法を含みます。)ことにより、いつでも本規約を変更することができるものとします。なお、変更内容の通知後、参加者が当社の定める期間内に本コンペへの参加を取り消す手続をとらなかった場合には、当該参加者は変更後の規約に同意したものとみなされます。当社は、本規約の変更により参加者に生じたすべての損害について一切の責任を負いません。

第9条(その他)
本契約の準拠法は日本法とし、本契約に起因し又は関連する一切の紛争については、当社の本店所在地を管轄する裁判所を第一審の専属的合意管轄裁判所とします。

(制定)2020年6月22日