NCAA全米大学バスケの勝敗予測 ~ kaggleのデータコンペ
kaggleで面白そうなデータコンペやってる
予測モデルやデータ分析のコンペティションのkaggle。 今回はスポーツに関連したコンペで、大学バスケの勝敗(勝率)予測です。
NCAAってなんだろ?
バスケは全然詳しくないので、、NBAは知ってるけど、NCAAって聞いたこともなかった。 この辺の前提知識がないと、予測もできないと思うので、ちょっと調べてみた。
まず、NCAAとは、アメリカ大学体育協会(National Collegiate Athletic Association)のことで、バスケとか野球とか、アメフト、ホッケーなどなど、いろんな大学スポーツを運営しているらしいです。
つまり、NCAAバスケは全米大学バスケチームのNO.1を決める大会というわけですね。
出場校は、各地区レギュラーシーズンを勝ち上がった代表68チーム。トーナメントは3月途中から試合が始まり、アメリカ全土が熱狂するころから「マーチマッドネス」と呼ばれてるそうです。詳しくは、このあたりを→ WOGのNCAA講座!
kaggleからダウンロードするデータ
- 各チームのデータ(idと名前だけ)
- レギュラーシーズンの試合結果(得失点)
- トーナメントの試合結果(得失点)
- トーナメントの組み合わせ
以上のデータが18年分もらえます。
実際に予測するものは、各試合の勝敗。\( y_i \)は勝敗の結果、0 or 1。\(n\)はゲーム数。\( \hat{y}_i \)は勝率。基本的に全ての項にペナルティがついて、勝率を高く予想して勝ったときには小さいペナルティ、負けてしまったら大きなペナルティになります。 同じくらいの実力のときは、どちらが優勢か分からないので、勝率を0.5に設定して、傷を浅くするようなイメージ。 ペナルティの総和が小さいほど、正確な予測ということです。
\( \textrm{LogLoss} = - \frac{1}{n} \sum_{i=1}^n \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right] \)
チェスのレーティング
とりあえず、kaggleのベンチマークにチェスのレーティングモデルを使ったものがあったので、それを試してみます。
計算方法は、wikipediaをみていただいて。。 イロレーティング - Wikipedia
どこかでみたことある数式だと思ったら、映画「ソーシャルネットワーク」で、ザッカーバーグ達が「facemash」のアルゴリズムとして、窓に書いていましたね。
強いチームから勝つとレーティングが大きくあがり、弱いチームに負けるとレーティングが大きく下がります。
とりあえず、csvのデータをMySQLにぶち込んで、18年分の試合結果を基に、各校のレーティングを計算してみました。 上位校は、
順位 | 大学名 | レーティング |
---|---|---|
1st | Kentucky | 1772 |
2nd | North Carolina | 1769 |
3rd | Louisville | 1767 |
4th | Kansas | 1759 |
参考までに、2013年の優勝はLouisville、準優勝はMichigan。2012年は優勝がKentucky、準優勝がKansas。 ちなみに最下位の大学(578)が、Louisvilleと試合をすると勝率0.1%となってしまいます。 チェスのレーティングには「レート差が200以上あるときは、勝率を75%に固定する」というルールがありますが、レート差が開いてるときの勝率をうまいこと決めることができれば、いいスコアが出せそうです。
3月はスポーツバー行って、予測結果を見ながらワイワイ観戦します。
D3.jsでインタラクティブな感じにする
下の棒グラフは前回のコードに、各イベントを実装したものです。 グラフ表示の際のアニメーションと、マウスオーバーしたときの動作を、D3.jsのtransition()とイベントリスナーを使って簡単に追加することができます。
transition()
ドキュメントはこちら。
選択した要素のあとに.transition()を呼んで、アニメーション終了時の属性を指定しておくだけです(楽チン!)。 ちなみにアニメーション時間は、デフォルトで250msらしいので、適宜.duration()を使って調整します。
svg.selectAll("rect") .data(dataset) .transition().delay(1500).duration(2000) .attr("y", function(d) { return height-d*5 }) .attr("height", function(d) { return d*5 })
イベントリスナー
ドキュメントはこちら。
イベントリスナーも選択した要素に対して、.on()を呼び出すだけです。今回はマウスオーバーとマウスアウトのイベントに対するアクションを実装しています。 他にも、click、submitなどのイベントを取得できます。
.on("mouseover", function() { d3.select(this) .attr("fill", "rgb(39, 250, 102)") .attr("stroke", "green"); }) .on("mouseout", function(d) { d3.select(this) .attr("fill", "yellow") .attr("stroke", "orange") });
今回はてなブログに載せたコード↓↓↓
<script type="text/javascript", src="http://d3js.org/d3.v3.min.js"></script> <svg id="svgRect"></svg> <button id="transitionBtn">transition()</button> <script type="text/javascript"> var dataset = [ 5, 10, 15, 20, 25 ]; var width = 50; var height = 150; var svg = d3.select("#svgRect").attr("height", 200).attr("width", 800); svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("width", width) .attr("height", function(d) { return 0 }) .attr("x", function(d, i) { return i*(width+5)+5 }) .attr("y", function(d) { return height }) .attr("fill", "yellow") .attr("stroke", "orange") .attr("stroke-width", "3") .on("mouseover", function() { d3.select(this) .attr("fill", "rgb(39, 250, 102)") .attr("stroke", "green"); }) .on("mouseout", function(d) { d3.select(this) .attr("fill", "yellow") .attr("stroke", "orange") }); svg.selectAll("rect") .data(dataset) .transition().delay(1500).duration(2000) .attr("y", function(d) { return height-d*5 }) .attr("height", function(d) { return d*5 }) d3.select("#transitionBtn").on("click", function() { svg.selectAll("rect") .data(dataset) .attr("height", function(d) { return 0 }) .attr("y", function(d) { return height }) svg.selectAll("rect") .data(dataset) .transition().delay(0).duration(2000) .attr("y", function(d) { return height-d*5 }) .attr("height", function(d) { return d*5 }) }); </script>
D3.jsを始める前に ~SVGの基礎
D3.jsとデータビジュアライゼーション
「ビッグデータ」や「データサイエンティスト」といった言葉に続き、「データビジュアライゼーション」もキーワードとして注目されてきていますね。
データを視覚化するツールは本当にたくさんありますが、個人的に使いたいなーと思っているのが、D3.jsです。 D3.js
ブラウザで動くのでプラットフォームを選ばないし、ただの画像にはできないインタラクティブな表現がアツいです。思わず「すげー!」というようなサンプルコードがたくさんあるのですが、D3.jsを使うには、SVGの知識が必要です。D3.jsの日本語書籍が最近発売されましたが、HTMLやCSSの基本的な部分から解説してあるので、非エンジニアでも、最初から読み進めていけばD3.jsを使えるようになるのではと思います。↓↓↓
インタラクティブ・データビジュアライゼーション ―D3.jsによるデータの可視化
SVGとcanvas
SVGはScalable Vector Graphicsの略。HTML要素のひとつであり、ベクターグラフィックで図形を表現します。よくcanvasと比較されますが、違いを議論すると長くなるので以下のURLなどを参考に。 http://msdn.microsoft.com/ja-jp/library/ie/gg193983(v=vs.85).aspx
さて、ふたつの円を描いてみました。上の円がSVG、下の円がcanvasです。 画像を拡大してみるとベクター、ラスターの違いがよくわかるかと思います。
<svg width="50" height="50"> <circle cx="25" cy="25" r="22" fill="green" stroke="gray" stroke-width="2"/> </svg> <canvas id="canvasCircle" width="50" height="50"></canvas> <script type="text/javascript"> (function() { var canvas = document.getElementById("canvasCircle"); var c = canvas.getContext("2d"); c.beginPath(); c.arc(25, 25, 22, 0, 2 * 3.14, false); c.fillStyle = "green"; c.fill(); c.lineWidth = 2; c.strokeStyle = "gray"; c.stroke(); })() </script>
SVGの基礎
さて、「D3.jsによるデータの可視化」のSVGチュートリアルを試してみます。
rect
<svg width="500" height="50"> <rect x="0" y="0" width="300" height="50" fill="green"/> </svg>
circle
<svg width="500" height="50"> <circle cx="100" cy="25" r="25" fill="yellow"/> </svg>
ellipse
<svg width="500" height="50"> <ellipse cx="100" cy="25" rx="100" ry="25" fill="red"/> </svg>
line
<svg width="500" height="50"> <line x1="0" y1="0" x2="500" y2="50" stroke="gray"/> </svg>
text
<svg width="500" height="50"> <text x="150" y="25">はろーわーるど!!</text> </svg>
複雑なビジュアライゼーションにはまだまだ遠いですが、長方形や円を描くことができます。 以下のようにjavascriptで図形の生成、変形を行うこともできます。↓↓↓
とはいえ、棒グラフを描くだけならExcelで十分ですね。 D3.jsの使いどころとしては、凝ったデザインにしたいとか、インタラクティブなグラフを作りたいとき。 また、APIたたいてjsonデータとか、DBから取得したデータなど、Webとの親和性が高い状況での相性が良さそうですね。
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> <svg id="d3js"></svg> <script type="text/javascript"> var dataset = [ 5, 10, 15, 20, 25 ]; var width = 50; var height = 150; var svg = d3.select("#d3js"); svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("width", width) .attr("height", function(d) { return d*5 }) .attr("x", function(d, i) { return i*(width+5)+5 }) .attr("y", function(d) { return height-d*5 }) .attr("fill", "yellow") .attr("stroke", "orange") .attr("stroke-width", "3"); </script>