プロ野球の順位予測APIを作成してみた

以前公開したプロ野球の順位予測モデルを作成する記事の続きです。
試行錯誤を繰り返し、順位予測の精度を0.20→0.75に大幅改善することができました。
この精度を改善したモデルを使用して、順位予測をするAPIを作成しました。

前回の記事はこちら

https://qiita.com/wooooo/items/bcc830c8e14a9eef52fe


# APIのコード
Flaskなどのフレームワークを使用せずにPythonだけで書いてみました。
```python:app.py
from http.server import BaseHTTPRequestHandler, HTTPServer
import urllib.parse as urlparse
from joblib import load
import numpy as np

model = load('rank_model.joblib')


class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # パスからクエリパラメータを解析
        query_components = urlparse.parse_qs(urlparse.urlparse(self.path).query)

        # 順位予測に必要なパラメータ
        features_params = [
            "games", "wins", "losses", "draws", "winning_percentage",
            "ERA", "batting_average", "home_runs", "stolen_bases", "runs_scored",
            "runs_allowed", "sacrifice_hits", "sacrifice_hit_rate", "QS_rate", "RISP",
            "UC_hitting", "pinch_hitting", "errors"
        ]

        # リクエストパラメータをリスト化
        features = []
        for feature in features_params:
            if feature in query_components:
                features.append(float(query_components[feature][0]))
            else:
                features.append(np.nan)

        # リクエストパラメータに任意項目がない場合はエラーを返す
        if not any(feature != np.nan for feature in features):
            self.send_error(400, 'パラメータが含まれていません。')
            return

        # パラメータがある場合、順位予測
        predict_rank = model.predict([features])[0]

        self.send_response(200)
        self.send_header('Content-Type', 'text/plain')
        self.end_headers()
        self.wfile.write((f"予測順位は {predict_rank}位").encode('utf-8'))


def run(server_class=HTTPServer, handler_class=RequestHandler, port=8000):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print(f"Starting httpd on port {port}...")
    httpd.serve_forever()


if __name__ == "__main__":
    run()
```

このコードを実行するとport8000で起動します。

# 実行方法
先ほどのコードを実行します
```shell
$ python app.py
```
そうすると以下のテキストが出力されます
```
Starting httpd on port 8000...
```

次にcurlコマンドを実行し、先ほど起動させたAPIを呼びます。
```shell
$ curl "http://localhost:8000/?ERA=2.73&batting_average=.250&home_runs=109&stolen_bases=52&runs_scored=508&runs_allowed=428&sacrifice_hits=83&sacrifice_hit_rate=83.00&QS_rate=53.15&RISP=0.267&UC_hitting&0.237&pinch_hitting=0.226&errors=54"
```
実行結果です。
```
予測順位は 1位
```

このようにlocalhostのURLにERA(防御率)などのパラメータを与えると予想順位を返してくれます。

ちなみに先ほど実行したリクエストパラメータは2023年シーズンに1位だったオリックスの成績です。

# 試し
続いて、2023年シーズン5位だった埼玉西武ライオンズの成績でcurlを実行してみます。
```shell
$ curl "http://localhost:8000/?ERA=2.94&batting_average=0.233&home_runs=90&stolen_bases=80&runs_scored=435&runs_allowed=465&sacrifice_hits=90&sacrifice_hit_rate=80.36&QS_rate=60.14&RISP=0.220&UC_hitting=0.235&pinch_hitting=0.175&errors=66"
予測順位は 5位
```
単純に、2024年シーズンは防御率が良くなり、期待の長距離砲の新外国人2名の加入によりホームラン数が増えたとして、再度実行してみます。

|項目|パラメータ|改善前|改善後|
|--|--|--|--|
|防御率|ERA|2.94|2.70|
|本塁打|home_runs|90|120|
|得点|runs_scored|435|460|
|失点|runs_allowed|465|440|

```shell
& curl "http://localhost:8000/?ERA=2.70&batting_average=0.233&home_runs=120&stolen_bases=80&runs_scored=480&runs_allowed=440&sacrifice_hits=90&sacrifice_hit_rate=80.36&QS_rate=60.14&RISP=0.220&UC_hitting=0.235&pinch_hitting=0.175&errors=66"
予測順位は 3位
```

補強の想定ではおそらく今年は3位です。（機械学習、いわゆるAIが出した答えでは）

以上です。
プロ野球ファンのエンジニアの方がいらっしゃいましたらご参考にお願いします。
気分でセリーグの順位予測を作りたいと思います。ARE

# 補足
リクエストパラメータの各項目の説明です。
+ ERA: 防御率
+ batting_average :打率
+ home_runs : 本塁打
+ stolen_bases : 盗塁
+ runs_scored : 得点
+ runs_allowed : 失点
+ sacrifice_hits : 犠打
+ sacrifice_hit_rate : 犠打成功率
+ QS_rate : QS率
+ RISP : 得点圏打率
+ UC_hitting : 試合の勝敗に関係する（同点、勝ち越し、逆転）場面の打率
+ pinch_hitting : 代打率
+ errors : 失策