LightFMで はてなブックマーク のレコメンドモデルを作ってみた話
おすすめブクマ(仮) というサイトを運営している id:bukumame です。日頃からブコメ検索をご利用いただきありがとうございます。
本来のおすすめ機能よりも検索機能のほうが利用されている当サイトですが、今日はブコメ検索ではなくトップページのおすすめ機能の改善に関する調査報告をご紹介をいたします。
既存のおすすめ機能の問題点について
既存のおすすめは単純な協調フィルタリングを少し改変したロジックでできていますが、その問題点は主に2点あります:
- 性能がイマイチ
- 頻繁なモデル更新が難しい
性能がイマイチなのは、協調フィルタリングでユーザー同士の類似度を計算して、一定以上の類似度を持つユーザーのブックマークを推薦しているだけなのが原因です。
モデル更新についても原因はだいたい同じで、単純な協調フィルタリングで類似度を計算しているため、部分的なデータでの再計算が難しくなっています。またメモリベースな手法であるため、データ量が多くなるにつれてメモリ使用量も増えていってしまうという問題もあります。
こういった問題点を解決するため、もっと精度の良い、追加学習が可能で軽量なレコメンド手法を調べてみたところ、LightFMというライブラリが使いやすそうであったため試してみることにしました。
LightFMとは
LightFMはMatrix Factorization(MF)をベースとする手法で、そこにユーザーおよびアイテムの特徴量を加味できるようにしたのが通常のMFと異なる点です。LightFMという名称は作者がFM(Factorization Machines)にヒントを得て開発されたことが由来であり、実際の中身はMFのほうが近いです。
また、追加学習については fit_partial メソッドを使うことで追加データでの学習が部分的に可能になります。
以下でははてなブックマークのデータを用いて協調フィルタリング(CF)とLightFMでモデルを作成して、その性能を比較してみた結果をご紹介します。
テスト条件
- 現行モデルはピアソン相関係数によるモデル構築
- 新モデルはLightFM
- ユーザーの評価値データはブックマークデータ
- データの期間は3ヶ月分(180万件くらい)
- アイテム属性は記事のカテゴリとドメイン
- ユーザー属性は無し
細かいテスト条件は他にもありますが、CFとLightFMの双方がなるべく同様の条件になるように調整しました。
テスト結果と考察
Precision@KとRecall@Kを計測したところ、以下のようにLightFMの圧勝となりました:
Precision@7 | Recall@7 | Precision@50 | Recall@50 | |
---|---|---|---|---|
CF | 0.200 | 0.065 | 0.155 | 0.071 |
LightFM | 0.332 | 0.135 | 0.355 | 0.161 |
※Kの値で分けて計測した理由は、評価値データが少ないユーザーはそもそもK=50の結果を十分に評価できないからです。K=7のほうは評価値データが少ないユーザーも含んでおり、K=50はヘビーユーザーのみを対象にした計測結果になっています。
precisionもrecallもLightFMが1.6倍~2倍程度の差をつけており、特にPrecisionが0.3を超えているためUXはCFモデルと比べてかなり向上すると思われます。
ちなみに上記のテストではアイテム特徴量を追加していますが、追加しなかった場合と結果に大差がなかったため、今回追加したアイテム特徴量はモデル性能に寄与していない可能性が高いです。
LightFMでアイテム/ユーザー特徴量を追加しなかった場合はMFと同等の処理になりますが、MFモデル自体がユーザー/アイテムの特徴を潜在ベクトルとして表現できる*1ため、記事のドメインとカテゴリくらいの情報であればわざわざ追加せずとも潜在ベクトル内で表現できるものなのかもしれません。もしくは特徴量の質が低かったか。
処理の負荷について
モデル構築にかかる時間およびメモリ使用量は以下のようになりました。
なお、使用したマシンの性能は以下です:
計算時間(秒) | メモリ使用量(GB) | |
---|---|---|
CF | 40 | 3.11 |
LightFM | 547 | 0.77 |
LightFMのほうが構築に時間がかかりますが、一方でメモリ使用量はCFに比べて少なく抑えられており、LightFMならより多くのデータでモデルを構築することもできそうです。
LightFM以外のレコメンドライブラリについて
世の中には他にも多数のレコメンド用ライブラリがあり、一通り試したのでその感想を簡単に書き連ねておきます。
RankFM
- とりあえず動いたがあまり成績が良くなかった。ハイパーパラメータの調整で改善する?
xlearn
- サンプルは動いたが、implicit feedbackに対応しているのかどうか不明だったため採用は見送り
fastFM
- 使い方がちょっとよく分からなくて途中で使うのを止めた
implicit
- precision@K が常に1になる。使い方を間違えている?
- ライブラリの名前のせいで searchability が低くて辛い
recommenders
- ライブラリというよりかはいろんなライブラリの使い方集みたいな感じ?
- cornacのサンプルを使ってみたがやたらとメモリを食った。内部でSparkを使ってるから?
おまけ:検索機能の改善について
検索機能にはElasticsearchを使っているのですがこいつがけっこう負荷が高いため、新しい機能を追加するにはもっとよいマシンに切り替える必要があります。もちろんESのチューニングはしてありますがそれでも負荷は高めです。
実装・改善したい機能はたくさんあるのですが、収益化しているわけでもないのであまり期待しないでください。