よくある推薦システムの構成と使われるアプリケーション例

# はじめに
こんにちは[rilmayer](https://twitter.com/rilmayer_jp)です。
この記事はアドベントカレンダー「[Search&Discovery 全部俺](https://adventar.org/calendars/4691)」17日目の記事となります。（遅れ・・・

今日は一般的な推薦システムの構成について簡単に説明しつつ、それぞれのコンポーネントが何をやっているか、それぞれのコンポーネントを担う代表的なアプリケーションについて紹介したいと思います。

# 推薦システムの構成
以下の図は、著者が今まで見たシステムや「[推薦システム: 統計的機械学習の理論と実践](https://amzn.to/2MeJ4EL)」や「[AIアルゴリズムマーケティング 自動化のための機械学習](https://amzn.to/2P5uHEU)」、「[Building a smart recommender system across LINE services](https://speakerdeck.com/line_devday2019/building-a-smart-recommender-system-across-line-services?slide=15)」などをベースに作成しています。

![note_表紙.044.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108223/e54d4cd1-90e4-03c1-5219-47a1190a9b62.jpeg)

以下、それぞれの部品っぽいものをコンポーネントとして、どんな働きをするかというのと、実際にどんなアプリケーションで実現できるかというのを紹介していきます。
なお、インターフェースは[検索の方で紹介している](https://qiita.com/rilmayer/items/670e2a24fe16a00d1407)ので割愛します。

## 全体の流れ
もっとも大きな流れはインターフェースシステムから**推薦システム**にユーザーの行動情報をコンテクストとしてリクエストを送り、推薦結果であるアイテムリストを受け取るという部分です。
（「コンテクスト」という言葉は一般的に「推薦に到るまでのユーザーの行動」といった意味で使われることが多いですが、ここではアイテム情報、ユーザー行動、いわゆるコンテクストの3つをまとめてコンテクストとしていることにご注意ください。）
**推薦システム**の中には**検索器**と**ランク器**があり、最初に検索器で粗くアイテムを取得し、ランク器でコンテクストに適した形のランキングに並び替えるという方法が良く行われています。
これは大量のアイテムに対して初めからランキングを行ってしまうと計算量が多くなってしまい、レスポンスタイムが遅くなったり計算リソースの枯渇に繋がってしまうためです。

ランク器は**学習器**によってモデル（ランキングのパラメータや、予測モデルなど）が作成されます。
学習器はユーザーの行動ログなどを元にモデルを作成するコンポーネントです。

## 検索器
ユーザーIDやアイテムID、または何らかの特徴量を元に関連するアイテムを一定数のサイズに絞ります。
このコンポーネントは[（以前に紹介した）検索システム](https://qiita.com/rilmayer/items/670e2a24fe16a00d1407)やキーバリューストアなどをベースに実現されます。

アイテム・ユーザーデータベースから何らかのクエリで問い合わせることができるような適切な形でアイテムを保持できるようにするアプリケーションが必要です。

また、データを保持するキーバリューストアは以下のようなものがあります。

- ソフトウェア（サーバー上に構築） ... [redis](https://redis.io/)、[memcached](https://memcached.org/)など
- フルマネージド ... [Amazon DynamoDB](https://aws.amazon.com/jp/dynamodb/)、[Cloud Datastore](https://cloud.google.com/datastore/?hl=ja)

## ランク器/学習器（Ranker/Trainer）
ランク器では検索器によって取り出したアイテムを並び替えます。
ランキングには事前に学習したモデルを元に並び替えが行われます。

### 実際に使われる技術
- 横断的に扱える技術
    - [Cloud ML Engine](https://cloud.google.com/ml-engine/?hl=ja)、[Amazon SageMaker](https://aws.amazon.com/jp/sagemaker/) ... モデルの構築から管理デプロイまで一貫して行える
- ストレージ: モデルやデータの格納
    - [Amazon S3](https://aws.amazon.com/jp/s3/)、[Cloud Strage](https://cloud.google.com/storage/?hl=ja) ... オブジェクトのストレージとして用いられる
    - Dockerイメージをそのままモデルとすることもある
- データベース（大規模データの計算）
    - [Hadoop](http://hadoop.apache.org/)、[BigQuery](https://cloud.google.com/bigquery/?hl=ja) ... 分散処理によりデータ分析等を可能にする
- モデル構築
    - Pythonの技術スタック ... 現在広く使われているので一部を紹介
        - [scikit-learn](https://scikit-learn.org/stable/) ... 各種の機械学習ライブラリを用いることができる
        - [PyTorch](https://pytorch.org/) ... Python用のディープラーニングライブラリ
    - その他言語
        - [C++](https://isocpp.org/) 、[JAVA](https://java.com/)... フルスクラッチで実装されるケースがある（早い）

### オンライン学習/オフライン学習
モデルの更新は1日に1回や管理者の都度更新（オフライン更新）であったり、ユーザーの行動が即座に反映されるオンライン更新であったりします。
それぞれ使われる技術が異なります。

データパイプライン+モデルの更新処理をどのように構築するかという問題であり、[検索システムでどのようにインデックスを行うか](https://qiita.com/rilmayer/items/670e2a24fe16a00d1407#%E3%82%A4%E3%83%B3%E3%83%87%E3%82%AF%E3%82%B7%E3%83%B3%E3%82%B0%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E6%8A%80%E8%A1%93)という項目が参考になります。

オンライン学習を行う場合は、モデルによっては実現が難しいものもあるため、どのようなモデルを選択するかが非常に重要となります。

# おわりに
推薦システムについてはまだ色々な形が生まれているので、これが正解というものはありません。
ですので色々なアーキテクチャを見ながら、自サービスにとって最適な形になるように試行錯誤が必要だと思います。

また、いくつかのコンポーネントは以前の検索システムで紹介したようなものが多かったと思います。
こうして見ると検索と推薦はやはり似ている部分が非常に多いですね。