1.前口上
大リーグで活躍している大谷翔平選手。目を見張る大活躍だ。
その大谷選手をテーマに機械学習を学べば、興味が持てて、身につくだろうということで、やってみた。
今回は、投手編。使用するデータは大リーグMLBが提供しているこちらのサイト。とっても充実した良いサイトだ。
https://baseballsavant.mlb.com/
データ分析には、GoogleのColaboratoryを使用した。自分のマシンより良いスペックのマシンが使えるのは嬉しい。
2.分析手法
日本では大谷投手の球速が話題になるけれど、大リーグでは回転数も注目されている。そこで、球速と回転数を使って、機械学習(教師なし、クラスタリング)をやってみよう。
まずは、先ほどのBaseball Savantのサイトから、2017年の投手のデータを集める。球種はデータが最も多いフォーシーム(いわゆるストレートの速球)。
大谷投手のデータだけは、2018年4月のデータを使った。
球速は大リーグで重宝されている「打者が体感する球速」を使ってみよう。これは、球を投げる際のリリース・ポイントが考慮されている球速で、打者に近いところでリリースされれば、その分だけ、打者との距離が短くなって、球を速く感じるということらしい。
球速も回転数も、対象期間の平均値を使用した。
3.クラスタリングの準備
データはpitch2017.csvという名前で保存して、Colaboratoryにアップロードする。
from google.colab import files
upload = files.upload()
ファイル選択の画面が出るので、アップロードするファイルを選ぶことになる。
念のため、確認すると、アップロードできたことが分かる。
!ls
ここから先はColaboratoryを使わない場合も同じ。Pandasを使って分析を進める。
import pandas as pd
df = pd.read_csv("pitch2017.csv")
df
対象とした33投手の名前とデータが分かる。(番号はゼロ始まり)
大谷投手のデータは最後に加えている。
まずは、散布図で見てみよう。
df.plot(kind='scatter',x='Avg Perceived Speed (mph)',y='Avg Spin Rate (rpm)')
4.クラスタリング(失敗例)
まず、失敗した例から見ていこう。
データ加工しないで、クラスタリングをしてみる。
クラスタリングの結果はresultsに格納する。
from sklearn.cluster import KMeans
km=KMeans(n_clusters=3,
init='k-means++',
random_state=0)
X=df[['Avg Perceived Speed (mph)','Avg Spin Rate (rpm)']]
km.fit(X)
y=km.labels_
df['results']=y
df.tail()
結果を散布図で見てみよう。
import matplotlib.pyplot as plt
%matplotlib inline
plt.scatter(df['Avg Perceived Speed (mph)'].where(y==0),df['Avg Spin Rate (rpm)'].where(y==0),c="r",s=40)
plt.scatter(df['Avg Perceived Speed (mph)'].where(y==1),df['Avg Spin Rate (rpm)'].where(y==1),c="b",s=40)
plt.scatter(df['Avg Perceived Speed (mph)'].where(y==2),df['Avg Spin Rate (rpm)'].where(y==2),c="g",s=40)
plt.xlabel('Avg Perceived Speed (mph)')
plt.ylabel('Avg Spin Rate (rpm)')
何か、変じゃないですか?
上・中・下と並んでいる。
これって、単純に回転数だけでクラスタリングされている。
球速が二桁(およそ98mph)なのに対して、回転数は四桁(およそ2,300回転)。つまり、回転数が相対的に大きいので、回転数だけでクラスタリングされている。
これじゃマズイので、標準化して、やり直そう。
5.クラスタリング(やり直し)
まずは、関数を作って、標準化しよう。やっぱり、データの前準備が大切だ。
標準化したデータは球速A、回転数Bとしてデータフレームに追加しよう。
zscore=lambda x:(x-x.mean())/x.std()
df[['A','B']]=df[['Avg Perceived Speed (mph)','Avg Spin Rate (rpm)']].transform(zscore)
df.tail()
もう一度、クラスタリングして、
from sklearn.cluster import KMeans
km=KMeans(n_clusters=3,
init='k-means++',
random_state=0)
X=df[['A','B']]
km.fit(X)
y=km.labels_
df['results']=y
df.tail()
プロットしてみよう。
plt.scatter(df['A'].where(y==0),df['B'].where(y==0),c="r",s=40)
plt.scatter(df['A'].where(y==1),df['B'].where(y==1),c="b",s=40)
plt.scatter(df['A'].where(y==2),df['B'].where(y==2),c="g",s=40)
plt.xlabel('Avg Perceived Speed')
plt.ylabel('Avg Spin Rate')
大谷投手は球は速いけど、回転数は多くない投手にクラスタリングされている。
(黒い星で囲まれた赤い点が大谷投手のデータ)
大谷投手と同じクラスターに含まれる投手を上げてみよう。
df1=df['Pitcher'].where(y==0)
df1=df1.dropna()
df1
6参考データ
同じクラスターの投手をWikipediaで調べてみると、以下のようになっていた。(番号は表の番号と合わせている。説明は抜粋。)
1ノア・セス・シンダーガード(Noah Seth Syndergaard)
長身からオーバースローで投げ下ろす、平均97-98mph(約156-158km/h)・最速101.4mph(約163.2、km/h)の速球(フォーシーム・シンカー)を操るなど、平均球速は先発投手であるにもかかわらずMLB全体でもトップクラスである。また、制球も悪くない。変化球では縦に割れる平均81mph(約130km/h)カーブが一級品で、平均89mph(約143km/h)チェンジアップも投げ分ける。
7ジョセフ・ウィリアム・ケリー (Joseph William Kelly)
2015年までは、150キロ台前半から半ば (150 - 156キロ) のツーシーム (シンカーとも) が主体をなしていたが、2016年にリリーフに転向すると球速が増して、161キロまで出るようになった。変化球としては、チェンジアップ・カーブ・スライダーがある。投球スタイルとしては、ツーシーム・シンカーでゴロを量産するグラウンドボールピッチャーだったが、リリーフ転向後は三振を大量に奪うようになった。
8ホセ・アントニオ・アルバラド
96-99mphの4シームを投げるほか、カーブは80mph前半。コントロールに難あり。ベネズエラ出身。
19トーマス・ロバート・ケインリー(Thomas Robert Kahnle)
オーバースローから、最速球速100.6mph(162km/h)・平均98mph(158km/h)のフォーシームを中心に、決め球である平均90mph(145km/h)のチェンジアップ、平均87mph(140km/h)のスライダーで投球を組み立てる。
29ルイス・アマド・ガルシア(Luis Amado García)
2016年、メジャーでは17試合の登板に留まり、防御率6.46・1勝1敗・WHIP1.89と炎上して結果を残せなかった。
30ホセ・ラファエル・ディアス・ロドリゲス(Jose Rafael Diaz Rodriguez)
スリークォーターから、平均球速96 mph(約154 km/h)のフォーシーム、平均86 mph(約138 km/h)のスライダー、平均96mph(約154 km/h)のシンカー、平均90 mph(約145 km/h)のチェンジアップ、稀に平均94 mph(約151 km/h)のカッターも使用する。
球速がある一方、制球に苦しんでいる投手もいるらしい。
7最後に
このクラスタリングが有益かどうか、僕には正直、分らない。
ただ、大谷翔平選手のピッチャーとしての位置付けを確認したかったので、ひとまず、これで良しとしよう。
なお、大リーグについて言えば、お勧めのサイトを紹介したい。
Baseball Geeksというサイトだ。
見た目も、中身も、とっても良いサイトなので、個人的に大好きなサイトだ。
https://www.baseballgeeks.jp/
大谷翔平選手が、投手としても、大リーグで活躍を続けることを祈って、本稿を終わることとする。