Hacker News のランキングは実際どう決まるか:スコア、論争、ペナルティ
著者は数日間 HN の上位 60 記事を追跡して逆解析した。公開式はほぼ正確だが、フロントページの 20% はペナルティを受け、タイトルに NSA があると 0.4 倍、コメントが票より多く 40 件に達すると「論争」判定で一瞬で消える。
日本語
コピー

Hacker News のランキングの基本式は何年も前から知られているが、疑問は残っていた。公開されているコードは本当のアルゴリズムなのか。ランキングは純粋に投票だけで決まるのか、見えない要素が働いているのか。NSA に関する記事は順位を下げられるのか。あの人気記事が、あなたがコメントした直後になぜフロントページから消えたのか。
数日間、HN の上位 60 記事を注意深く分析することで、これらの疑問とそれ以上に答えられる。公開されている式はほぼ正確だ。ランキングの調整は想像以上に多く、フロントページの記事の 20% が何らかの形でペナルティを受けている。 タイトルに「NSA」を含むものはペナルティを受け、急速に落ちていく。「論争的」な記事はコメントが 40 件に達した後、厳しくペナルティを受ける。本稿ではスコアリングとペナルティを詳しく述べる。(編集注:HN は後に NSA 記事へのペナルティを廃止した。詳細。)
記事は、得票数、投稿からの経過時間、および各種ペナルティに基づいて採点される。式は次のとおりだ。
score = (votes - 1)^0.8 / (age_hours + 2)^1.8 × penalties
時間の指数が票の指数より大きいため、記事のスコアはいずれゼロまで下がる。だから何もフロントページに長く留まれない。この指数は重力(gravity)と呼ばれる。
Hacker News を訪れるたびに、すべての記事が上式で採点され並べ替えられていると思うかもしれない。しかし効率のため、個々の記事が再ランクされるのは時々だけだ。記事が投票されると、その記事だけが再ランクされ、リスト内の適切な位置へ移動する。他の記事は変わらない。こうして再ランクの量は大幅に減る。ただし、投票が止まった記事が高い位置に居座る可能性が出てくる。これを避けるため、30 秒ごとに上位 50 記事のうち 1 つがランダムに選ばれて再ランクされる。結果として、票が伸びない記事は何分もの間「誤った」順位に置かれうる。さらに、ページは 90 秒間キャッシュされ得る。
生スコアと、よくある日の 1 位
次の図は、11 月 11 日一日を通した HN 上位 60 記事の生スコア(ペナルティを除く)を示す。各線が 1 記事に対応し、ページ上の位置に応じて色分けされている。赤い線が HN のトップ記事だ。ペナルティのため、生スコアが最高の記事がトップ記事でないことも多いことに注意してほしい。

このグラフはいくつか興味深いことを示している。記事のスコアは急速に跳ね上がり、その後何時間もかけてゆっくり下がる。採点式がその多くを説明する。一定の票を得続ける記事はすぐにピークに達し、その後なだらかに下降する。だが実際に観測されるピークはもっと速い。記事は最初の 1〜2 時間に多くの票を集め、その後は投票率が落ちるからだ。この二つが合わさって、図のような急峻な曲線になる。
毎日、他よりずば抜けて高いスコアの記事がいくつかあり、同時に中位の記事が大量にある。スコアは良いのに運が悪く、より人気の記事の後ろに詰まるものもある。ある記事の下落と別の記事の上昇の隙間で、一瞬だけ 1 位を取るものもある。
生スコアが最高の記事(グラフの上端)と、実際に最高位の記事(赤線)の差を見れば、ペナルティがいつ適用されたか分かる。『ウェブサイト登録を完全に間違える』は早朝に 1 位になったが、論争ペナルティを受けて急速にページを落ち、『Linux が私の RAM を食べた』が一瞬 1 位を取り、続いて『CSS でシンプソンズ』が追い抜いた。少し後、Apple Mapsは 1 位に達した直後に論争ペナルティを受け、1 位を失って急速に順位を落とした。Snapchat の記事は HN のトップに達したが、午前 8:22 に非常に重いペナルティを受け、チャートから完全に消えた。『MongoDB を決して使うべきでない理由』は非常に人気で、一日の大半を 1 位で過ごすはずだったが、急速にペナルティを受け、7 位付近で足踏みした。『NSA との関係を断つ』は最初から NSA ペナルティを受けたが、あまりに人気だったためそれでも 1 位を取った。しかしすぐにさらに大きなペナルティを与えられ、ページ下方へ押しやられた。最後に、一日の終わり近くに『410 万ドルが消える』がペナルティを受けた。実際には、ペナルティがなくてもまもなく FTL に 1 位を譲っていただろう。
緑の三角とテキストは「論争」ペナルティが適用された箇所を示す。青の三角とテキストは、記事が忘却の彼方へペナルティを受け、上位 60 から落ちた箇所を示す。より軽いペナルティはここには示していない。
HN の 1 位の内容が「自然」なものではなく、多くの記事への絶え間ないペナルティ適用の結果であることは明らかだ。これらのペナルティが HN の管理者によるものか、記事が flag された結果なのかは不明である。
自動的にペナルティを受ける投稿
タイトルに基づいて自動的にペナルティを受ける投稿もあれば、ドメインに基づくものもある。タイトルに NSA を含む記事は自動的に 0.4 のペナルティを受けるようだ。awesome、bitcoin、bubble など、自動ペナルティを引き起こす他の語も探したが、ペナルティを受けているようには見えなかった。多くのウェブサイトが 0.25〜0.8 のペナルティを自動的に受けているらしいと観察した。arstechnica.com、businessinsider.com、easypost.com、github.com、imgur.com、medium.com、quora.com、qz.com、reddit.com、rt.com、stackexchange.com、theguardian.com、theregister.com、theverge.com、torrentfreak.com、youtube.com。実際のリストはもっと長いに違いない。(これは「ban」されたサイトとは別で、かつて一覧が公開されていた。)
eterm による興味深い説は、人気サイトのニュースは複数の人に並行して投稿され、記事が「値する」以上の票を得る、というものだ。人気ウェブサイトに自動ペナルティを与えることは、この効果を打ち消すのに役立つ。
ペナルティの影響
採点式を使えば、ペナルティの影響を計算できる。記事のペナルティ係数が 0.4 なら、各票が 0.3 票としてしか数えられないのと等価だ。別の言い方をすれば、順位の下落速度が通常より 66% 速い。係数 0.1 は各票が 0.05 票に相当し、通常の 3.6 倍の速さで落ちる。つまり 0.4 でも大きな影響があり、0.1 は非常に厳しい。
論争。 Hacker News での罵り合いを防ぐため、コメントが「多すぎる」記事は「論争的」として厳しくペナルティを受ける。公開コードでは、contro-factor 関数はコメントが 20 件を超え、かつコメントが得票より多い投稿に対して働き、そうした記事は (votes/comments)^2 でスケールされる。だが実際の式は異なり、コメントが得票より多く、かつコメントが少なくとも 40 件ある投稿で有効になる。経験的データから、指数は 2 ではなく 3 ではないかと疑っているが、証明はしていない。論争ペナルティは記事の順位に突然かつ壊滅的な影響を与え得る。ある分には上位だった記事が、コメント 40 件に達した瞬間に消えるのだ。人気記事が突然フロントページから消えた理由に心当たりがないなら、論争が原因の可能性が高い。例えば『Chromebook の論者たちが現実から乖離している理由』はコメント 40 件に達した瞬間に 5 位から 22 位へ落ち、Show HN:どの医者からでも自分の健康記録を取得は 17 位にいたが 40 件到達で上位 60 から完全に消えた。
私の方法
私は /news と /news2 のページを毎分 1 回クロールした(毎分 2 ページというガイドラインを守っている)。やや見苦しい HTML を Beautiful Soup で解析し、大量の Python スクリプトで処理し、難解だが強力な matplotlib でグラフ化した。分析の基本は、式で生スコアを計算し、そこから異常を探すことだ。ある時点(例:11/09 8:46)で、上位 10 記事の生スコアを計算できる。
2.802 Pyret: A new programming language from the creators of Racket
1.407 The Big Data Brain Drain: Why Science is in Trouble
1.649 The NY Times endorsed a secretive trade agreement that the public can't read
0.785 S.F. programmers build alternative to HealthCare.gov (warning: autoplay video)
0.844 Marelle: logic programming for devops
0.738 Sprite Lamp
0.714 Why Teenagers Are Fleeing Facebook
0.659 NodeKnockout is in Full Tilt. Checkout some demos
0.805 ISO 1
0.483 Shopify accepts Bitcoin.
0.452 Show HN: Understand closures
上位 10 のうち 3 つ(The NY Times、Marelle、ISO 1)はスコアから期待される順位より低いことに注目してほしい。The NY Times は 1.407 と 0.785 の記事の間にランクされているので、そのペナルティ係数は 0.47〜0.85 と計算できる。同様に他の二つは 0.87〜0.93 と 0.60〜0.82 でなければならない。ほとんどの記事はスコアどおりにランクされ、例外は一貫してかなり低くランクされており、これがペナルティの存在を示す。これは使用中の採点式が公開コードと一致することを意味する。もし式が違っていたら——例えば重力指数がもっと大きければ——票や時間の増加に伴って記事が「期待される」順位からずれていくはずだが、それは一度も観測されなかった。
この手法はペナルティの存在を示し、その範囲を与えるが、正確な値を決めるのは難しい。範囲の時間変化を見て単一の値に収束することを期待することになる。しかし誤差の源がいくつかある。第一に、隣の記事にもペナルティがかかっている、あるいは採点方式が違う(求人投稿など)可能性。第二に、記事は常に再ランクされるわけではないので、一時的に位置がずれることがある。第三に、ペナルティが時間とともに変わり得る。第四に、「悪い」票は抑制されるため、表示される票数が実際と異なることがある。結果として、おおよそのペナルティは求められたが、数値の不安定さはかなり大きい。
一日のペナルティ
次のグラフは、一日の間に算出されたペナルティを示す。各線がある記事を表し、1(ペナルティなし)から始まり、ペナルティが適用されるとその水準まで下がる。線は記事が上位 60 から落ちたところで終わるが、それはペナルティ適用から間もないことも多い。0.2 と 0.4 のペナルティ、そして 0.8〜0.9 の範囲に多くが分布しているように見える。午前 9 時(モデレーターが出勤する時間?)に多くのペナルティが適用され、その後も一日を通じて続くようだ。このグラフはかなりノイズが多いので、改善するために異なるアルゴリズムを試している。

平均して、フロントページの記事の約 20% がペナルティを受けており、2 ページ目の記事では 38% がペナルティを受けている。(フロントページの比率が低いのは、ペナルティを受けた記事は定義上フロントページに残りにくいからだ。)ペナルティは想像以上に多く行われている。
以下は 11/11 にフロントページに載り、ペナルティを受けていた記事の一覧だ。(ペナルティがなければ載っていたはずの記事は含まない。)この一覧は予想よりずっと長い。全リストはスクロールして確認してほしい。
Why the Climate Corporation Sold Itself to Monsanto、Facebook Publications、Bill Gates: What I Learned in the Fight Against Polio、McCain says NSA chief Keith Alexander 'should resign or be fired'、You are not a software engineer、What is a y-combinator?、Typhoon Haiyan kills 10,000 in Philippines、To Persuade People, Tell Them a Story、Tetris and The Power Of CSS、Microsoft Research Publications、Moscow subway sells free tickets for 30 sit-ups、The secret world of cargo ships、These weeks in Rust、Empty-Stomach Intelligence、Getting website registration completely wrong、The Six Most Common Species Of Code、Amazon to Begin Sunday Deliveries, With Post Office's Help、Linux ate my RAM、Simpsons in CSS、Apple maps: how Google lost when everyone thought it had won、Docker and Go: why did we decide to write Docker in Go?、Amazon Code Ninjas、Last Doolittle Raiders make final toast、Linux Voice - A new Linux magazine that gives back、Want to download anime? Just made a program for that、Commit 15 minutes to explain to a stranger why you love your job.、Why You Should Never Use MongoDB、Show HN: SketchDeck - build slides faster、Zero to Peanut Butter Docker Time in 78 Seconds、NSA's Surveillance Powers Extend Far Beyond Counterterrorism、How Sentry's Open Source Service Was Born、Real World OCaml、Show HN: Get your health records from any doctor、Why the Chromebook pundits are out of touch with reality、Towards a More Modular Future for JavaScript Libraries、Why is virt-builder written in OCaml?、IOS: End of an Era、The craziest things you can plug into your iPhone's audio jack、RFC: Replace Java with Go in default languages、Show HN: Find your health plan on Health Sherpa、Web Latency Benchmark: A new kind of browser benchmark、Why are Amazon, Facebook and Yahoo copying Microsoft's stack ranking system?、Severing Ties with the NSA、Doctor performs surgery using Google Glass、Duplicity + S3: Easy, cheap, encrypted, automated full-disk backups、Bitcoin's UK future looks bleak、Amazon Redshift's New Features、You're only getting the nice feedback、Software is Easy, Hardware is of Medium Difficulty、Facebook Warns Users After Adobe Breach、International Space Station Infected With USB Stick Malware、Tidbit: Client-Side Bitcoin Mining、Go: "I have already used the name for MY programming language"、Multi-Modal Drone: Fly, Swim & Drive、The Daily Go Programming Newspaper、"We have no food, we need water and other things to survive."、Introducing the Humble Store、The Six Most Common Species Of Code、$4.1m goes missing as Chinese bitcoin trading platform GBL vanishes、Could Bitcoin Be More Disruptive than the Internet?、Apple Store is updating。
採点式のコード
あるバージョンの HN サーバーの Arc ソースは入手可能で、更新された採点式もある。
(= gravity* 1.8 timebase* 120 front-threshold* 1
nourl-factor* .4 lightweight-factor* .17 gag-factor* .1)
(def frontpage-rank (s (o scorefn realscore) (o gravity gravity*))
(* (/ (let base (- (scorefn s) 1)
(if (> base 0) (expt base .8) base))
(expt (/ (+ (item-age s) timebase*) 60) gravity))
(if (no (in s!type 'story 'poll)) .8
(blank s!url) nourl-factor*
(mem 'bury s!keys) .001
(* (contro-factor s)
(if (mem 'gag s!keys)
gag-factor*
(lightweight s)
lightweight-factor*
1)))))
Arc を読まない人のために言えば、上の断片はいくつかの定数を定義している——gravity* = 1.8、timebase* = 120(分)など。次にメソッド frontpage-rank を定義し、記事 s をその得票(realscore)と分単位の経過時間(item-age)に基づいてランクする。ペナルティ係数は複数分岐の if で定義される。記事が 'story' でも 'poll' でもなければ係数は 0.8。そうでなく URL フィールドが空(Ask HN など)なら nourl-factor*。'bury' とフラグされた記事はスケール係数 0.001 で、忘却の彼方へランクされる。最後に既定の分岐が論争係数と gag/lightweight 係数を組み合わせる。論争係数 contro-factor は炎上を招く投稿を抑えるためのもので、後で詳しく述べる。
次の係数は gag(冗談)とフラグされた記事に 0.1 という重い値を与え、「軽量」な記事には 0.17 の係数を与える。実際のペナルティ体系は、公開コードに現れるものよりはるかに複雑なようだ。
結論
Hacker News のホームページ上の記事の位置は、あなたが想像するような得票に基づく実力主義ではない。Hacker News のページに現れる記事を注意深く調べることで、使用中の採点式について多くを学べる。票が順位を左右する明白な要素である一方、記事の順位を下げたり完全に消したりする複雑な「ペナルティ」体系も存在する。これはスパム対策にとどまらず、非常に人気のある記事にも影響する。そして、記事のコメント数が票数より多いなら、コメントを付けないほうがいい——記事を完全に殺してしまうかもしれない! 詳しくは Hacker News の議論を参照。
更新(11/18):ペナルティについての記事がペナルティを受けた
皮肉なことに、この記事は Hacker News でペナルティを受けた。フロントページに達してから数分後、0.2 という重いペナルティが適用され、フロントページから押し出された。下のグラフの黒線は、この記事の Hacker News 上での位置を示す。ペナルティが適用されたときの急落が見える。灰色の線は、ペナルティがなければどこにランクされていたかを示す。ペナルティがなければ 5 位に入っていたはずだが、ペナルティのためフロントページ(1〜30 位)に戻ることはなかった。下の緑の線はこの記事の生スコアだ。(11/26:ペナルティは「投票リング検出」の誤作動によるものだと聞いた。)
