TensorFlow.orgで表示 | GoogleColabで実行 | GitHubでソースを表示 | ノートブックをダウンロード |
実際のレコメンダーシステムは、多くの場合、次の2つの段階で構成されます。
- 検索段階では、考えられるすべての候補から数百の候補の初期セットを選択します。このモデルの主な目的は、ユーザーが関心のないすべての候補を効率的に取り除くことです。検索モデルは数百万の候補を処理する可能性があるため、計算効率が高くなければなりません。
- ランク付け段階では、検索モデルの出力を取得し、それらを微調整して、可能な限り最良の少数の推奨事項を選択します。そのタスクは、ユーザーが関心を持つ可能性のあるアイテムのセットを、可能性のある候補の候補リストに絞り込むことです。
このチュートリアルでは、最初の段階である検索に焦点を当てます。あなたは、ランキングのステージに興味があるなら、私たちを見ていランキングチュートリアルを。
検索モデルは、多くの場合、2つのサブモデルで構成されます。
- クエリ機能を使用してクエリ表現(通常は固定次元の埋め込みベクトル)を計算するクエリモデル。
- 候補特徴を使用して候補表現(同じサイズのベクトル)を計算する候補モデル
次に、2つのモデルの出力が乗算されて、クエリ候補のアフィニティスコアが得られます。スコアが高いほど、候補とクエリの一致度が高くなります。
このチュートリアルでは、Movielensデータセットを使用して、このような2タワーモデルを構築およびトレーニングします。
に行っていました:
- データを取得し、トレーニングとテストのセットに分割します。
- 検索モデルを実装します。
- 適合させて評価します。
- おおよその最近傍(ANN)インデックスを作成することにより、効率的なサービスのためにエクスポートします。
データセット
以下からの古典的なデータセットですセットMovielens GroupLensのミネソタ大学の研究グループ。これには、一連のユーザーによって映画に与えられた一連の評価が含まれており、レコメンダーシステム研究の主力製品です。
データは2つの方法で処理できます。
- これは、ユーザーがどの映画を視聴(および評価)したか、どの映画を視聴しなかったかを表すものと解釈できます。これは暗黙のフィードバックの形式であり、ユーザーの時計は、ユーザーが見たいものと見たくないものを教えてくれます。
- また、ユーザーが視聴した映画をどれだけ気に入ったかを表すものとして見ることもできます。これは明示的なフィードバックの形式です。ユーザーが映画を視聴した場合、ユーザーが付けた評価を確認することで、ユーザーがどれだけ気に入ったかを大まかに知ることができます。
このチュートリアルでは、検索システムに焦点を当てています。これは、ユーザーが視聴する可能性のあるカタログから一連の映画を予測するモデルです。多くの場合、ここでは暗黙的なデータの方が便利なので、Movielensを暗黙的なシステムとして扱います。これは、ユーザーが見たすべての映画がポジティブな例であり、ユーザーが見たことがないすべての映画が暗黙のネガティブな例であることを意味します。
輸入
まず、インポートを邪魔にならないようにしましょう。
pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
pip install -q scann
import os
import pprint
import tempfile
from typing import Dict, Text
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
import tensorflow_recommenders as tfrs
データセットの準備
まず、データを見てみましょう。
私たちは、からMovieLensデータセットを使用Tensorflowデータセットを。ロードmovielens/100k_ratings
得tf.data.Dataset
評価データとロード含むオブジェクトmovielens/100k_movies
得tf.data.Dataset
映画だけのデータを含むオブジェクトを。
分割を事前に定義されていていないデータセットMovieLensいるので、すべてのデータが下にあることを注意train
分割。
# Ratings data.
ratings = tfds.load("movielens/100k-ratings", split="train")
# Features of all the available movies.
movies = tfds.load("movielens/100k-movies", split="train")
2021-10-02 11:05:34.633747: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
評価データセットは、映画ID、ユーザーID、割り当てられた評価、タイムスタンプ、映画情報、およびユーザー情報の辞書を返します。
for x in ratings.take(1).as_numpy_iterator():
pprint.pprint(x)
{'bucketized_user_age': 45.0, 'movie_genres': array([7]), 'movie_id': b'357', 'movie_title': b"One Flew Over the Cuckoo's Nest (1975)", 'raw_user_age': 46.0, 'timestamp': 879024327, 'user_gender': True, 'user_id': b'138', 'user_occupation_label': 4, 'user_occupation_text': b'doctor', 'user_rating': 4.0, 'user_zip_code': b'53211'} 2021-10-02 11:05:35.718641: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
映画データセットには、映画ID、映画タイトル、およびそれが属するジャンルのデータが含まれています。ジャンルは整数ラベルでエンコードされていることに注意してください。
for x in movies.take(1).as_numpy_iterator():
pprint.pprint(x)
{'movie_genres': array([4]), 'movie_id': b'1681', 'movie_title': b'You So Crazy (1994)'} 2021-10-02 11:05:35.893098: W tensorflow/core/kernels/data/cache_dataset_ops.cc:768] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.
この例では、評価データに焦点を当てます。他のチュートリアルでは、モデルの品質を向上させるために映画情報データを使用する方法についても説明します。
私たちは続けるuser_id
、およびmovie_title
データセット内のフィールドを。
ratings = ratings.map(lambda x: {
"movie_title": x["movie_title"],
"user_id": x["user_id"],
})
movies = movies.map(lambda x: x["movie_title"])
モデルを適合させて評価するには、モデルをトレーニングと評価のセットに分割する必要があります。産業推薦システムでは、これが最も可能性の高い時間で行うことになります。時間にデータをバックアップし \(T\) 後の相互作用を予測するために使用される \(T\)。
ただし、この簡単な例では、ランダム分割を使用して、評価の80%をトレインセットに入れ、20%をテストセットに入れてみましょう。
tf.random.set_seed(42)
shuffled = ratings.shuffle(100_000, seed=42, reshuffle_each_iteration=False)
train = shuffled.take(80_000)
test = shuffled.skip(80_000).take(20_000)
また、データに存在する一意のユーザーIDと映画のタイトルを把握しましょう。
これは重要です。なぜなら、カテゴリの特徴の生の値をモデルの埋め込みベクトルにマッピングできる必要があるからです。これを行うには、生の特徴値を連続した範囲の整数にマップする語彙が必要です。これにより、埋め込みテーブルで対応する埋め込みを検索できます。
movie_titles = movies.batch(1_000)
user_ids = ratings.batch(1_000_000).map(lambda x: x["user_id"])
unique_movie_titles = np.unique(np.concatenate(list(movie_titles)))
unique_user_ids = np.unique(np.concatenate(list(user_ids)))
unique_movie_titles[:10]
array([b"'Til There Was You (1997)", b'1-900 (1994)', b'101 Dalmatians (1996)', b'12 Angry Men (1957)', b'187 (1997)', b'2 Days in the Valley (1996)', b'20,000 Leagues Under the Sea (1954)', b'2001: A Space Odyssey (1968)', b'3 Ninjas: High Noon At Mega Mountain (1998)', b'39 Steps, The (1935)'], dtype=object)
モデルの実装
モデルのアーキテクチャを選択することは、モデリングの重要な部分です。
2タワーの検索モデルを構築しているため、各タワーを個別に構築してから、それらを組み合わせて最終モデルにすることができます。
クエリタワー
クエリタワーから始めましょう。
最初のステップは、クエリと候補表現の次元を決定することです。
embedding_dimension = 32
値が高いほど、より正確なモデルに対応しますが、適合が遅くなり、過剰適合しやすくなります。
2つ目は、モデル自体を定義することです。ここでは、整数に最初に変換ユーザーIDにKeras前処理層を使用し、その後を介してユーザの埋め込みにそれらを変換しようとしているEmbedding
層。以前に計算した一意のユーザーIDのリストを語彙として使用することに注意してください。
user_model = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_user_ids, mask_token=None),
# We add an additional embedding to account for unknown tokens.
tf.keras.layers.Embedding(len(unique_user_ids) + 1, embedding_dimension)
])
このような単純なモデルでは、古典的に正確に対応する行列の因数分解アプローチ。サブクラスを定義しながらtf.keras.Model
この単純なモデルではやり過ぎかもしれないが、我々は簡単に私たちが返す限り、標準Kerasコンポーネントを使用して任意の複雑なモデルに拡張することができますembedding_dimension
終わり・ワイド出力を。
候補タワー
候補タワーでも同じことができます。
movie_model = tf.keras.Sequential([
tf.keras.layers.StringLookup(
vocabulary=unique_movie_titles, mask_token=None),
tf.keras.layers.Embedding(len(unique_movie_titles) + 1, embedding_dimension)
])
指標
トレーニングデータには、ポジティブ(ユーザー、映画)のペアがあります。モデルがどれだけ優れているかを判断するには、モデルがこのペアに対して計算するアフィニティスコアを、他のすべての可能な候補のスコアと比較する必要があります。正のペアのスコアが他のすべての候補のスコアよりも高い場合、モデル非常に正確です。
これを行うために、我々は使用することができますtfrs.metrics.FactorizedTopK
メトリックを。メトリックには、1つの必須の引数があります。それは、評価の暗黙のネガとして使用される候補のデータセットです。
だ私たちの場合、 movies
セット、私たちの映画のモデルを経ての埋め込みに変換:
metrics = tfrs.metrics.FactorizedTopK(
candidates=movies.batch(128).map(movie_model)
)
損失
次の要素は、モデルのトレーニングに使用される損失です。 TFRSには、これを簡単にするためのいくつかの損失レイヤーとタスクがあります。
この例では、我々はの使用を作ってあげるRetrieval
一緒損失関数とメトリック演算をバンドルコンビニエンスラッパー:タスクオブジェクト:
task = tfrs.tasks.Retrieval(
metrics=metrics
)
タスク自体は、クエリと候補の埋め込みを引数として受け取り、計算された損失を返すKerasレイヤーです。これを使用して、モデルのトレーニングループを実装します。
フルモデル
これで、すべてを1つのモデルにまとめることができます。 TFRSは、ベースモデルクラス(公開しtfrs.models.Model
流線がモデルを構築):私たちが行う必要があるのは、中にコンポーネントを設定することです__init__
メソッド、および実装compute_loss
方法を、生の機能に取って、損失の値を返します。
次に、基本モデルが、モデルに適合する適切なトレーニングループの作成を処理します。
class MovielensModel(tfrs.Model):
def __init__(self, user_model, movie_model):
super().__init__()
self.movie_model: tf.keras.Model = movie_model
self.user_model: tf.keras.Model = user_model
self.task: tf.keras.layers.Layer = task
def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
# We pick out the user features and pass them into the user model.
user_embeddings = self.user_model(features["user_id"])
# And pick out the movie features and pass them into the movie model,
# getting embeddings back.
positive_movie_embeddings = self.movie_model(features["movie_title"])
# The task computes the loss and the metrics.
return self.task(user_embeddings, positive_movie_embeddings)
tfrs.Model
基底クラスは、単に利便クラスである:それは私たちが同じ方法を使用して、両方のトレーニングとテストの損失を計算することができます。
内部的には、それはまだプレーンなKerasモデルです。あなたは、から継承して同じ機能を実現できtf.keras.Model
とオーバーライドtrain_step
とtest_step
(参照機能をガイド詳細を):
class NoBaseClassMovielensModel(tf.keras.Model):
def __init__(self, user_model, movie_model):
super().__init__()
self.movie_model: tf.keras.Model = movie_model
self.user_model: tf.keras.Model = user_model
self.task: tf.keras.layers.Layer = task
def train_step(self, features: Dict[Text, tf.Tensor]) -> tf.Tensor:
# Set up a gradient tape to record gradients.
with tf.GradientTape() as tape:
# Loss computation.
user_embeddings = self.user_model(features["user_id"])
positive_movie_embeddings = self.movie_model(features["movie_title"])
loss = self.task(user_embeddings, positive_movie_embeddings)
# Handle regularization losses as well.
regularization_loss = sum(self.losses)
total_loss = loss + regularization_loss
gradients = tape.gradient(total_loss, self.trainable_variables)
self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))
metrics = {metric.name: metric.result() for metric in self.metrics}
metrics["loss"] = loss
metrics["regularization_loss"] = regularization_loss
metrics["total_loss"] = total_loss
return metrics
def test_step(self, features: Dict[Text, tf.Tensor]) -> tf.Tensor:
# Loss computation.
user_embeddings = self.user_model(features["user_id"])
positive_movie_embeddings = self.movie_model(features["movie_title"])
loss = self.task(user_embeddings, positive_movie_embeddings)
# Handle regularization losses as well.
regularization_loss = sum(self.losses)
total_loss = loss + regularization_loss
metrics = {metric.name: metric.result() for metric in self.metrics}
metrics["loss"] = loss
metrics["regularization_loss"] = regularization_loss
metrics["total_loss"] = total_loss
return metrics
これらのチュートリアルでは、しかし、我々は使用に固執tfrs.Model
離れた定型の一部をモデル化し、抽象的に私たちのフォーカスを維持するために、基本クラスを。
フィッティングと評価
モデルを定義した後、標準のKerasフィッティングおよび評価ルーチンを使用してモデルをフィッティングおよび評価できます。
まず、モデルをインスタンス化します。
model = MovielensModel(user_model, movie_model)
model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))
次に、トレーニングデータと評価データをシャッフル、バッチ処理、およびキャッシュします。
cached_train = train.shuffle(100_000).batch(8192).cache()
cached_test = test.batch(4096).cache()
次に、モデルをトレーニングします。
model.fit(cached_train, epochs=3)
Epoch 1/3 10/10 [==============================] - 6s 302ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0011 - factorized_top_k/top_5_categorical_accuracy: 0.0094 - factorized_top_k/top_10_categorical_accuracy: 0.0203 - factorized_top_k/top_50_categorical_accuracy: 0.1001 - factorized_top_k/top_100_categorical_accuracy: 0.1772 - loss: 69885.1129 - regularization_loss: 0.0000e+00 - total_loss: 69885.1129 Epoch 2/3 10/10 [==============================] - 3s 286ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0029 - factorized_top_k/top_5_categorical_accuracy: 0.0186 - factorized_top_k/top_10_categorical_accuracy: 0.0376 - factorized_top_k/top_50_categorical_accuracy: 0.1689 - factorized_top_k/top_100_categorical_accuracy: 0.2923 - loss: 67523.3707 - regularization_loss: 0.0000e+00 - total_loss: 67523.3707 Epoch 3/3 10/10 [==============================] - 3s 269ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0036 - factorized_top_k/top_5_categorical_accuracy: 0.0224 - factorized_top_k/top_10_categorical_accuracy: 0.0459 - factorized_top_k/top_50_categorical_accuracy: 0.1880 - factorized_top_k/top_100_categorical_accuracy: 0.3162 - loss: 66302.9609 - regularization_loss: 0.0000e+00 - total_loss: 66302.9609 <keras.callbacks.History at 0x7f560e5ea090>
あなたはTensorBoardでトレーニングプロセスを監視したい場合は、フィット()関数にTensorBoardコールバックを追加し、使用してTensorBoardを開始することができます%tensorboard --logdir logs/fit
。参照してくださいTensorBoardドキュメント詳細については。
モデルがトレーニングするにつれて、損失は減少し、上位kの取得メトリックのセットが更新されます。これらは、候補セット全体から取得された上位k個のアイテムに真の陽性があるかどうかを示します。たとえば、上位5つのカテゴリ精度メトリック0.2は、平均して、20%の確率で上位5つの取得済みアイテムに真の陽性があることを示しています。
この例では、トレーニング中および評価中にメトリックを評価することに注意してください。候補セットが大きい場合、これは非常に遅くなる可能性があるため、トレーニングではメトリック計算をオフにし、評価でのみ実行するのが賢明な場合があります。
最後に、テストセットでモデルを評価できます。
model.evaluate(cached_test, return_dict=True)
5/5 [==============================] - 2s 149ms/step - factorized_top_k/top_1_categorical_accuracy: 7.5000e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0099 - factorized_top_k/top_10_categorical_accuracy: 0.0226 - factorized_top_k/top_50_categorical_accuracy: 0.1245 - factorized_top_k/top_100_categorical_accuracy: 0.2324 - loss: 31079.0635 - regularization_loss: 0.0000e+00 - total_loss: 31079.0635 {'factorized_top_k/top_1_categorical_accuracy': 0.000750000006519258, 'factorized_top_k/top_5_categorical_accuracy': 0.009850000031292439, 'factorized_top_k/top_10_categorical_accuracy': 0.02264999970793724, 'factorized_top_k/top_50_categorical_accuracy': 0.12449999898672104, 'factorized_top_k/top_100_categorical_accuracy': 0.23235000669956207, 'loss': 28244.771484375, 'regularization_loss': 0, 'total_loss': 28244.771484375}
テストセットのパフォーマンスは、トレーニングのパフォーマンスよりもはるかに劣ります。これは2つの要因によるものです。
- 私たちのモデルは、それを記憶できるという理由だけで、それが見たデータに対してより良いパフォーマンスを発揮する可能性があります。この過剰適合現象は、モデルに多くのパラメーターがある場合に特に強くなります。これは、モデルの正則化と、モデルが見えないデータに対してより一般化するのに役立つユーザーおよびムービー機能の使用によって仲介できます。
- このモデルは、ユーザーがすでに視聴した映画の一部を再推奨しています。これらの既知のポジティブな時計は、トップKの推奨事項からテスト映画を混雑させる可能性があります。
2番目の現象は、以前に見た映画をテストの推奨事項から除外することで対処できます。このアプローチは、レコメンダーシステムの文献では比較的一般的ですが、これらのチュートリアルでは従いません。過去の時計を推奨しないことが重要な場合は、適切に指定されたモデルが過去のユーザー履歴とコンテキスト情報からこの動作を自動的に学習することを期待する必要があります。さらに、同じアイテムを複数回推奨することが適切な場合がよくあります(たとえば、常緑のテレビシリーズや定期的に購入したアイテム)。
予測を行う
モデルができたので、予測できるようにしたいと思います。我々は使用することができますtfrs.layers.factorized_top_k.BruteForce
これを行うための層を。
# Create a model that takes in raw query features, and
index = tfrs.layers.factorized_top_k.BruteForce(model.user_model)
# recommends movies out of the entire movies dataset.
index.index_from_dataset(
tf.data.Dataset.zip((movies.batch(100), movies.batch(100).map(model.movie_model)))
)
# Get recommendations.
_, titles = index(tf.constant(["42"]))
print(f"Recommendations for user 42: {titles[0, :3]}")
Recommendations for user 42: [b'Bridges of Madison County, The (1995)' b'Father of the Bride Part II (1995)' b'Rudy (1993)']
もちろん、 BruteForce
層は、多くの可能性のある候補者とのモデルを提供するには余りにも遅いことになるだろう。次のセクションでは、近似検索インデックスを使用してこれを高速化する方法を示します。
モデルサービング
モデルがトレーニングされたら、それをデプロイする方法が必要です。
2タワーの検索モデルでは、サービングには2つのコンポーネントがあります。
- サービングクエリモデル、クエリの機能を取り入れてクエリ埋め込みに変換し、
- サービング候補モデル。これはほとんどの場合、クエリモデルによって生成されたクエリに応答して候補の高速近似ルックアップを可能にする近似最近傍(ANN)インデックスの形式を取ります。
TFRSでは、両方のコンポーネントを単一のエクスポート可能なモデルにパッケージ化して、生のユーザーIDを取得し、そのユーザーのトップ映画のタイトルを返すモデルを提供できます。これはにモデルをエクスポートを介して行われSavedModel
使用して奉仕することが可能となる形式、サービングTensorFlowを。
このようなモデルを展開するには、我々は単純にエクスポートするBruteForce
我々は上記で作成したレイヤーを:
# Export the query model.
with tempfile.TemporaryDirectory() as tmp:
path = os.path.join(tmp, "model")
# Save the index.
tf.saved_model.save(index, path)
# Load it back; can also be done in TensorFlow Serving.
loaded = tf.saved_model.load(path)
# Pass a user id in, get top predicted movie titles back.
scores, titles = loaded(["42"])
print(f"Recommendations: {titles[0][:3]}")
2021-10-02 11:05:54.109254: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. WARNING:absl:Found untraced functions such as query_with_exclusions while saving (showing 1 of 1). These functions will not be directly callable after loading. INFO:tensorflow:Assets written to: /tmp/tmp7otg6id7/model/assets INFO:tensorflow:Assets written to: /tmp/tmp7otg6id7/model/assets Recommendations: [b'Bridges of Madison County, The (1995)' b'Father of the Bride Part II (1995)' b'Rudy (1993)']
予測を高速化するために、近似検索インデックスをエクスポートすることもできます。これにより、数千万の候補者のセットからの推奨事項を効率的に表示できるようになります。
そうするために、我々は使用することができますscann
パッケージを。これはTFRSのオプションの依存関係であり、我々は呼び出すことで、このチュートリアルの最初に別々にインストールさ!pip install -q scann
。
一度インストールすると、私たちはTFRS使用することができますScaNN
層を:
scann_index = tfrs.layers.factorized_top_k.ScaNN(model.user_model)
scann_index.index_from_dataset(
tf.data.Dataset.zip((movies.batch(100), movies.batch(100).map(model.movie_model)))
)
<tensorflow_recommenders.layers.factorized_top_k.ScaNN at 0x7f560caffc10>
この層は、おおよそのルックアップを実行します:このなりますが桁違いに速く大規模な候補セットに少し精度が低い検索、しかし。
# Get recommendations.
_, titles = scann_index(tf.constant(["42"]))
print(f"Recommendations for user 42: {titles[0, :3]}")
Recommendations for user 42: [b'Sleepless in Seattle (1993)' b'Father of the Bride Part II (1995)' b'Hunchback of Notre Dame, The (1996)']
サービス提供のためにそれをエクスポートすると、エクスポートするのと同じくらい簡単ですBruteForce
層を:
# Export the query model.
with tempfile.TemporaryDirectory() as tmp:
path = os.path.join(tmp, "model")
# Save the index.
tf.saved_model.save(
index,
path,
options=tf.saved_model.SaveOptions(namespace_whitelist=["Scann"])
)
# Load it back; can also be done in TensorFlow Serving.
loaded = tf.saved_model.load(path)
# Pass a user id in, get top predicted movie titles back.
scores, titles = loaded(["42"])
print(f"Recommendations: {titles[0][:3]}")
WARNING:absl:Found untraced functions such as query_with_exclusions while saving (showing 1 of 1). These functions will not be directly callable after loading. INFO:tensorflow:Assets written to: /tmp/tmp_rde8grm/model/assets INFO:tensorflow:Assets written to: /tmp/tmp_rde8grm/model/assets Recommendations: [b'Bridges of Madison County, The (1995)' b'Father of the Bride Part II (1995)' b'Rudy (1993)']
高速近似検索モデルを使用して、チューニングの詳細については、私たちを見てい効率的なサービス提供のチュートリアルを。
アイテム間の推奨
このモデルでは、ユーザームービーモデルを作成しました。ただし、一部のアプリケーション(たとえば、製品の詳細ページ)では、アイテムからアイテム(たとえば、映画から映画、または製品から製品)の推奨を実行するのが一般的です。
このようなトレーニングモデルは、このチュートリアルに示されているのと同じパターンに従いますが、トレーニングデータが異なります。ここでは、ユーザーと映画タワーがあり、(ユーザー、映画)ペアを使用してそれらをトレーニングしました。アイテム間モデルでは、2つのアイテムタワー(クエリアイテムと候補アイテム用)があり、(クエリアイテム、候補アイテム)のペアを使用してモデルをトレーニングします。これらは、製品の詳細ページをクリックすることで作成できます。
次のステップ
これで検索チュートリアルは終了です。
ここに示されている内容を拡張するには、以下を参照してください。
- マルチタスクモデルの学習:評価とクリックを共同で最適化します。
- 映画のメタデータの使用:コールドスタートを軽減するためのより複雑な映画モデルの構築。