Filme empfehlen: Abrufen

Ansicht auf TensorFlow.org Quelle auf GitHub anzeigen Notizbuch herunterladen

Reale Empfehlungssysteme bestehen häufig aus zwei Phasen:

  1. Die Abrufphase ist für die Auswahl eines ersten Satzes von Hunderten von Kandidaten aus allen möglichen Kandidaten verantwortlich. Das Hauptziel dieses Modells besteht darin, alle Kandidaten, an denen der Benutzer nicht interessiert ist, effizient auszusortieren. Da das Abrufmodell möglicherweise Millionen von Kandidaten enthält, muss es rechnerisch effizient sein.
  2. In der Rangfolge werden die Ergebnisse des Abrufmodells verwendet und verfeinert, um die bestmögliche Handvoll Empfehlungen auszuwählen. Seine Aufgabe besteht darin, die Menge der Elemente, an denen der Benutzer interessiert sein könnte, auf eine Auswahlliste wahrscheinlicher Kandidaten einzugrenzen.

In diesem Tutorial konzentrieren wir uns auf die erste Phase, das Abrufen. Wenn Sie an der Ranking-Phase interessiert sind, schauen Sie sich unser Ranking- Tutorial an.

Abrufmodelle bestehen häufig aus zwei Untermodellen:

  1. Ein Abfragemodell, das die Abfragedarstellung (normalerweise ein Einbettungsvektor mit fester Dimension) unter Verwendung von Abfragefunktionen berechnet.
  2. Ein Kandidatenmodell, das die Kandidatendarstellung (einen Vektor gleicher Größe) unter Verwendung der Kandidatenmerkmale berechnet

Die Ausgaben der beiden Modelle werden dann miteinander multipliziert, um eine Affinitätsbewertung für den Abfragekandidaten zu erhalten, wobei höhere Bewertungen eine bessere Übereinstimmung zwischen dem Kandidaten und der Abfrage ausdrücken.

In diesem Tutorial werden wir ein solches Modell mit zwei Türmen unter Verwendung des Movielens-Datensatzes erstellen und trainieren.

Wir werden:

  1. Holen Sie sich unsere Daten und teilen Sie sie in ein Trainings- und Test-Set auf.
  2. Implementieren Sie ein Abrufmodell.
  3. Passen und bewerten.
  4. Exportieren Sie es für eine effiziente Bereitstellung, indem Sie einen ungefähren Index für die nächsten Nachbarn (ANN) erstellen.

Der Datensatz

Der Movielens-Datensatz ist ein klassischer Datensatz der GroupLens- Forschungsgruppe an der University of Minnesota. Es enthält eine Reihe von Bewertungen, die von einer Reihe von Benutzern für Filme abgegeben wurden, und ist ein Arbeitspferd für die Recherche nach Empfehlungssystemen.

Die Daten können auf zwei Arten behandelt werden:

  1. Es kann so interpretiert werden, dass es ausdrückt, welche Filme die Benutzer gesehen (und bewertet) haben und welche nicht. Dies ist eine Form des impliziten Feedbacks, bei dem Benutzeruhren uns mitteilen, welche Dinge sie am liebsten sehen und welche sie lieber nicht sehen möchten.
  2. Es kann auch als Ausdruck dafür angesehen werden, wie sehr die Benutzer die Filme mochten, die sie gesehen haben. Dies ist eine Form des expliziten Feedbacks: Angesichts der Tatsache, dass ein Benutzer einen Film gesehen hat, können wir anhand der von ihm abgegebenen Bewertung grob feststellen, wie gut er gefallen hat.

In diesem Tutorial konzentrieren wir uns auf ein Abrufsystem: ein Modell, das eine Reihe von Filmen aus dem Katalog vorhersagt, die der Benutzer wahrscheinlich sehen wird. Oft sind implizite Daten hier nützlicher, und deshalb werden wir Movielens als implizites System behandeln. Dies bedeutet, dass jeder Film, den ein Benutzer gesehen hat, ein positives Beispiel ist und jeder Film, den er nicht gesehen hat, ein implizites negatives Beispiel ist.

Importe

Lassen Sie uns zuerst unsere Importe aus dem Weg räumen.

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

Datensatz vorbereiten

Schauen wir uns zuerst die Daten an.

Wir verwenden den MovieLens-Datensatz aus Tensorflow-Datensätzen . Das Laden von movielens/100k_ratings ergibt ein tf.data.Dataset Objekt mit den Bewertungsdaten und das Laden von movielens/100k_movies ein tf.data.Dataset Objekt, das nur die Filmdaten enthält.

Beachten Sie, dass die Movielens seit dataSet Splits sind nicht vorgegeben, sind alle Daten unter train 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")

Der Bewertungsdatensatz gibt ein Wörterbuch mit der Film-ID, der Benutzer-ID, der zugewiesenen Bewertung, dem Zeitstempel, den Filminformationen und den Benutzerinformationen zurück:

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'}

Der Filmdatensatz enthält die Film-ID, den Filmtitel und Daten zu den Genres, zu denen er gehört. Beachten Sie, dass die Genres mit ganzzahligen Bezeichnungen codiert sind.

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)'}

In diesem Beispiel konzentrieren wir uns auf die Bewertungsdaten. In anderen Tutorials wird erläutert, wie Sie die Filminformationsdaten verwenden, um die Modellqualität zu verbessern.

Wir behalten nur die Felder user_id und movie_title im Dataset.

ratings = ratings.map(lambda x: {
    "movie_title": x["movie_title"],
    "user_id": x["user_id"],
})
movies = movies.map(lambda x: x["movie_title"])

Um das Modell anzupassen und zu bewerten, müssen wir es in ein Trainings- und Bewertungsset aufteilen. In einem industriellen Empfehlungssystem würde dies höchstwahrscheinlich nach Zeit erfolgen: Die Daten bis zum Zeitpunkt $ T $ würden verwendet, um Interaktionen nach $ T $ vorherzusagen.

In diesem einfachen Beispiel verwenden wir jedoch eine zufällige Aufteilung, bei der 80% der Bewertungen in den Zugsatz und 20% in den Testsatz eingefügt werden.

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)

Lassen Sie uns auch eindeutige Benutzer-IDs und Filmtitel herausfinden, die in den Daten enthalten sind.

Dies ist wichtig, da wir in der Lage sein müssen, die Rohwerte unserer kategorialen Merkmale auf Einbettungsvektoren in unsere Modelle abzubilden. Dazu benötigen wir ein Vokabular, das einen Roh-Feature-Wert einer Ganzzahl in einem zusammenhängenden Bereich zuordnet: Dadurch können wir die entsprechenden Einbettungen in unseren Einbettungstabellen nachschlagen.

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)

Modell implementieren

Die Auswahl der Architektur unseres Modells ist ein wesentlicher Bestandteil der Modellierung.

Da wir ein Abrufmodell mit zwei Türmen erstellen, können wir jeden Turm separat erstellen und dann im endgültigen Modell kombinieren.

Der Abfrageturm

Beginnen wir mit dem Abfrageturm.

Der erste Schritt besteht darin, über die Dimensionalität der Abfrage- und Kandidatendarstellungen zu entscheiden:

embedding_dimension = 32

Höhere Werte entsprechen Modellen, die möglicherweise genauer sind, aber auch langsamer passen und anfälliger für Überanpassungen sind.

Die zweite besteht darin, das Modell selbst zu definieren. Hier verwenden wir Keras-Vorverarbeitungsebenen, um zuerst Benutzer-IDs in Ganzzahlen zu konvertieren und diese dann über eine Embedding in Benutzereinbettungen zu konvertieren. Beachten Sie, dass wir die Liste der eindeutigen Benutzer-IDs, die wir zuvor berechnet haben, als Vokabular verwenden:

user_model = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.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)
])

Ein einfaches Modell wie dieses entspricht genau einem klassischen Matrixfaktorisierungsansatz . Während das Definieren einer Unterklasse von tf.keras.Model für dieses einfache Modell möglicherweise übertrieben ist, können wir es mit Standard-Keras-Komponenten leicht auf ein beliebig komplexes Modell erweitern, solange wir am Ende eine embedding_dimension weite Ausgabe zurückgeben.

Der Kandidatenturm

Wir können dasselbe mit dem Kandidatenturm tun.

movie_model = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.StringLookup(
      vocabulary=unique_movie_titles, mask_token=None),
  tf.keras.layers.Embedding(len(unique_movie_titles) + 1, embedding_dimension)
])

Metriken

In unseren Trainingsdaten haben wir positive (Benutzer, Film) Paare. Um herauszufinden, wie gut unser Modell ist, müssen wir die Affinitätsbewertung, die das Modell für dieses Paar berechnet, mit den Bewertungen aller anderen möglichen Kandidaten vergleichen: Wenn die Bewertung für das positive Paar höher ist als für alle anderen Kandidaten, unser Modell ist sehr genau.

Dazu können wir die Metrik tfrs.metrics.FactorizedTopK . Die Metrik hat ein erforderliches Argument: den Datensatz von Kandidaten, die als implizite Negative für die Bewertung verwendet werden.

In unserem Fall , dass das ist movies - Datensatz, umgewandelt in Einbettungen über unseren Film Modell:

metrics = tfrs.metrics.FactorizedTopK(
  candidates=movies.batch(128).map(movie_model)
)

Verlust

Die nächste Komponente ist der Verlust, der zum Trainieren unseres Modells verwendet wird. TFRS verfügt über mehrere Verlustschichten und Aufgaben, um dies zu vereinfachen.

In diesem Fall verwenden wir das Retrieval Abrufen": einen praktischen Wrapper, der die Verlustfunktion und die Metrikberechnung bündelt:

task = tfrs.tasks.Retrieval(
  metrics=metrics
)

Die Aufgabe selbst ist eine Keras-Ebene, die die Abfrage- und Kandidateneinbettungen als Argumente verwendet und den berechneten Verlust zurückgibt. Damit wird die Trainingsschleife des Modells implementiert.

Das vollständige Modell

Wir können jetzt alles zu einem Modell zusammenfügen. TFRS stellt eine Basismodellklasse ( tfrs.models.Model ) tfrs.models.Model die Gebäudemodelle rationalisiert. Wir müssen __init__ die Komponenten in der Methode __init__ und die Methode compute_loss implementieren, die compute_loss und einen Verlustwert zurückgeben .

Das Basismodell sorgt dann dafür, dass die entsprechende Trainingsschleife für unser Modell erstellt wird.

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)

Die tfrs.Model ist eine einfache Convenience-Klasse: Sie ermöglicht es uns, sowohl Trainings- als auch Testverluste mit derselben Methode zu berechnen.

Unter der Haube ist es immer noch ein einfaches Keras-Modell. Sie können dieselbe Funktionalität erreichen, indem Sie von tf.keras.Model train_step und test_step Funktionen train_step und test_step (Einzelheiten finden Sie im Handbuch ):

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

In diesen Tutorials bleiben wir jedoch bei der Verwendung der tfrs.Model , um uns weiterhin auf die Modellierung zu konzentrieren und einen Teil der Boilerplate zu abstrahieren.

Anpassen und bewerten

Nach der Definition des Modells können wir Standard-Keras-Anpassungs- und Bewertungsroutinen verwenden, um das Modell anzupassen und zu bewerten.

Lassen Sie uns zuerst das Modell instanziieren.

model = MovielensModel(user_model, movie_model)
model.compile(optimizer=tf.keras.optimizers.Adagrad(learning_rate=0.1))

Mischen, stapeln und zwischenspeichern Sie dann die Trainings- und Bewertungsdaten.

cached_train = train.shuffle(100_000).batch(8192).cache()
cached_test = test.batch(4096).cache()

Dann trainiere das Modell:

model.fit(cached_train, epochs=3)
Epoch 1/3
10/10 [==============================] - 5s 298ms/step - factorized_top_k/top_1_categorical_accuracy: 1.6250e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0029 - factorized_top_k/top_10_categorical_accuracy: 0.0082 - factorized_top_k/top_50_categorical_accuracy: 0.0680 - factorized_top_k/top_100_categorical_accuracy: 0.1419 - loss: 69885.1072 - regularization_loss: 0.0000e+00 - total_loss: 69885.1072
Epoch 2/3
10/10 [==============================] - 3s 289ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0020 - factorized_top_k/top_5_categorical_accuracy: 0.0150 - factorized_top_k/top_10_categorical_accuracy: 0.0315 - factorized_top_k/top_50_categorical_accuracy: 0.1565 - factorized_top_k/top_100_categorical_accuracy: 0.2807 - loss: 67523.3700 - regularization_loss: 0.0000e+00 - total_loss: 67523.3700
Epoch 3/3
10/10 [==============================] - 3s 278ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0029 - factorized_top_k/top_5_categorical_accuracy: 0.0211 - factorized_top_k/top_10_categorical_accuracy: 0.0437 - factorized_top_k/top_50_categorical_accuracy: 0.1842 - factorized_top_k/top_100_categorical_accuracy: 0.3126 - loss: 66302.9609 - regularization_loss: 0.0000e+00 - total_loss: 66302.9609
<tensorflow.python.keras.callbacks.History at 0x7f16a7780898>

Während das Modell trainiert, sinkt der Verlust und eine Reihe von Top-K-Abrufmetriken wird aktualisiert. Diese sagen uns, ob das wahre Positiv in den Top-k-abgerufenen Elementen aus dem gesamten Kandidatensatz enthalten ist. Zum Beispiel würde eine kategoriale Top-5-Genauigkeitsmetrik von 0,2 uns sagen, dass das wahre Positive in 20% der Fälle im Durchschnitt in den Top-5-abgerufenen Elementen liegt.

Beachten Sie, dass in diesem Beispiel die Metriken sowohl während des Trainings als auch während der Auswertung ausgewertet werden. Da dies bei großen Kandidatensätzen sehr langsam sein kann, kann es ratsam sein, die Metrikberechnung im Training zu deaktivieren und nur in der Evaluierung auszuführen.

Schließlich können wir unser Modell am Testsatz bewerten:

model.evaluate(cached_test, return_dict=True)
5/5 [==============================] - 1s 164ms/step - factorized_top_k/top_1_categorical_accuracy: 9.0000e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0099 - factorized_top_k/top_10_categorical_accuracy: 0.0221 - factorized_top_k/top_50_categorical_accuracy: 0.1248 - factorized_top_k/top_100_categorical_accuracy: 0.2327 - loss: 31079.0628 - regularization_loss: 0.0000e+00 - total_loss: 31079.0628
{'factorized_top_k/top_1_categorical_accuracy': 0.0008999999845400453,
 'factorized_top_k/top_5_categorical_accuracy': 0.009850000031292439,
 'factorized_top_k/top_10_categorical_accuracy': 0.022050000727176666,
 'factorized_top_k/top_50_categorical_accuracy': 0.12475000321865082,
 'factorized_top_k/top_100_categorical_accuracy': 0.23274999856948853,
 'loss': 28244.76953125,
 'regularization_loss': 0,
 'total_loss': 28244.76953125}

Die Leistung des Testsatzes ist viel schlechter als die Trainingsleistung. Dies ist auf zwei Faktoren zurückzuführen:

  1. Unser Modell wird wahrscheinlich eine bessere Leistung bei den Daten erzielen, die es gesehen hat, einfach weil es sie sich merken kann. Dieses Überanpassungsphänomen ist besonders stark, wenn Modelle viele Parameter haben. Es kann durch die Regularisierung des Modells und die Verwendung von Benutzer- und Filmfunktionen vermittelt werden, die dem Modell helfen, Daten besser auf unsichtbare Daten zu verallgemeinern.
  2. Das Modell empfiehlt einige der bereits gesehenen Filme der Benutzer erneut. Diese bekanntermaßen positiven Uhren können Testfilme aus den Top-K-Empfehlungen verdrängen.

Das zweite Phänomen kann angegangen werden, indem zuvor gesehene Filme von den Testempfehlungen ausgeschlossen werden. Dieser Ansatz ist in der Literatur zu Empfehlungssystemen relativ verbreitet, wird in diesen Tutorials jedoch nicht befolgt. Wenn es nicht wichtig ist, frühere Uhren zu empfehlen, sollten wir erwarten, dass entsprechend spezifizierte Modelle dieses Verhalten automatisch aus der Vergangenheit des Benutzers und aus Kontextinformationen lernen. Darüber hinaus ist es häufig angebracht, denselben Artikel mehrmals zu empfehlen (z. B. eine immergrüne Fernsehserie oder einen regelmäßig gekauften Artikel).

Vorhersagen treffen

Nachdem wir nun ein Modell haben, möchten wir Vorhersagen treffen können. Wir können dazu die tfrs.layers.factorized_top_k.BruteForce verwenden.

# 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(movies.batch(100).map(model.movie_model), movies)

# 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)']

Natürlich wird die BruteForce Ebene zu langsam sein, um ein Modell mit vielen möglichen Kandidaten zu bedienen. In den folgenden Abschnitten wird gezeigt, wie Sie dies mithilfe eines ungefähren Abrufindex beschleunigen können.

Modell servieren

Nachdem das Modell trainiert wurde, benötigen wir eine Möglichkeit, es bereitzustellen.

In einem Abrufmodell mit zwei Türmen besteht das Serving aus zwei Komponenten:

  • ein Serving-Abfragemodell, das Funktionen der Abfrage aufnimmt und sie in eine eingebettete Abfrage umwandelt, und
  • ein dienendes Kandidatenmodell. Dies erfolgt meistens in Form eines ANN-Index (Approximate Nearest Neighbours), der eine schnelle ungefähre Suche nach Kandidaten als Antwort auf eine vom Abfragemodell erzeugte Abfrage ermöglicht.

In TFRS können beide Komponenten in ein einzelnes exportierbares Modell gepackt werden. Dadurch erhalten wir ein Modell, das die unformatierte Benutzer-ID verwendet und die Titel der Top-Filme für diesen Benutzer zurückgibt. Dies erfolgt durch Exportieren des Modells in ein SavedModel Format, wodurch die SavedModel mit TensorFlow Serving möglich wird .

Um ein Modell wie dieses BruteForce , exportieren wir einfach die BruteForce erstellte BruteForce Ebene:

# Export the query model.
with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, "model")

  # Save the index.
  index.save(path)

  # Load it back; can also be done in TensorFlow Serving.
  loaded = tf.keras.models.load_model(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.
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/tmpedp1pofu/model/assets
INFO:tensorflow:Assets written to: /tmp/tmpedp1pofu/model/assets
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
Recommendations: [b'Bridges of Madison County, The (1995)'
 b'Father of the Bride Part II (1995)' b'Rudy (1993)']

Wir können auch einen ungefähren Abrufindex exportieren, um Vorhersagen zu beschleunigen. Auf diese Weise können Empfehlungen von mehreren zehn Millionen Kandidaten effizient veröffentlicht werden.

Dazu können wir das scann Paket verwenden. Dies ist eine optionale Abhängigkeit von TFRS. Wir haben sie zu Beginn dieses Tutorials separat installiert, indem wir !pip install -q scann .

Nach der Installation können wir die TFRS ScaNN Schicht verwenden:

scann_index = tfrs.layers.factorized_top_k.ScaNN(model.user_model)
scann_index.index(movies.batch(100).map(model.movie_model), movies)
<tensorflow_recommenders.layers.factorized_top_k.ScaNN at 0x7f16c1480400>

Diese Ebene führt ungefähre Suchvorgänge durch: Dadurch wird der Abruf etwas ungenauer, bei großen Kandidatensätzen jedoch um Größenordnungen schneller.

# 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)']

Das Exportieren zum Servieren ist so einfach wie das Exportieren der BruteForce Ebene:

# Export the query model.
with tempfile.TemporaryDirectory() as tmp:
  path = os.path.join(tmp, "model")

  # Save the index.
  scann_index.save(
      path,
      options=tf.saved_model.SaveOptions(namespace_whitelist=["Scann"])
  )

  # Load it back; can also be done in TensorFlow Serving.
  loaded = tf.keras.models.load_model(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.
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/tmprglhaqg1/model/assets
INFO:tensorflow:Assets written to: /tmp/tmprglhaqg1/model/assets
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
Recommendations: [b'Sleepless in Seattle (1993)' b'Father of the Bride Part II (1995)'
 b'Hunchback of Notre Dame, The (1996)']

Weitere Informationen zur Verwendung und Optimierung von Modellen mit schnellem ungefährem Abruf finden Sie in unserem Tutorial zur effizienten Bereitstellung .

Nächste Schritte

Damit ist das Abruf-Tutorial abgeschlossen.

Um zu erweitern, was hier vorgestellt wird, werfen Sie einen Blick auf:

  1. Lernen von Multitasking-Modellen: Gemeinsame Optimierung für Bewertungen und Klicks.
  2. Verwenden von Filmmetadaten: Erstellen eines komplexeren Filmmodells zur Verringerung des Kaltstarts.