Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
Les systèmes de recommandation du monde réel sont souvent composés de deux étapes :
- L'étape de récupération est chargée de sélectionner un ensemble initial de centaines de candidats parmi tous les candidats possibles. L'objectif principal de ce modèle est d'éliminer efficacement tous les candidats qui ne intéressent pas l'utilisateur. Étant donné que le modèle de récupération peut traiter des millions de candidats, il doit être efficace en termes de calcul.
- L'étape de classement prend les sorties du modèle de récupération et les affine pour sélectionner la meilleure poignée possible de recommandations. Sa tâche consiste à réduire l'ensemble d'éléments susceptibles d'intéresser l'utilisateur à une liste restreinte de candidats probables.
Dans ce tutoriel, nous allons nous concentrer sur la première étape, la récupération. Si vous êtes intéressé par la phase de classement, consultez notre classement tutoriel.
Les modèles de récupération sont souvent composés de deux sous-modèles :
- Un modèle de requête calculant la représentation de la requête (normalement un vecteur d'intégration à dimension fixe) à l'aide de fonctionnalités de requête.
- Un modèle candidat calculant la représentation candidate (un vecteur de taille égale) à l'aide des caractéristiques candidates
Les sorties des deux modèles sont ensuite multipliées ensemble pour donner un score d'affinité requête-candidat, avec des scores plus élevés exprimant une meilleure correspondance entre le candidat et la requête.
Dans ce didacticiel, nous allons créer et entraîner un tel modèle à deux tours à l'aide de l'ensemble de données Movielens.
Nous allons :
- Obtenez nos données et divisez-les en un ensemble d'entraînement et de test.
- Mettre en œuvre un modèle de récupération.
- Ajustez-le et évaluez-le.
- Exportez-le pour une diffusion efficace en créant un indice approximatif des voisins les plus proches (ANN).
L'ensemble de données
L'ensemble de données MovieLens est un ensemble de données classique des GroupLens groupe de recherche à l'Université du Minnesota. Il contient un ensemble de notes attribuées aux films par un ensemble d'utilisateurs et constitue un outil de recherche de système de recommandation.
Les données peuvent être traitées de deux manières :
- Il peut être interprété comme exprimant les films que les utilisateurs ont regardés (et notés) et ceux qu'ils n'ont pas vus. Il s'agit d'une forme de retour implicite, où les montres des utilisateurs nous indiquent ce qu'ils préfèrent voir et ce qu'ils préfèrent ne pas voir.
- Cela peut également être considéré comme exprimant à quel point les utilisateurs ont aimé les films qu'ils ont regardés. C'est une forme de retour explicite : étant donné qu'un utilisateur a regardé un film, on peut dire à peu près combien il a aimé en regardant la note qu'il a donnée.
Dans ce tutoriel, nous nous concentrons sur un système de récupération : un modèle qui prédit un ensemble de films du catalogue que l'utilisateur est susceptible de regarder. Souvent, les données implicites sont plus utiles ici, et nous allons donc traiter Movielens comme un système implicite. Cela signifie que chaque film qu'un utilisateur a regardé est un exemple positif, et chaque film qu'il n'a pas vu est un exemple implicitement négatif.
Importations
Éliminons d'abord nos importations.
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
Préparation du jeu de données
Voyons d'abord les données.
Nous utilisons l'ensemble de données MovieLens de tensorflow datasets . Chargement movielens/100k_ratings
donne un tf.data.Dataset
objet contenant les données de notation et le chargement movielens/100k_movies
donne un tf.data.Dataset
objet contenant uniquement les données de films.
Notez que depuis le jeu de données MovieLens ne dispose pas des scissions prédéfinies, toutes les données sont en train
de Split.
# 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
L'ensemble de données de classement renvoie un dictionnaire de l'identifiant du film, de l'identifiant de l'utilisateur, de la note attribuée, de l'horodatage, des informations sur le film et des informations sur l'utilisateur :
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.
L'ensemble de données de films contient l'identifiant du film, le titre du film et des données sur les genres auxquels il appartient. Notez que les genres sont codés avec des étiquettes entières.
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.
Dans cet exemple, nous allons nous concentrer sur les données d'évaluation. D'autres didacticiels explorent également comment utiliser les données d'informations sur le film pour améliorer la qualité du modèle.
Nous ne gardons que le user_id
et movie_title
champs dans l'ensemble de données.
ratings = ratings.map(lambda x: {
"movie_title": x["movie_title"],
"user_id": x["user_id"],
})
movies = movies.map(lambda x: x["movie_title"])
Pour ajuster et évaluer le modèle, nous devons le diviser en un ensemble de formation et d'évaluation. Dans un système de recommender industriel, ce serait très probablement fait par le temps: les données jusqu'à temps \(T\) serait utilisé pour prédire les interactions après \(T\).
Dans cet exemple simple, cependant, utilisons une répartition aléatoire, mettant 80% des notes dans l'ensemble de train et 20% dans l'ensemble de test.
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)
Déterminons également les identifiants d'utilisateur uniques et les titres de films présents dans les données.
Ceci est important car nous devons être en mesure de mapper les valeurs brutes de nos caractéristiques catégorielles aux vecteurs intégrés dans nos modèles. Pour ce faire, nous avons besoin d'un vocabulaire qui mappe une valeur de caractéristique brute à un entier dans une plage contiguë : cela nous permet de rechercher les plongements correspondants dans nos tables de plongement.
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)
Implémentation d'un modèle
Le choix de l'architecture de notre modèle est un élément clé de la modélisation.
Parce que nous construisons un modèle de récupération à deux tours, nous pouvons construire chaque tour séparément, puis les combiner dans le modèle final.
La tour d'interrogation
Commençons par la tour de requête.
La première étape consiste à décider de la dimensionnalité de la requête et des représentations candidates :
embedding_dimension = 32
Des valeurs plus élevées correspondront à des modèles qui peuvent être plus précis, mais seront également plus lents à s'adapter et plus sujets au surajustement.
La seconde est de définir le modèle lui-même. Ici, nous allons utiliser des couches de pré - traitement KERAS premier utilisateur à convertir ids en entiers, puis convertir ceux incorporations utilisateur via une Embedding
couche. Notez que nous utilisons la liste des identifiants d'utilisateur uniques que nous avons calculés précédemment comme vocabulaire :
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)
])
Un modèle simple comme cela correspond exactement à un classique factorisation matrice approche. Lors de la définition d' une sous - classe de tf.keras.Model
pour ce modèle simple pourrait être surpuissant, nous pouvons facilement l' étendre à un modèle arbitrairement complexe en utilisant des composants standards KERAS, aussi longtemps que nous revenons d' une embedding_dimension
sortie -Wide à la fin.
La tour des candidats
On peut faire de même avec la tour candidate.
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)
])
Métrique
Dans nos données d'entraînement, nous avons des paires positives (utilisateur, film). Pour déterminer la qualité de notre modèle, nous devons comparer le score d'affinité que le modèle calcule pour cette paire aux scores de tous les autres candidats possibles : si le score de la paire positive est plus élevé que pour tous les autres candidats, notre modèle est très précis.
Pour ce faire, nous pouvons utiliser la tfrs.metrics.FactorizedTopK
métrique. La métrique a un argument obligatoire : l'ensemble de données des candidats qui sont utilisés comme négatifs implicites pour l'évaluation.
Dans notre cas, c'est le movies
ensemble de données, converti en incorporations via notre modèle de film:
metrics = tfrs.metrics.FactorizedTopK(
candidates=movies.batch(128).map(movie_model)
)
Perte
Le composant suivant est la perte utilisée pour entraîner notre modèle. TFRS a plusieurs couches et tâches de perte pour rendre cela facile.
Dans ce cas, nous utilisons la Retrieval
objet tâche: commodité emballage que liasses la fonction de perte et calcul métrique:
task = tfrs.tasks.Retrieval(
metrics=metrics
)
La tâche elle-même est une couche Keras qui prend la requête et les plongements candidats comme arguments, et renvoie la perte calculée : nous l'utiliserons pour implémenter la boucle d'apprentissage du modèle.
Le modèle complet
Nous pouvons maintenant mettre le tout ensemble dans un modèle. TFRS expose une classe de modèle de base ( tfrs.models.Model
) qui rationalise la construction de modèles: tout ce que nous devons faire est de mettre en place les composants dans la __init__
méthode, et mettre en œuvre la compute_loss
méthode, en prenant les fonctions premières et de retourner une valeur de perte .
Le modèle de base s'occupera ensuite de créer la boucle d'entraînement appropriée pour s'adapter à notre modèle.
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)
La tfrs.Model
classe de base est une classe tout simplement pratique: il nous permet de calculer les pertes de formation et de test en utilisant la même méthode.
Sous le capot, c'est toujours un modèle Keras sobre. Vous pouvez obtenir la même fonctionnalité en héritant de tf.keras.Model
et en remplaçant les train_step
et test_step
fonctions (voir le guide pour les détails):
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
Dans ces tutoriels, cependant, nous restons fidèles à l' aide de la tfrs.Model
classe de base pour continuer à nous concentrer sur la modélisation et abstraire certains des passe- partout.
Ajustement et évaluation
Après avoir défini le modèle, nous pouvons utiliser les routines d'ajustement et d'évaluation Keras standard pour ajuster et évaluer le modèle.
Commençons par instancier le modèle.
model = MovielensModel(user_model, movie_model)
model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))
Ensuite, mélangez, regroupez et cachez les données d'entraînement et d'évaluation.
cached_train = train.shuffle(100_000).batch(8192).cache()
cached_test = test.batch(4096).cache()
Ensuite, entraînez le modèle :
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>
Si vous voulez suivre le processus de formation avec TensorBoard, vous pouvez ajouter une fonction de rappel de TensorBoard à ajustement (), puis commencer à TensorBoard en utilisant %tensorboard --logdir logs/fit
. S'il vous plaît se référer à la documentation TensorBoard pour plus de détails.
Au fur et à mesure que le modèle s'entraîne, la perte diminue et un ensemble de métriques de récupération top-k est mis à jour. Ceux-ci nous indiquent si le vrai positif se trouve dans le top-k des éléments récupérés de l'ensemble des candidats. Par exemple, une métrique de précision catégorielle des 5 premiers de 0,2 nous indiquerait qu'en moyenne, le vrai positif se trouve dans les 5 premiers éléments récupérés 20 % du temps.
Notez que, dans cet exemple, nous évaluons les métriques pendant la formation ainsi que l'évaluation. Étant donné que cela peut être assez lent avec de grands ensembles de candidats, il peut être prudent de désactiver le calcul des métriques lors de la formation et de ne l'exécuter que lors de l'évaluation.
Enfin, nous pouvons évaluer notre modèle sur l'ensemble de test :
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}
Les performances de l'ensemble de test sont bien pires que les performances d'entraînement. Cela est dû à deux facteurs:
- Notre modèle est susceptible de mieux fonctionner sur les données qu'il a vues, simplement parce qu'il peut les mémoriser. Ce phénomène de surapprentissage est particulièrement fort lorsque les modèles ont de nombreux paramètres. Il peut être médié par la régularisation du modèle et l'utilisation de fonctionnalités d'utilisateur et de film qui aident le modèle à mieux se généraliser aux données invisibles.
- Le modèle recommande à nouveau certains des films déjà regardés par les utilisateurs. Ces montres positives connues peuvent évincer les films de test des meilleures recommandations K.
Le deuxième phénomène peut être combattu en excluant les films déjà vus des recommandations de test. Cette approche est relativement courante dans la littérature sur les systèmes de recommandation, mais nous ne la suivons pas dans ces didacticiels. S'il est important de ne pas recommander les montres passées, nous devrions nous attendre à ce que les modèles correctement spécifiés apprennent automatiquement ce comportement à partir de l'historique des utilisateurs passés et des informations contextuelles. De plus, il est souvent approprié de recommander le même article plusieurs fois (par exemple, une série télévisée à feuilles persistantes ou un article acheté régulièrement).
Faire des prédictions
Maintenant que nous avons un modèle, nous aimerions pouvoir faire des prédictions. Nous pouvons utiliser la tfrs.layers.factorized_top_k.BruteForce
couche pour ce faire.
# 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)']
Bien sûr, la BruteForce
couche va être trop lent pour servir un modèle avec de nombreux candidats possibles. Les sections suivantes montrent comment accélérer cette opération en utilisant un index de récupération approximatif.
Modèle au service
Une fois le modèle formé, nous avons besoin d'un moyen de le déployer.
Dans un modèle de récupération à deux tours, la diffusion comporte deux composants :
- un modèle de requête de service, prenant en compte les caractéristiques de la requête et les transformant en une incorporation de requête, et
- un modèle de candidat au service. Cela prend le plus souvent la forme d'un index approximatif des voisins les plus proches (ANN) qui permet une recherche approximative rapide des candidats en réponse à une requête produite par le modèle de requête.
Dans TFRS, les deux composants peuvent être regroupés dans un seul modèle exportable, ce qui nous donne un modèle qui prend l'identifiant utilisateur brut et renvoie les titres des meilleurs films pour cet utilisateur. Cela se fait via l' exportation du modèle à un SavedModel
format, ce qui permet de servir en utilisant tensorflow service .
Pour déployer un modèle comme celui - ci, nous avons simplement exporter la BruteForce
couche que nous avons créé ci - dessus:
# 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)']
Nous pouvons également exporter un index de récupération approximatif pour accélérer les prédictions. Cela permettra de faire émerger efficacement des recommandations à partir d'ensembles de dizaines de millions de candidats.
Pour ce faire, nous pouvons utiliser le scann
package. Ceci est une dépendance facultative de TFRS, et nous avons installé séparément au début de ce tutoriel en appelant !pip install -q scann
.
Une fois installé , nous pouvons utiliser la TFRS ScaNN
couche:
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>
Cette couche effectue des recherches approximatives: ce qui rend la récupération un peu moins précis, mais les ordres de grandeur plus rapide sur les grands ensembles candidats.
# 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)']
Exportation pour servir est aussi facile que l' exportation de la BruteForce
couche:
# 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)']
Pour en savoir plus sur l' utilisation et l' optimisation des modèles de récupération rapide approximatives, jetez un oeil à notre portion efficace tutoriel.
Recommandation d'article à article
Dans ce modèle, nous avons créé un modèle de film utilisateur. Cependant, pour certaines applications (par exemple, les pages de détails de produits), il est courant d'effectuer des recommandations élément à élément (par exemple, film à film ou produit à produit).
Les modèles d'entraînement comme celui-ci suivraient le même modèle que celui illustré dans ce didacticiel, mais avec des données d'entraînement différentes. Ici, nous avions un utilisateur et une tour de cinéma, et nous avons utilisé des paires (utilisateur, film) pour les former. Dans un modèle élément à élément, nous aurions deux tours d'éléments (pour la requête et l'élément candidat) et formerions le modèle à l'aide de paires (élément de requête, élément candidat). Ceux-ci pourraient être construits à partir de clics sur les pages de détails des produits.
Prochaines étapes
Ceci conclut le didacticiel de récupération.
Pour développer ce qui est présenté ici, jetez un œil à:
- Apprentissage de modèles multi-tâches : optimisation conjointe des notes et des clics.
- Utilisation des métadonnées de film : création d'un modèle de film plus complexe pour atténuer le démarrage à froid.