※この記事はあくまで僕の備忘録であり、内容の整合性を保証するものではありません。
ユースケース
tensorflow_recommendersで、user / item間のデータで学習させた上で、Scannを使って、あるitemに近いitemを取得したい。
すなわち、tensorflow_recommendersで学習させたモデルで得たitemのembedding表現を利用して、似たアイテムを近似近傍探索で取得したいという状況である。
例えば、tensorflow_recommendersのチュートリアルのような学習をさせた状況を考える。
失敗例
チュートリアルにあるScannをそのままitem2itemに流用すると、おそらく失敗する。
scann = tfrs.layers.factorized_top_k.ScaNN(num_reordering_candidates=100)
scann.index_from_dataset(
tf.data.Dataset.zip((lots_of_movies, lots_of_movies_embeddings))
)
_, titles = scann(model.movie_model(np.array(["42"])), k=3)
print(f"Top recommendations: {titles[0]}")
なぜなら、Scannは内積距離の最大化をする順でベクトルを取得してしまうのだが、tensorflow_recommendersで得られるembedding表現は正規化されていないからである。
なお、user-item間の場合にScannのデフォルト設定でうまくいくのは、内積がすなわち学習データのratingを表すためである。
解決策
Scannは内積距離とユークリッド距離の2つのmetricsを選択できる。
そのため、item2itemでのレコメンドを取得したいのであれば、Scannを初期化する際にdistance_measure='squared_l2'
を指定すれば問題なく動作すると考えられる。