0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プロ野球の順位表のデータから順位予測のモデルを作るのは難しい

Last updated at Posted at 2024-02-10

はじめに

冬から春先にかけてプロ野球の解説者が新シーズンの順位予想をします。
その順位予想は「上位にK藤、Y田、Y川がいるから⚪︎位」のように感覚的で抽象的であると思いましたので、機械学習を用いて順位予測ができないか手軽にコードを書いてみましたが、精度の高くない順位予測モデルが出来上がりましたので作業内容を一部だけ公開します。

resized_futuristic_baseball_stadium.png

つくるもの

パリーグの順位表を独自集計しているサイト(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

コード

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です

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?