忘れないようにメモっとく

機械学習とかプログラミングとか。

NCAA全米大学バスケの勝敗予測 ~ kaggleのデータコンペ

kaggleで面白そうなデータコンペやってる

予測モデルやデータ分析のコンペティションのkaggle。 今回はスポーツに関連したコンペで、大学バスケの勝敗(勝率)予測です。

https://kaggle2.blob.core.windows.net/competitions/kaggle/3812/media/Kaggle_web_banner_FINAL.png

NCAAってなんだろ?

バスケは全然詳しくないので、、NBAは知ってるけど、NCAAって聞いたこともなかった。 この辺の前提知識がないと、予測もできないと思うので、ちょっと調べてみた。

まず、NCAAとは、アメリカ大学体育協会(National Collegiate Athletic Association)のことで、バスケとか野球とか、アメフト、ホッケーなどなど、いろんな大学スポーツを運営しているらしいです。

つまり、NCAAバスケは全米大学バスケチームのNO.1を決める大会というわけですね。

出場校は、各地区レギュラーシーズンを勝ち上がった代表68チーム。トーナメントは3月途中から試合が始まり、アメリカ全土が熱狂するころから「マーチマッドネス」と呼ばれてるそうです。詳しくは、このあたりを→ WOGのNCAA講座!

kaggleからダウンロードするデータ

  1. 各チームのデータ(idと名前だけ)
  2. レギュラーシーズンの試合結果(得失点)
  3. トーナメントの試合結果(得失点)
  4. トーナメントの組み合わせ

以上のデータが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」のアルゴリズムとして、窓に書いていましたね。

http://3.bp.blogspot.com/_ie_tvDj66rE/TUni7aVaIOI/AAAAAAAADoM/34Uz8ymAzzQ/s1600/2010_the_social_network_063%2B%2528Medium%2529.jpg

強いチームから勝つとレーティングが大きくあがり、弱いチームに負けるとレーティングが大きく下がります。

とりあえず、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によるデータの可視化


SVGcanvas

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>