はじめに
冬から春先にかけてプロ野球の解説者が新シーズンの順位予想をします。
その順位予想は「上位にK藤、Y田、Y川がいるから⚪︎位」のように感覚的で抽象的であると思いましたので、機械学習を用いて順位予測ができないか手軽にコードを書いてみましたが、精度の高くない順位予測モデルが出来上がりましたので作業内容を一部だけ公開します。
つくるもの
パリーグの順位表を独自集計しているサイト(NPBの公式のものを使用しようと思いましたがカラムが少ないため、非公式なものを使用しましたがデータの選定に関して参考にしないでください)からデータを引用し、決定木の手法で順位予測モデルを作成する。
打率や打点、防御率などをリクエストに詰めて、このモデルを呼び出すと順位を予測するREST APIを作成(今回はモデル作成まで)
・データセット引用元サイト
https://baseballdata.jp/p/#
環境
python :3.12.1
pandas :2.2.0
pip :23.3.2
scikit-learn :1.4.0
ディレクトリ構成
データセットをdataディレクトリに配置して、rank_model.pyで読み込むという構成
app/
- data/
- 2021.json
- 2022.json
- 2023.json
- rank_model.py
コード
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from joblib import dump
def load_data(years):
all_data = pd.DataFrame()
for year in years:
with open(f"data/{year}.json", "r") as file:
year_data = pd.read_json(file)
all_data = pd.concat([all_data, year_data], ignore_index=True)
return all_data
def preprocess_data(data):
features = data.drop(['rank', 'team'], axis=1)
target = data['rank']
return train_test_split(features, target, test_size=0.2, random_state=42)
def train_model(X_train, y_train):
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
return model
def evaluate_model(model, X_test, y_test):
predictions = model.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
print(f'精度: {accuracy:.2f}')
def save_model(model, filename):
dump(model, filename)
# データの読み込み
years = ['2023', '2022', '2021']
data = load_data(years)
# データの前処理
X_train, X_test, y_train, y_test = preprocess_data(data)
# モデルの訓練
model = train_model(X_train, y_train)
# モデルの評価
evaluate_model(model, X_test, y_test)
# モデルの保存
save_model(model, 'rank_model.joblib')
実行結果
$ python rank_model.py
精度: 0.20
精度が0.20という低いモデルができました。
パリーグは6球団あるので、ランダムに順位を予測した場合は1/6、つまり16.6%
今回の精度0.20は20%なので、順位予測モデルとして有効的ではありません。せめて0.50にしたいです。
原因
順位予測は、打率などの数値から純粋に導き出すのが難しいものだと思われます。
打率や打点、防御率など順位と相関がありますが、怪我の離脱や移動を含めた試合スケジュール、天候などの外的要因やチームの雰囲気やチームスタッフのマネジメント・コーチングなどの相互作用が影響するのではないかと思われます。
また、今回使用した機械学習のアルゴリズムは決定木で、データセットには1年毎に6行しかデータがなく、決定木にはデータ数が少なかったと思われます。
改善案
- 2020年以前の成績などデータを増やす
- クロスバリデーションを使う
- ハイパーパラメータの調整(train_model関数のRandomForestClassifier)
おわりに
今回はざっくりモデルを作成してみたので、あまり参考にならないコード、低い精度になったと思います。
コードを修正して精度を高めることを試みたいと思います。
また、解説者には「⚪︎⚪︎選手の加入で打点が50打点増えると思うので首位を狙えると思います」など数値的な発言をすると、よりプロ野球ファンが興奮すると思います。期待します。
↓続き
⚾️おまけ⚾️
私が好きな野球系YouTuberです