🤩
LibRecommenderが使いやすかった話
はじめに
- Two-Towerなどの推薦アルゴリズムについて調査を進めている中で、LibRecommenderについての日本語の記事がなかったので、復習がてら、執筆しました。参考になれば幸いです。
Librecommenderとは?(以下、引用)
概要
LibRecommender は、エンドツーエンドの推奨プロセスに重点を置いた、使いやすい推奨システムです。トレーニング (libreco) およびサービング (libserving) モジュールが含まれており、ユーザーはさまざまな種類の推奨モデルをすばやくトレーニングしてデプロイできます。
主な機能は次のとおりです:
- FM、DIN、LightGCN などの一般的な推奨アルゴリズムを多数実装しています。完全なアルゴリズム リスト を参照してください。
- ハイブリッド推奨システム。ユーザーは、協調フィルタリングまたはコンテンツベースの機能のいずれかを使用できます。新機能は、オンザフライで追加できます。
- メモリ使用量が少なく、カテゴリおよび多値カテゴリ機能をスパース表現に自動的に変換します。
- 明示的および暗黙的なデータセットの両方のトレーニング、および暗黙的なデータのネガティブ サンプリングをサポートします。
- エンドツーエンドのワークフロー (データ処理/前処理 -> モデル トレーニング -> 評価 -> 保存/読み込み -> 提供) を提供します。
- コールド スタート予測と推奨をサポートします。
- 動的な機能とシーケンスの推奨をサポートします。
- すべてのアルゴリズムに統一された使いやすい API を提供します。
- 新しいデータから新しいユーザー/アイテムを使用してモデルを簡単に再トレーニングできます。
References
[1] Category:
pure
は行動データのみを使用する協調フィルタリング アルゴリズムを意味し、feat
は他の副次的特徴を含めることができることを意味します。[2] Sequence: ユーザーの行動シーケンスを活用するアルゴリズム。
[3] Graph: グラフ埋め込み (GE) やグラフ ニューラル ネットワーク (GNN) などのグラフ情報を活用するアルゴリズム。
[4] Embedding: 最終的なユーザーおよびアイテムの埋め込みを生成できるアルゴリズム。
デモ(TwoTower)
データ準備
- 数値とカテゴリのカラムを設定してデータを準備する
※この際に、ユーザーに該当するからむを’user’,アイテムに該当するカラムを’item’、スコアやレートに該当するカラムを'label'に変名し、左側に置いておかないとエラーになります。
from libreco.data import DatasetFeat
sparse_col = ["sex", "occupation", "genre1", "genre2", "genre3"]
dense_col = ["age"]
user_col = ["sex", "age", "occupation"]
item_col = ["genre1", "genre2", "genre3"]
train_data, data_info = DatasetFeat.build_trainset(train_data, user_col, item_col, sparse_col, dense_col)
eval_data = DatasetFeat.build_evalset(eval_data)
test_data = DatasetFeat.build_testset(test_data)
学習
- 今回は少し細かく設定しています。
from libreco.algorithms import TwoTower
model = TwoTower(
"ranking",
data_info,
loss_type='softmax',
embed_size=16,
norm_embed=False,
n_epochs=5,
lr=0.001,
batch_size=256,
sampler='popular',
num_neg=1,
use_bn=True,
dropout_rate=0.1,
hidden_units=(128, 64, 32),
margin=1.0,
use_correction=True,
temperature=1.0,
remove_accidental_hits=True,
ssl_pattern=None,
alpha=0.2,
seed=42,
tf_sess_config=None
)
model.fit(train_data,
neg_sampling=True,
verbose=2,
shuffle=True,
eval_data=eval_data,
metrics=["loss", "roc_auc", "precision", "recall", "ndcg"],
k=10,
eval_batch_size=8192)
# train: 100%|██████████| 1563/1563 [00:16<00:00, 94.80it/s]
# Epoch 5 elapsed: 16.498s
# train_loss: 5.1638
# eval_pointwise: 100%|██████████| 13/13 [00:00<00:00, 541.06it/s]
# eval_listwise: 100%|██████████| 2797/2797 [00:01<00:00, 1860.42it/s]
# eval log_loss: 0.4866
# eval roc_auc: 0.8689
# eval precision@10: 0.0451
# eval recall@10: 0.0827
# eval ndcg@10: 0.1794
# ==============================
評価
from libreco.evaluation import evaluate
evaluate(
model=model,
data=test_data,
neg_sampling=True, # perform negative sampling on test data
metrics=["loss", "roc_auc", "precision", "recall", "ndcg"],
)
# eval_pointwise: 100%|██████████| 13/13 [00:00<00:00, 405.12it/s]
# eval_listwise: 100%|██████████| 2834/2834 [00:01<00:00, 1905.65it/s]
# {'loss': 0.4876128090140591,
# 'roc_auc': 0.8681895942994191,
# 'precision': 0.04418563613905064,
# 'recall': 0.08114577510636821,
# 'ndcg': 0.17590274424371724}
予測
- ユーザ名(ID)だけで予測可能です。
model.recommend_user(user=1, n_rec=3)
# {1: array([ 34, 595, 588])}
- 複数ユーザも同時予測可能
model.recommend_user(user=[1, 2, 3], n_rec=3)
# {1: array([ 34, 595, 588]),
# 2: array([ 480, 377, 1617]),
# 3: array([1198, 2028, 1210])}
- 属性情報を追加(またはその一部だけでも)も対応可能
model.recommend_user(user=1, n_rec=3, user_feats={"sex": "M", "age": 33})
# {1: array([1219, 919, 2858])}
- ユーザーとアイテムのスコア算出も可能で、コールドスタート問題が発生した場合は平均で対応できる
model.predict(user=1, item=100, cold_start = 'average')
# array([0.01761321], dtype=float32)
感想
- 個人的に扱ってみて良かったと思う点は以下です。
- 属性情報(ユーザーの性別やアイテムのジャンル)を自動で処理してくれる
- モデルの評価も自動でしてくれる
- 予測の際に学習時に使用した属性情報を一部入力しなくとも予測ができる
- 検索もスコア算出にも対応している
- 商用利用可能
* バッチ予測系のタスクの場合であれば、業務上でも使える場面は多いのかなと感じました。
Discussion