Re:ゼロから始めるML生活

Standing on the shoulders of Giants

数字で見るバスケットボール

最近Sports Analyst Meetupの発表を聞かせて頂いて、毎回非常に面白いLTばかりで、自分でもやってみたくなりました。

とはいうものの、分析・機械学習ですらまともにやったことがなく、スポーツに関する分析に至っては何から手をつけていいのかわかりませんでした。 そんなところに、最近気になる書籍が発売されました。

バスケットボールについての分析に関する本のようです。(概要)

サンプルコードも提供されているので、勉強にはもってこいですね。 こちらの書籍を参考に、Bリーグのデータをつかってバスケットボール分析をやってみたいと思います。

tl;dr;

  • B.LEAGUEではディフェンスが強いチームが勝てるような傾向が見られる
  • 攻撃についてはアシストが増加するようなチームの連携が増えると勝ち星が多い傾向が見られる

今回使用したコード

使用したコードについてはこちらにあります。

colab.research.google.com

描画にplotlyを使っているので、インタラクティブに結果が見たいという方はノートブックから確認したほうが良いかと思います。

諸注意

まず、こちらの一言のご紹介から。

“We’ve got 43 wins. If we win (tonight), we’ll have 44. That’s the only number you guys (media) should care about.
“Stats are great, but wins and losses matter. Stats are killing the game of basketball. Basketball is a subjective game. A lot of things happen that you cannot measure in stats.
“Different things matter. To me, the most important things in basketball are not measured by stats.” Marc Gasol: 'Stats Are Killing Basketball'

これはマルク・ガソル選手の言葉だそうです。

DeepLで翻訳するとこんな感じです。

"我々は43勝を挙げている。今夜勝てば44勝になる。君たち(メディア)が気にするべき数字はそれだけだ。 "統計は素晴らしいが、勝敗は重要だ。統計はバスケットボールのゲームを殺している。バスケットボールは主観的なゲーム だ。統計では測れないようなことがたくさん起こる。 "様々なことが重要だ 私にとって バスケットボールで最も重要なことは スタッツでは測れない"

バスケットボールは非常に数あるスポーツの中でも、トップクラスにデータを取得しているスポーツです。 そのバスケットボールにおいて、トップ選手からこのような発言が出るほど、表面上のデータを見るだけでは説明できないことも非常に多いのも事実です。

問題なのは、表面上のスタッツだけに注目してしまうことです。 本当に必要なのは、それらの情報を紐解いて洞察を得て、勝利につなげていくことかと思います。 なので、今回の記事も真に受け過ぎず、勝利のためにスタッツ以外のことにも注目する視野の広さは重要なので、その点はご注意ください。

問題定義

データ

今回参考にしている本ではNBAシーズンのスタッツを使用して分析を行っています。 今回はBリーグのデータに適用してなぞっていきたいと思います。

19-20シーズンの各スタッツはこちらに公開されています。

www.bleague.jp

また、こちらで紹介されているパッケージなどからも簡単に取得できるようです。

bleaguebydata.hatenablog.jp

このあたりからデータを取得してやってみます。

B.LEAGUEのデータを見てみる

まずは、全チームのスタッツをもとに上記の可視化をしてみます。 2019-20シーズンは残念ながら、リーグ終盤で中止になってしまいましたので、今回は2018-19シーズンのデータを見ていきます。 勝ち星に関してはこの様になっていました。

f:id:nogawanogawa:20200426143402p:plain

ポゼッション

ここから、スタッツを見る上での指標について確認します。 詳しくは本書をちゃんと読んでいただたいのですが、この記事に関係しそうな部分だけ簡単に紹介します。

試合中のボールの保有率を表すポゼッションは、時間ではなく、下記のようにゲームスタッツから計算されます。

 POSS = (P2A + P3A) + 0.44 × FTA − OREB + TOV

  • P2A:2Pシュート(アテンプト)
  • P3A:3Pシュート(アテンプト)
  • FTA:フリースロー(アテンプト)
  • OREB:オフェンスリバウンド
  • TOV:ターンオーバー

基本的にはどれだけシュートに行ったか、どれだけ攻撃回数を重ねられたかが指標になっています。 リバウンドは成功した場合には攻撃が継続するため、その分が差し引かれています。

f:id:nogawanogawa:20200426143351p:plain

グラフを見る限り、名古屋や千葉は攻撃回数が他のチームより多いことがわかります。 それと比べると、勝ち星の多かったA東京や栃木はそれほど攻撃回数が多くなく、少ない回数の攻撃で確実に点を積み上げていったようです。

攻守のPOSSの値を可視化してみるとこのような形になりました。

f:id:nogawanogawa:20200426143418p:plain

グラフから分かるのは、チームごとに試合の攻撃試行回数がバラけており、名古屋は非常に攻撃・守備の回数が多く試合展開が速いことがわかります。 一方琉球は試合展開としてゆっくり時間を使った試合になることが多いようです。

ペース

試合の展開の速さを表すペースは下記の様に算出されます。

P ACE = 5 × POSS/MIN

  • POSS : ポゼッション
  • MIN : 試合に出場した全選手の出場時間の合計

ペースは試合時間あたりの攻撃回数という指標になりそうです。

f:id:nogawanogawa:20200426144457p:plain

POSSでもそうでしたが、名古屋と横浜は攻守の切り替えの回数が多く、速い試合展開のことが多いようです。 逆に琉球やA東京、栃木などは比較的じっくり時間をかけた試合になるようです。

レーティング

ポゼッションに対する得点効率を表すレーティングは下記の様に計算されます。 自チームのレーティングは下記の様に計算されます。

ORtg = PTS_T /POSS_T

一方、自チームの守備に関するレーティングは下記の様に計算されます。

DRtg = PTS_O /POSS_O

どちらもポゼッションあたりの得点を表しています。

f:id:nogawanogawa:20200426144650p:plain

結果より、千葉ジェッツは攻撃は効率よく決めつつ、相手には点を取らせない良い効率で試合を進めることができていることがわかります。 逆に、北海道・横浜・福岡・秋田などは、攻撃回数の割に攻撃が抑え込まれることが多いようです。

four factors

最後に、four factorを示します。

Factor Offence Difense
eFG%  \frac{P2M_T + 1.5 × P3M_T}{P2A_T + P3A_T}  \frac{P2M_O + 1.5 × P3M_O}{P2A_O + P3A_O}
TO Ratio  \frac{TOV_T}{POSS_T}  \frac{TOV_O}{POSS_P}
REB %  \frac{OREB_T}{OREB_T + DREB_O}  \frac{OREB_O}{OREB_O + DREB_T}
FT Rate%  \frac{FTM_T}{P2A_T+P3A_T}  \frac{FTM_O}{P2A_O+P3A_O}

上からフィールドゴール成功効率(得点基準)、ターンオーバー比率(どれだけターンオーバーした/されたか)、リバウンド率、フリースロー率を表しています。

まず、自チームについて示します。

f:id:nogawanogawa:20200426145056p:plain

次に対戦相手について示します。

f:id:nogawanogawa:20200426145128p:plain

千葉は、攻撃は効率よく守備では点をうまく防げていることがわかります。 秋田は被ファールの数が多く、自チームのリバウンド数が多いことから、ペイントエリア内ではかなり試合運びがうまいのかもしれません。

見ていて気になったこと

これだけでも色々面白い情報が見つかるとは思います。 今回は分析したいことのゴールとして、

  • 強いチームの強さの秘訣を知る

こととしたいと思います。

分析の方針としては、

  • チーム・選手の傾向を見る
  • 対戦相手との関係を見る
  • 勝ちパターンと要因を見る

という流れでやっていきたいと思います。

チーム・選手の傾向を見る

まずは、チーム・選手の傾向ごとにグルーピングしていきたいと思います。 チームとしては、各チームがどんなチームであるか、どのチームと似ているかを見つけていきたいと思います。 選手としては、選手全体で見たときに各選手がどんな選手なのかを見ることで、これらをグループを見つけていきたいと思います。

チームの階層化クラスタリング

各チームがどんなチームなのか、階層化クラスタリングで分類して考えます。

f:id:nogawanogawa:20200426145953p:plain

下記の記事によると、今回の実装では距離計算法は最大距離(complete)、メトリックはEuclideanを使用しているようです。

community.plotly.com

階層化クラスタリングの結果から大きく3グループに分けられるようです。

  • Aグループ
    • 千葉ジェッツ
    • 名古屋ダイヤモンドドルフィンズ
    • 川崎ブレイブサンダース
    • 富山グラウジーズ
  • Bグループ
    • 秋田ノーザンハピネッツ
    • シーホース三河
    • 三遠ネオフェニックス
    • 栃木ブレックス
    • アルバルク東京
    • ライジングゼファー福岡
    • レバンガ北海道
    • サンロッカーズ渋谷
    • 横浜ビー・コルセアーズ
  • Cグループ
    • 新潟アルビレックスBB
    • 京都ハンナリーズ
    • 大阪エヴェッサ
    • 琉球ゴールデンキングス
    • 滋賀レイクスターズ

選手のクラスタリング

上記と同様に、階層化クラスタリングによって選手を分類していきたいと思います。

f:id:nogawanogawa:20200426150130p:plain

ちょっと量が量なだけに、クラスタの読み取りは困難ですね。 一つわかるのは、上の山は完全に外国人選手なので、そういった傾向が大きいクラスタなのでしょう。 下段は本当に人数が多いので、難しいです。 細かい内容が見たい方は、上のノートブックを直接ご参照ください。

対戦相手との関係を見る

上でグループについて確認しました。 今度はそれぞれの相性について確認したいと思います。

A~Cグループは、傾向の近いもの同士でグループになっているので、グループごとに戦績に影響があるかを確認します。 各クラスタごとの勝率を計算すると、このようになります。

f:id:nogawanogawa:20200426172656p:plain

AグループはB、Cグループに対して勝率が高く、CグループはBグループに対して勝率が良いという結果になっています。 言われてみれば、Aグループは上位チームが多いので勝率は高いはずですね。 スタッツから上位チームがある程度選別できているので、そこそこ妥当な分類なのかもしれません。

勝ちパターンと要因を見る

最後に、上記の内容を踏まえて勝ちパターンの要因を考察します。

相関行列

まずは、勝敗に寄与するスタッツはどれか、相関行列を使用して確認してみたいと思います。

f:id:nogawanogawa:20200426151007p:plain

※画像では勝敗(Win、右から2番目)のラベルが切れてしまっていますので、詳しく見たい方は実際のコードから確認することをおすすめします。

結果として、上位5件は下記のようになっていました。

  • BL(ブロック数)
  • PTS(得点数)
  • DR(ディフェンスリバウンド数)
  • AS(アシスト数)
  • PFT(ターンオーバーからの得点数)

得点が勝敗に大きく寄与することはある程度納得いきますが、ブロック数(BL)が大きな値を示しており、意外な結果になっています。 アシスト数の影響力が強いのは、やはり個人ではなく連携から崩したほうが勝ちやすいということなのでしょうか。 あとはオフェンスリバウンドよりディフェンスリバウンドのほうが相関が強いので、きちんと守れるチームが勝ちやすいということでしょう。

また、フィールドゴール数より、3Pゴール数のほうが勝敗に与える影響が大きく、近年の3Pが重視されるバスケットボールのトレンドが出た結果となりました。

決定木で勝敗の分岐を可視化する

今度は、勝敗について決定木で学習した結果から、どのような点が勝負の分かれ目になっているかを確認したいと思います。

f:id:nogawanogawa:20200426163344p:plain

簡単に図の説明をすると、緑が勝利、黄色が敗北の分布を表しており、対象のパラメータの基準点より大きい場合は上、小さい場合は下方向に分岐しています。

分岐を見る限り、初めにブロック数が考慮されているようです。 つまり、試合展開が守備的か攻撃的かによって分類されている感じですね。

その後、上半分ではFTA(フリースロー試行回数)と得点、下半分ではFTM(フリースロー成功回数)が考慮されているので、フリースローは試合の特徴を決める大きな要素になっているようです。

その他、目立つのはファールの数の登場回数が多いことから、ファールは試合結果を大きく左右することがわかります。

勝利の要因を考える

このシーズン最も勝ち星が多かった千葉ジェッツについて見ていきたいと思います。 どうやらリーグの傾向として、

  • BL(ブロック数)
  • PTS(得点数)
  • DR(ディフェンスリバウンド数)
  • AS(アシスト数)
  • PFT(ターンオーバーからの得点数)

が勝ち星に対して相関関係を持っていそうということはわかりました。 ということで、千葉ジェッツの選手について深堀りしたいと思います。

各選手の主なスタッツをリーグの平均で標準化し、レーダチャートで表したものが以下のようになりました。

f:id:nogawanogawa:20200426154137p:plain

影響度の大きかったブロック数(BS)ですが、レーダーチャートで目立つマイケル・パーカー選手や大宮選手はリーグ全体でみてもブロック数が11番目、15番目と上位に入っています。 また、アシストにおいては富樫選手や西村選手がそれぞれリーグ6位、10位と、チームとしても攻撃面でも影響度の高いスコアを抑えられていることがわかります。

ということで、今回見ていた限りでは、

  1. 守備をしっかり固めた結果ブロック数やリバウンド数が増加
  2. チームの連携やターンオーバーからの攻撃できちんと決めきることでアシスト数が増加

のような傾向があると、勝利に結びつきやすいと考えらました。

(Rでやる場合) BasketballAnalyzeR

本書で実際に使用されていたRで使用するバスケットボール向けのパッケージだそうです。

BasketballAnalyzeR

バスケットボールの分析をするには、こちらを使うと便利そうです。

環境構築

こちらのパッケージを使用する場合にはRの環境構築が必要です。 簡単に利用する場合にはGoogle Colabで実行する形だと思います。 その場合は、設定が必要になるかと思いますのでご注意を。

www.marketechlabo.com

こちらの記事を参考に、notebookをローカルで

"kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },

となっているものを

"kernelspec": {
      "name": "ir",
      "display_name": "R"
    },

に変更すれば使用できます。

本書で使用されているライブラリが一部含まれていないので、そちらだけ初めにインストールするコマンドを追加すれば、書いてあるとおりに使えるようになります。

install.packages("devtools", repos="https://cran.stat.unipd.it/")
devtools::install_github("sndmrc/BasketballAnalyzeR") 

自分が試しに使ってみたノートブックはこちら。

github.com

感想

書評という点では、思ってた以上に勉強になりました。(全文英語で読むのが大変なことを除けば、非常に良い本だと思います) ご興味ある方は、読んでみてはいかがでしょうか?

今回は本を読みながらコードを実装してましたが、今後やっていきたいところとしては、Statsに現れないデータを取れるようにすることが挙げられます。 具体的には、参考にした本では、Play by Playのデータが使用でき、そのデータも踏まえて分析が進められており、それらを使うともう一段深い分析になると感じました。

例えば3ポイントシュート一つとっても、右から打ったのか、左から打ったのか、正面なのか、コーナーなのかなど、どこから打ったのかを数値化できると非常に楽しいなとか思いました。 また、パスは誰から誰に通ったのか、その時の成功率はどれくらいか、マッチアップは誰だったか、守備はゾーンなのかマンツーなのかなど、人間は知っていて数字に出てこないパラメータが多く残っているので、それらを活用すると戦術などに適用できるのかもしれません。

この辺りは動画解析系の話もからんでくるので、大変そうです。 いつかその辺りまでできるようになったら、違った角度からデータを眺めてみたいと思います。