レコメンデーションといえば、現在最も多く使われている技術の一つと言えるでしょう。その応用は数多く存在し、身近なところで言えば、Amazonによる関連商品の推薦やNetflixによる映画の推薦などに使われており、私たちの意思決定を支援しています。
一口にレコメンデーションといってもそのやり方は様々です。古くは行列分解を用いた手法から最近では機械学習、特にディープラーニングを用いた手法が多数提案されています。今回はその中でも手動で設計したスコア関数を使った手法についてHacker Newsを例に紹介します。大きくは以下の3つを紹介します。
- 人気度に基づく手法
- 新規性に基づく手法
- ハイブリッドな手法
人気度に基づく手法
人気度(Popularity)に基づく手法というのは「他の人が好きなコンテンツなら、あなたも好きに違いない」という考えに基づいて推薦を行う手法です。たとえば、Netflixのようにユーザに映画を推薦する状況について考えてみましょう。世界的な映画データベースであるIMDbによると、2019年現在、最も評価が高い映画は「ショーシャンクの空に」、「ゴッドファーザー」「ゴッドファーザー2」の順番になっています。したがって、人気度に基づく手法ではこれらの映画をユーザに推薦します。
人気度に基づく手法を実装するのは難しくありません。もし、SQLを書いて実現するなら、以下のように書くことでユーザに推薦する候補を得られるでしょう。
SELECT movie_id FROM movies ORDER BY rating DESC;
人気度に基づく手法はシンプルですが問題点もあります。たとえば、私たちがイタリアに旅行した際にレストランを探しているとします。そのとき、人気度に基づく手法ではマクドナルドが推薦される可能性があります。私はマクドナルドのチーズバーガが好きなのですが、イタリアに来ているならピザやパスタを食べたいですし、そもそも誰もが知っているマクドナルドを推薦する必要があるのかは疑問です。
その他にも人気度に基づく手法では自分の好みに合わない候補が推薦されることがあります。たとえば、音楽を推薦する際にオリコンの週間ランキングから推薦した場合、少なくとも私の好みには全くあっていません。
また、Hacker Newsのようにニュースの推薦を行う場合にはコンテンツの新しさを考慮する必要があります。というのも、いくら人気の記事でもユーザは3年前の記事を読みたくはないだろうと考えられるからです。そういうわけで次に紹介するのが新規性に基づく手法です。
新規性に基づく手法
新規性(Recency)に基づく手法では、作成あるいは更新日時が新しいコンテンツをユーザに推薦します。たとえば、ニュースのように時事性の高いコンテンツを推薦したりする際には新規性を考慮します。技術者にとって身近なところでは、Hacker Newsのnewestは新規性に基づく推薦と言えるでしょう。
新規性に基づく手法を実装するのは難しくありません。もし、SQLを書いて実現するなら、以下のように書くことでユーザに推薦する候補を得られるでしょう。
SELECT news_id FROM news ORDER BY created_at DESC;
新規性に基づく手法はシンプルですが問題点もあります。たとえば、有用でない記事が新しいというだけの理由で推薦されてしまいます。こうなると、スパムによってそのランキングは支配されてしまうでしょう。また、新規性に基づいて記事を推薦する場合、自分の全く興味のない分野の記事が推薦されることがあるでしょう。この問題に対して、プログラミングの知識を共有できるサイトQiitaではユーザが自分の興味のある分野のタグをフォローすることで、推薦される記事を絞り込んでいます。
このように、人気度と新規性を単体で使うといくつかの問題が出てきてしまいます。そういうわけで、実際にはこれらの手法をハイブリッドして使うことを考えます。なお、個人化の問題については扱うと長くなるので、次の機会にしておきます。
ハイブリッドな手法
ハイブリッドな手法では、Hacker Newsで使っているアルゴリズムを紹介しましょう。その前に人気度と新規性に基づく手法の問題を整理しておきます。人気度に基づく手法ではコンテンツの新しさは考慮されませんでした。そのため、ニュースの推薦で3年前の記事を紹介してしまう可能性があります。一方、新規性に基づく手法では有用でない記事が新しいというだけの理由で推薦される可能性があります。
ハイブリッドな手法の基本的な考え方としては人気度と新規性をバランスさせるようにスコア関数を設計します。概念的には、のような形でスコア関数を設計します。こうすることで、「いいね!」がたくさんついているような人気度が高い記事は分子の値を大きくして全体的なスコアを高く、一方で発信されてから時間が経った記事は分母の値を大きくして全体的なスコアを小さくすることができます。
Hacker Newsを例にスコア関数について見てみましょう。Hacker Newsのアルゴリズムを解説した記事によると、Hacker Newsでは以下の式を使って記事にスコア付を行っています。
分子が人気度、分母が新規性を表しています。upsはupvoteの数、downsはdown voteの数、ageは投稿されてからの時間を表していると考えてください。
まず、注目すべきは分子の指数が分母より小さい点(0.8 < 1.8)です。これはつまり分母は分子より早く大きくなるということを示しています。こうすることで、どれだけupvoteが多くてもageは常にその成長を追い越すので、結果として新しい記事が上に来るような設計になっています。以下に示すように、スコア関数の形としては、最初に急激に上がって、ゆっくりと下がっていく形になっています。分母は最初の方はあまり効いていないのですが、時間が経つにつれ効いてくることを示しています。
また、分子の指数が0.8である点にも工夫が見られます。指数を0.8とすることで分子の形は以下の図に示すようにsublinearの形になります。こうすることで、最初に獲得した100のupvoteは1000獲得した後の100upvoteより価値があるという考え方を入れられます。
このように設計している理由としては、少数の記事がupvoteのほとんどを獲得し、大多数の記事はupvote数が少ないことに関係していると思われます。Linearに設計すると、1000vote得た記事に100voteの記事は勝負になりませんが、sublinearなら土俵に乗ることはできます。
最後に、penalty 項ではビジネスロジックを入れる事ができます。たとえば、画像だけの記事やリンク集のような記事はスコアが低くなるようにpenalty項を設計することができます。応用としては、たとえば自社でニュースのレコメンデーションシステムを作る際、penalty項をいじって自社に関係する記事に高いスコアを与えるといったことが考えられます。
おわりに
今回は手動で設計したスコア関数によるレコメンデーションの方法についてHacker Newsを例に紹介しました。これらの手法は学習が必要ないというメリットがありますが、その一方で推薦内容の個人化がされていないという欠点もあります。次回は行列分解による手法を例に個人化の方法について紹介したいと思います。