2013/10/19
データいろいろ
 >  好き嫌いを Wilson Score Interval で順位付け
昨日、Hacker News という海外のウェブサイトで行われているプログラミング言語の好き嫌い投票の結果を紹介した。この投票はかなり前から実施されている模様で、昨年に下の記事が出ている。当時の投票結果から各言語の点数を算出し、高い順に並べ替えたもの。その際に Wilson Score Interval という統計学上の指標を使っている。

Hacker News : Programming Languages sorted by Wilson Score Interval
https://news.ycombinator.com/item?id=3752509


日本語のウェブでは Wilson Score Interval に特化した情報はないようだが、二項割合の信頼区間(二項分布にもとづく母比率の信頼区間)の一種。Wikipedia 英語版に簡単な説明と算出式がある。他にも様々な計算方法による信頼区間があるが、今日は Hacker News にならって Wilson Score Interval だけを取り上げる。

Wikipedia : Binomial proportion confidence interval
http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval


実用面では下記ウェブが分かりやすい。好き嫌い投票など Rating の順位づけにあたり Wilson Score Interval が有益だとしている。Rating では対象ごとに投票数(統計学でいえばサンプルサイズ)が違うので、単純に「好き」票数と「嫌い」票数の差や、「好き」票数割合で順位づけるのは間違っていると。駄目な例として Amazon も挙げられている。

Evanmiller.org : How Not To Sort By Average Rating
http://www.evanmiller.org/how-not-to-sort-by-average-rating.html


冒頭に紹介した Hacker News の記事だが、実は算出結果が間違っている。下の Pascal を見て、好き嫌いが同数なのに 0.696 という値がついているのは何か変だと思った。で参照先のウェブページを見たら、算出プログラムが間違っていたのである。


Hacking and Gonzo : How Reddit ranking algorithms work
http://amix.dk/blog/post/19588


上のとおり、プログラムで平方根 sqrt の位置が間違っている。なお数式が Wikipedia と若干異なるが計算内容は同じ。試しに PostgreSQL でこのプログラムどおり計算してみたら Hacker News と同じ値になった。下が SQL のコード。
WITH a (pname, n_like, n_dislike) AS (
VALUES (text 'Python', 2881, 115) -- 以下サンプルデータ
, ('SQL', 92, 70)
, ('Pascal', 24, 24)
, ('C++', 503, 540)
), b AS (
SELECT *, n_like + n_dislike AS n -- 好き+嫌い
FROM a
), c AS (
SELECT *, n_like :: float / n AS p -- 好き割合
FROM b
), d AS (
SELECT *, pow(z, 2) AS z2 -- z 二乗(後で三回使う)
FROM (
VALUES (1 :: float) -- -- z 値 85% => 1.0, 95% => 1.6
) foo (z)
)
SELECT pname, n_like, n_dislike
, to_char(p, 'FM0.000') AS p_like

, to_char(sqrt(p + z2 / (2 * n)
- z * (p * (1 - p) + z2 / (4 * pow(n, 2))) / n)
/ (1 + z2 / n)
, 'FM0.000') AS score_err -- 間違いを再現

, (p + z2 / (2 * n)
- z * sqrt(p * (1 - p) / n + z2 / (4 * pow(n, 2))))
/ (1 + z2 / n) AS score_rev -- 修正後
FROM c, d ;

下が実行結果。score_err が Hacker News の値(間違ったプログラムの再現)、score_rev が修正版。Pascal と C++ の順位が入れ替わった。


そもそも Wilson Score Interval を使うのは、サンプルサイズが小さい場合の不確実さを考慮に入れて「好きという割合が、少なくともこの程度はあると言えそうな値」を出して順位づけるため。少ない投票数で好き嫌い同数の Pascal より、投票数が多くて好きよりわずかに嫌いが多い C++ の方が上になるのが正しい。Hacker News が使った間違ったプログラムは、値がおかしいだけでなく Wilson Score Interval を使う意味もなかったような…。

元々の Wilson Score Interval の算出式には ± の項があるが、今回のように Rating の順位付けに使う場合、上で述べた「好きという割合が、少なくともこの程度はあると言えそうな値」を使う趣旨からして、マイナスだけ計算すればよさそう。中ほどで紹介した Evanmiller.org もそうしている。

なお Hacker News が元にしたプログラムでは Z 値を正規分布の片側確率85%から与えているが、Evanmiller.org では両側確率を使っている。次回、確率を片側か両側か、また何%にするかも可変で点数を算出するストアド関数を作る予定。
<< Wilson Score Interval で順位付け…
プログラミング言語の好き嫌い(Hac… >>