レコメンドシステムを初心者が勉強してみた

# 記事の概要

- 記事投稿の理由
    - 今度、レコメンドシステムの改善をするためのプロジェクトに入ることになったため、レコメンドシステムの勉強を始めた。
    - **レコメンドシステムがわかりづらい。なぜなら、レコメンドアルゴリズムを整理するための軸が入り乱れており、その包含関係や分類がわかりづらかった。**
- 記事の目的
    - レコメンドシステム（アルゴリズム）を初心者が学習しその備忘録として記録するもの。
    - レコメンドシステムを極力かみ砕いて投稿する。
- 記事の今後
    - 今回：レコメンドシステムの概要を記述する。
    - 今後：レコメンドシステムの具体的なアルゴリズムやPythonコードを説明する。
- 参考サイト
    - この一連の記事は、以下の3つを参考に書いたもの。
        - ①：[神嶌先生のPDF](https://www.kamishima.net/archive/recsys.pdf)
        - ②：[Googleのレコメンドシステムのコンテンツ](https://developers.google.com/machine-learning/recommendation?hl=ja)
        - ③：[推薦システム実践入門](https://www.amazon.co.jp/%E6%8E%A8%E8%96%A6%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E2%80%95%E4%BB%95%E4%BA%8B%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%E5%B0%8E%E5%85%A5%E3%82%AC%E3%82%A4%E3%83%89-%E9%A2%A8%E9%96%93-%E6%AD%A3%E5%BC%98/dp/4873119669/ref=sr_1_3?adgrpid=143939553572&hvadid=679064847503&hvdev=c&hvqmt=e&hvtargid=kwd-1722180453068&hydadcr=16038_13711641&jp-ad-ap=0&keywords=%E6%8E%A8%E8%96%A6%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E5%85%A5%E9%96%80&qid=1703651498&sr=8-3)

# レコメンドシステムの概要

## レコメンドシステムの定義
「複数の候補から価値のあるものを選び出し、意思決定を支援するシステム」と定義される。

前半の「複数の候補から価値のあるものを選び出し」は『価値のあるもの』の定義の仕方によって**アルゴリズムが多数提案されている**。単純に閲覧回数の多いアイテムトップ10を選ぶ方法やパーソナライズしてレコメンドするなどの方法がある。


後半の「意思決定を支援するシステム」は、前半のアルゴリズムによって選び出されたアイテムをユーザが実際に閲覧や購入してくれるように提示するためのシステム、ということ。**ユーザにとって価値のあるアイテムを抽出できたとしても、それが適切にユーザへ提示されないと、そのアイテムに対してアクションをとってくれない**。だから、適切にアクションしてくれるように、いつどのタイミングでどのようなUIでユーザに提示するかを設計することが大事となる。

　
Amazonのように総合ECは、取り扱っている商品数が5千万を超えるともいわれてます（参考：https://saruwakakun.com/life/amazon/rakuten）。
この中からユーザが自力で探したい商品を探すことは難しいと思われます。そんな時に、人気ランキングや過去の自分の購入商品の傾向からおすすめ商品を出してくれると、商品を探す手間が省けて、楽にショッピングを楽しむことができますよね。そういった意味で、**レコメンドシステムは（不必要な商品を提示しないという意味で）フィルタリングのような役割を持つ**ともとらえることができます。

フィルタリングしたとしても、ぐちゃぐちゃしたUIでアイテムを表示されたとしても見づらいため、購入する意欲がうせてしまいます。また、なぜその商品がおすすめなのか（例えば、「この商品をチェックした人はほかにもこんな商品をチェックしています。」といった内容）表示されていないと、おすすめされても怪しくて購入しようとはなかなか思えないですよね。そういったことを避けるために、**レコメンドシステムにおいて、いつどのタイミングで、どのようなUIでユーザにアイテムを提示するかは大事な要素**なのです。


## 検索システムとの違い
上のように考えると、レコメンドシステムは検索システムに近いものがあるとも言えます。フィルタリングが必要であったり、選んだアイテムをユーザフレンドリーに提示する必要があるなど。言い換えれば、「たくさんあるアイテムから価値あるアイテムを選ぶ」という意味では双方似ています。ここでは、検索システムとの違いを記載します。

一言でいえば、利用するユーザの態度の違いです。
- レコメンドシステム：受動的
- 検索システム：能動的

表でまとめると、次のようになります。

|                            | 検索システム                           | レコメンドシステム              |
| -------------------------- | -------------------------------- | ---------------------- |
| ユーザがあらかじめお目当てのアイテムを把握しているか | 把握していることが多い                      | 把握していないことも多い           |
| キーワード入力                    | 入力あり                             | 入力なし                   |
| 関連アイテムの推測の仕方               | 入力されたキーワードからユーザの意図を推測する          | ユーザのプロファイルや過去の行動から推測する |
| パーソナライズ                    | しないことが多いものの、近年はパーソナライズすることが増えてきた | することが多い                |


# レコメンドシステムの大まかな流れ

レコメンドシステムは大きく3つのステップに沿ってシステムが構成されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/04be29d0-9ffa-e578-a194-08c52cb6369d.png)

- ① 候補を生成する
- ② スコアリング
- ③ 再ランキング

## ① 候補を生成する
たくさんあるアイテムの中からユーザにレコメンドする候補となるアイテムを選び出すパートです。**いわゆるレコメンドのアルゴリズムがここに該当**します。例えば、協調フィルタリングやコンテンツベースフィルタリング（内容ベースフィルタリング）など。詳細は後述します。


## ② スコアリング
①で選ばれた候補に対してスコアを付けます。①でもスコアを付けますが、それとは別に新たにスコアを付けます。例えば、最新のアイテムに対してより高いスコアを付けるなどの（ビジネス的な意図を含む）恣意的なスコアを付けます。もし、恣意的なスコアを付けない場合は、①のアルゴリズムですでにスコアがついていることがあるので、そのスコアをそのまま利用します（※スコアをつけないレコメンドアルゴリズムの場合は、ルールベースなどでスコアを付けます）。


## ③ 再ランキング
②のスコアに対してランキングを振り、ランキングに応じてユーザへアイテムを提示します。


# 「① 候補を生成する」=アルゴリズムの種類
筆者が一番わからなかったのが、ここです。アルゴリズムの分け方が複雑です。可能な限りわかりやすく説明してみます。

大きな分け方として、「利用するデータの違い」と「レコメンド方法の区別の仕方」の2つの違いがあります。

## 利用するデータ | （明示的データ / 暗黙的データ）
「利用するデータの違い」は用語でいえば、「明示的データ」と「暗黙的データ（暗示的データとも呼ばれます。今回は暗黙的データと呼称します）」の2種類があります。要するに、ユーザが明示的にアイテムへの評価をしたかどうかの違いなのですが、例を出します。

- 明示的データ
    - 「この商品への満足度を5段階で評価してください」など、ユーザへアンケート等を通じて評価してもらったデータのこと
- 暗黙的データ
    - ユーザが明示的に示したアイテムへの評価値ではなく、「ページの閲覧回数」や「アイテムの購入回数」などの"ユーザ行動"を基にしたデータのこと

些細な違いのように思えますが、レコメンドシステムは明示的データか暗黙的データかで利用できるアルゴリズムが変わるので、自分がこれから作るシステムがどちらのデータを使うのかをちゃんと把握しておく必要があります。最近のレコメンドアルゴリズムの多くは暗黙的データを利用していることが多いようです。ちなみに、歴史的には明示的データを利用したレコメンドアルゴリズムが先に開発されて、後から暗黙的データもレコメンドできるアルゴリズムが開発された、という経緯があるようです。


## レコメンド方法の区別の仕方
「レコメンド方法の区別の仕方」は、入り乱れています。いくつかの区別の仕方があるので、わかりやすいところから紹介します。

### パーソナライズの有無
パーソナライズは文字通りユーザに合わせておすすめするアイテムを変えること、という意味です。それぞれでどんなレコメンドがあるかを例示すると、

- パーソナライズ無
    - 新着アイテム順
    - 閲覧回数（購入回数）の多いトップ10のアイテム
    - etc...
- パーソナライズ有
    - 協調フィルタリング/コンテンツベースフィルタリング
    - etc...

です。
パーソナライズしたほうが買ってもらえるように思えますが、パーソナライズしないほうが良い場合もあります。例えばメディア（ニュースなど）サイトでは、新着の記事の価値が高いため、パーソナライズせずに新着記事を提示するほうが良い場合もあります。


### 協調フィルタリング vs コンテンツベースフィルタリング（内容ベースフィルタリング）
協調フィルタリングは、ユーザの過去の行動ログを基にアイテムをレコメンドする方法です。一方でコンテンツベースフィルタリングは、ユーザの特徴を表すプロファイリングを行い、そのプロファイルにとっておすすめできるアイテムをレコメンドする方法です。

さらに、協調フィルタリングは2種類があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/11778c0d-0853-ad2d-9fb0-e0b59b9591e6.png)

- 「自分と似たユーザ達」が購入したアイテムをレコメンドする
    - データを使って、自分と似ているユーザを見つけます。その似ているユーザ達が過去に購入したアイテム（の中で自分が勝ったことのないアイテム）をレコメンドします。
- 「自分が購入したアイテム」と似たアイテムをレコメンドする
    - データを使って、自分が購入したアイテムと似ているアイテムを見つけ、レコメンドします。

どちらもデータを使う点は異なりますが、「自分 ⇔ 人 ⇔ アイテム」なのか「自分 ⇔ アイテム ⇔ アイテム」なのかで2種類があるというわけですね。
どちらも、「データを使って」と「似ている」ユーザまたはアイテムを推薦するという点では共通です。

「データを使って」の「データ」とは、評価値行列（評価値マトリクス）のことです。例えば以下のような形式のデータです。縦方向がユーザで、横方向がアイテムです。それぞれの値は、明示的データの場合はユーザのアイテムへの評価値で、暗黙的データの場合は閲覧回数などです。※明示的データ、暗黙的データはどちらでも使えますが、アルゴリズムは使い分ける必要があります。

|      | アイテムa | アイテムb | アイテムc | ... |
| ---- | ----- | ----- | ----- | --- |
| ユーザA | 3     |       | 2     |     |
| ユーザB | 6     | 4     |       |     |
| ユーザC | 8     |       | 4     |     |
| ...  |       |       |       |     |


「似ている」を定量的に計算するためにはまず、上の評価値行列を使って、ユーザやアイテムを表すベクトルを手に入れます※。つぎにこのベクトルを使って、ユーザ（またはアイテム）の類似度を計算します。計算には、ユークリッド距離やcos類似度、ピアソンの相関係数などが使われます（cos類似度を使うことが多いように思います）。

※このベクトルを手に入れる方法が多数あります。代表的な方法である、行列分解（Matrix Factrization）はベクトルを手に入れるためにここで使われます。行列分解しない協調フィルタリングもあります。

　
コンテンツベースフィルタリング（内容ベースフィルタリング）は、ユーザのプロファイル情報（特徴を表す情報）を何らかの方法で取得し、それをベースにアイテムとの類似度を計測し、類似度の高いアイテムを提示する方法です。

ユーザのプロファイル情報の取得方法は2つあります。
1. 明示的データの場合、会員登録する際にユーザに対して関心のあるジャンルなどを回答してもらい、その情報をユーザプロファイル情報として活用する方法です。
    1-1. 登録時に動画サブスクサービスであれば、好きなジャンルとして「SF」と回答していた場合、サービス利用時にSFのコンテンツをレコメンドします。
2. 暗黙的データの場合、例えば、直近1週間で当該ユーザが最もよく閲覧しているアイテムの情報をユーザのプロファイル情報として活用する方法です。
    2-1. 直近1週間でサスペンス系のコンテンツを最も閲覧している場合は、当該ユーザのプロファイル情報 = サスペンスとして保存しておき、サスペンス系のコンテンツをレコメンドする方法です。


#### 比較
|                       | 協調フィルタリング | コンテンツベースフィルタリング |
| --------------------- | --------- | --------------- |
| 多様性の向上                | 〇         | ×               |
| ドメイン知識を扱うコスト          | 〇         | ×               |
| コールドスタート問題への対応        | ×         | △               |
| ユーザ数が少ないサービスにおけるレコメンド | ×         | 〇               |
| アイテム特徴の活用             | ×         | 〇               |
| 予測精度                  | 〇         | △               |

- 多様性の向上：
    - 「多様性」→ レコメンド結果に含まれるアイテムが互いに似ていないこと
    - 協調フィルタリングでは、ユーザ自身が知らないようなアイテムを推薦してくれる可能性が高まるため、コンテンツベースフィルタリングよりも多様性の高いレコメンドが可能です。
- ドメイン知識を扱うコスト：
    - コンテンツベースフィルタリングでは、ユーザがアクションをとる（閲覧する/購入するなど）ときの"判断軸"を分析者が知っている必要があります。動画サービスであれば、レコメンドされた動画を見る、見ないを決断する時にどんな情報をユーザが求めているかを知り、それをデータとして保持することで、ユーザの動画視聴回数や時間を長くすることができると考えられます。一方で、協調フィルタリングでは、このようなドメイン知識を持たずとも、行動ログデータ（評価値行列）から、アイテムやユーザ同士の類似度を機械的に計算することができるため、ドメイン知識を持つ必要がないです。
- コールドスタート問題：
    - 新規アイテムが追加されたとき、協調フィルタリングはレコメンドすることが難しいです。なぜなら、協調フィルタリングはある程度のデータ量（新規アイテムに対してアクションをとってくれたユーザ数）が必要だからです。一方で、コンテンツベースフィルタリングは、コンテンツの特徴を表す情報を持っていればレコメンドすることができるため、新規アイテムが追加されたとしても問題なくレコメンドすることができます。
- ユーザ数が少ないサービスにおけるレコメンド：
    - コールドスタート問題と同様に、協調フィルタリングはある程度のデータ量（ユーザ数やアイテム数）が必要です。したがって、利用者数が少ない状況では協調フィルタリングは精度高くレコメンドすることができません。一方でコンテンツベースフィルタリングは、ユーザのプロファイル情報とコンテンツの特徴量さえあれば、レコメンドできるため、ユーザ数の影響を受けません。
- アイテム特徴の活用：
    - 協調フィルタリングでは、例えば、色違いやサイズ違いのTシャツが全く異なるアイテムとして扱われてしまう。一方で、コンテンツベースフィルタリングでは、こういったアイテムの属性情報なども加味してレコメンドできるため、サイズ違いや色違いで同じTシャツがレコメンドされてしまう、といった問題を防ぐことができる。
- 予測精度：
    - 時と場合によるが、ある程度アクティブユーザ数がいるサービスでは、協調フィルタリングのほうが精度高く予測できるといわれています。


### メモリベース vs モデルベース

これまではアルゴリズムに関する区別の仕方が多かったですが、これはシステムの運用方法に関する区別です。

- メモリベース法
    - 使用するレコメンドアルゴリズムと類似度を測定する指標や定義を決めたうえで、今手元にあるデータをすべてシステムに流し込む方法。
- モデルベース法
    - 事前にモデルを作っておき、予測したいデータを流し込む方法。

|        | レコメンドにかかる時間                       | 運用のラクさ                                                                                                                  |
| ------ | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| メモリベース | レコメンドするときに毎回全データを活用するため、時間がかかる    | ユーザの追加、アイテムの追加があってもデータを使うだけであるため、特別な考慮は不要                                                                               |
| モデルベース | レコメンドするときに必要な分だけデータを流すため、時間はかからない | データが変わる（既存ユーザが閲覧行動をすればデータが更新される、新規ユーザが追加される、新規アイテムが追加されるなど）と、モデルも更新する必要がある。モデルの更新タイミングを考える必要があるため、運用方法については慎重に検討する必要がある |



### その他
協調フィルタリングでもなく、コンテンツベースフィルタリングでもないパーソナライズのためのレコメンド方法もある。

- 回帰（または分類）問題としてとらえた機械学習モデルを構築し、予測する方法
- Factorization Machines
- 自然言語処理を応用したレコメンド方法
- etc...


## 一覧
| アルゴリズム名                           | 概要                                   | URL（筆者がQiitaを追記していく予定） |
| --------------------------------- | ------------------------------------ | ---------------------- |
| ランダム推薦                            | ランダムにアイテムを推薦する。                      |                        |
| 特定のルールに基づくレコメンド（人気度レコメンドなど）       | レコメンドの精度としてベースラインとしてよく利用される。         |                        |
| アソシエーションルール                       | シンプルな計算方法。昔からよく使われている。               |                        |
| ユーザ間型メモリベース法協調フィルタリング             | シンプルな計算方法。昔からよく使われている。               |                        |
| 回帰モデル                             | 回帰問題としてレコメンドタスクを定式化して、機械学習を適用する。     |                        |
| SVD（特異値分解）                        | シンプルな行列分解手法。                         |                        |
| NMF（非負値行列分解）                      | 非負という制約を加えた行列分解手法。                   |                        |
| MF（Matrix Factorization）          | Netflixのコンペで好成績を収めた行列分解手法。           |                        |
| IMF（Impicit Matrix Factorization） | 暗黙的データに対して対応した行列分解手法。                |                        |
| FM（Factorization Machines）        | 評価値以外にもアイテムやユーザの情報を加味することが可能な手法。     |                        |
| LDA（コンテンツベース）                     | アイテムのコンテンツ情報にトピックモデルを適用してレコメンドする手法。  |                        |
| LDA（協調フィルタリング）                    | ユーザの行動履歴にトピックモデルを適用してレコメンドする手法。      |                        |
| word2vec（コンテンツベース）                | アイテムのコンテンツ情報にword2vecを適用してレコメンドする手法。 |                        |
| item2vec（協調フィルタリング）               | ユーザの行動履歴にword2vecを適用してレコメンドする手法。     |                        |



# レコメンドアルゴリズムの予測対象
レコメンドアルゴリズムについて紹介しましたが、何を予測するのでしょうか？2種類の予測対象があります。

- 評価値の予測
- アイテムの予測

「評価値の予測」は、明示的データにおいて、ユーザがまだ評価していないアイテムに対する評価点を予測することです。例えば、ユーザAがアイテムXに対してまだ評価（5段階評価など）をしたことがないとします。この時、レコメンドアルゴリズムでは、ユーザAがアイテムXに対してどのような評価値を出すかを予測します。

「アイテムの予測」は、ユーザが好むであろうアイテムを予測します。したがって、レコメンドアルゴリズムの良しあしの判断としては、実際にユーザがそれを好む（閲覧する/購入する）などのアクションを取ってくれればくれるほど、アルゴリズムの精度が高いと言います。


# 評価指標



| 指標の分類     | 利用目的                                                                    | 代表的な指標                              |
| --------- | ----------------------------------------------------------------------- | ----------------------------------- |
| 予測誤差指標    | 評価値予測をする場合に、予測した評価値と実際の評価値の誤差を定量化したもの。                                  | ・MAE<br>・RMSE<br>など                 |
| 集合の評価指標   | モデルが出力したスコアの高いk個のアイテム集合に対して、実際にユーザが好む（閲覧した/購入した/高評価した）アイテムの一致度合を計測する指標。 | ・Precision<br>・Recall<br>・F1スコア     |
| ランキング評価指標 | アイテムの順序を考慮したランキングの評価に用いられる。モデルが出力したk個のアイテムがどれくらい正しく並んでいるかを定量化する指標。      | ・MAP<br>など                 |
| その他の評価指標  | 予測精度以外で、レコメンドシステムの満足度を間接的に測る指標。                                         | ・セレンディピティ<br>・新規性<br>・カバレッジ |


## MAE
いわゆるMAEであり、Mean Average Errorであり、「レコメンドアルゴリズムが出力した評価値の予測値」と「実際の評価値」の差分の絶対値の平均です。

## RMSE
Root Mean Squared Errorです。
「レコメンドアルゴリズムが出力した評価値の予測値」と「実際の評価値」の差分の二乗の平均の平方根をとったものです。


## Precision
レコメンドモデルでユーザ一人に対して、アイテムをk個レコメンドするとします。
このとき、
- 分子 = 当該ユーザが実際に好きなアイテムとレコメンドモデルが予測したアイテムが一致した個数
- 分母 = k
で計算した値です。


## Recall
レコメンドモデルでユーザ一人に対して、アイテムをk個レコメンドするとします。
このとき、
- 分子 = 当該ユーザが実際に好きなアイテムとレコメンドモデルが予測したアイテムが一致した個数
- 分母 = 当該ユーザが実際に好きなアイテムの個数
で計算した値です。

## F1スコア

```math
F1 = \frac{2 Recall・Precision}{Recall + Precision}
```

## MAP
Mean Average Precisionのことで、Average Precisionを全ユーザで平均化したものです。

下のように8個を順序つきで予測していたとします。このとき、5番以内の予測であれば、Average Precision（AP）は、

```math
\begin{align}
AP@5 & = \frac{1}{2} (Precision@2 + Precision@4) \\
     & = \frac{1}{2} (\frac{1}{2}  + \frac{2}{4}) \\
     & = 0.5
\end{align}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/0cc2c820-ea7b-86c1-49f5-17921ada7dd5.png)




## その他の指標（多様性/セレンディピティ/カバレッジなど）
レコメンドモデルの精度という観点では、上述した指標を使って計測することができますが、精度以外の面でのレコメンドシステムの"良さ"を測る必要がある場合もあります。

例えば、ECサイトでずっと似たような商品がレコメンドされ続けてしまったり、ニュースサイトで類似記事ばかりレコメンドされるようなレコメンドシステムはユーザ体験として好ましくないですよね。このように精度は悪くないが、特定の同じものばかりをレコメンドしがちで、ユーザがこれまでに見たことのないジャンルが全く表示されないといった問題が発生してしまうことをフィルターバブルやエコーチェンバーなどと呼びますが、これらは避けたほうが良いです。

この時、セレンディピティや新規性、カバレッジなどの指標を使ってレコメンドシステムの評価をする必要があります。

- セレンディピティは定量評価しづらいですが、ユーザが想定していなかったけれども欲しいと思えるアイテムをレコメンドできたかどうかを測るための指標です。
- 新規性は、レコメンドモデルが過去に提示したアイテムが今回の推薦にどれくらい含まれているかを測る指標です。
- カバレッジは、サービスが保有しているアイテムのうち、どれくらいをレコメンドすることができたかを表す指標です。例えば、10万個のアイテムを保有しているのに、実際にユーザに対してレコメンドしたアイテムの種類が1万個しかないような場合は、カバレッジが低いと言えます。











# まとめ
- 概要レベルでまとめてみたつもりですが、かなりボリューミーな投稿となってしまいました。
- 入門レベルの内容をまとめただけなので、レコメンドシステムのエキスパートからすると幼稚な部分が多々あったと思いますが、初心者からするとこれだけの内容を学ぶ必要があるため、かなり歯ごたえのある分野だと筆者は思いました。
- アルゴリズムの区別の仕方が難しいと感じた理由は、区別のための軸が排他的ではないことが理由だと思います。具体的には、「協調フィルタリングのメモリベースアルゴリズム」、「協調フィルタリングのモデルベースアルゴリズム」が存在します。言い換えれば、レコメンド「システム」の話とレコメンド「アルゴリズム」の話が混在しているように見えるのです。
    - メモリベース/モデルベースの違いは、運用方法の違いの話であるため、レコメンド「システム」の話です。
    - 一方で、協調フィルタリング/コンテンツベースフィルタリングは、アルゴリズムの話です。
- そこにさらに、パーソナライズの有無という区別のための軸が加わるため、非常にわかりづらいのです。さらに言えば、メモリベースとモデルベースの違いが、実際にシステムにレコメンドアルゴリズムを搭載した経験のない筆者からすると違いがあまり感じられないのです。