לשמור את התאריך! קלט / פלט של Google חוזר 18-20 במאי הירשם עכשיו
דף זה תורגם על ידי Cloud Translation API.
Switch to English

המלצה על סרטים: אחזור

צפה ב- TensorFlow.org הפעל בגוגל קולאב צפה במקור ב- GitHub הורד מחברת

מערכות ממליצים בעולם האמיתי מורכבות לרוב משני שלבים:

  1. שלב האחזור אחראי לבחירת מערך ראשוני של מאות מועמדים מכל המועמדים האפשריים. המטרה העיקרית של מודל זה היא לחסל ביעילות את כל המועמדים שהמשתמש אינו מעוניין בהם. מכיוון שמודל האחזור עשוי להתמודד עם מיליוני מועמדים, עליו להיות יעיל מבחינה חישובית.
  2. שלב הדירוג לוקח את תפוקות מודל האחזור ומכוון אותם בכדי לבחור קומץ המלצות טוב ביותר. המשימה שלה היא לצמצם את מכלול הפריטים שהמשתמש עשוי להתעניין בהם לרשימה קצרה של מועמדים סבירים.

במדריך זה נתמקד בשלב הראשון, בשליפה. אם אתה מעוניין בשלב הדירוג, עיין במדריך הדירוג שלנו.

מודלים לאחזור מורכבים לרוב משני דגמי משנה:

  1. מודל שאילתה המחשב את ייצוג השאילתה (בדרך כלל וקטור הטבעה בעל מימד קבוע) באמצעות תכונות שאילתה.
  2. מודל מועמד המחשב את ייצוג המועמד (וקטור בגודל שווה) תוך שימוש בתכונות המועמדים

לאחר מכן מכפילים את התפוקות של שני המודלים יחד בכדי לתת ציון זיקה למועמד לשאילתה, כאשר ציונים גבוהים יותר מבטאים התאמה טובה יותר בין המועמד לשאילתה.

במדריך זה אנו הולכים לבנות ולהכשיר מודל דו-מגדלי שכזה באמצעות מערך הנתונים Movielens.

אנחנו הולכים ל:

  1. קבל את הנתונים שלנו ופצל אותם למערך אימונים ומבחנים.
  2. יישם מודל אחזור.
  3. התאם והערך אותו.
  4. ייצא אותו להגשה יעילה על ידי בניית אינדקס שכנים קרוב ביותר (ANN).

מערך הנתונים

מערך הנתונים Movielens הוא מערך נתונים קלאסי מקבוצת המחקר GroupLens באוניברסיטת מינסוטה. הוא מכיל מערך דירוגים שניתן לסרטים על ידי קבוצת משתמשים, והוא סוס עבודה של מחקר מערכת ממליץ.

ניתן לטפל בנתונים בשתי דרכים:

  1. ניתן לפרש אותו כמבטא באילו סרטים המשתמשים צפו (ודורגו), ואילו לא צפו. זוהי סוג של משוב מרומז, שבו שעוני המשתמשים מספרים לנו אילו דברים הם מעדיפים לראות ואילו מעדיפים שלא לראות.
  2. ניתן לראות בכך גם ביטוי עד כמה המשתמשים אהבו את הסרטים שהם כן צפו. זו סוג של משוב מפורש: בהתחשב בכך שמשתמש צפה בסרט, אנו יכולים לומר בערך כמה הם אהבו על ידי התבוננות בדירוג שנתנו.

במדריך זה אנו מתמקדים במערכת אחזור: מודל החוזה מערך סרטים מהקטלוג שהמשתמש צפוי לצפות בו. לעתים קרובות, נתונים מרומזים שימושיים יותר כאן, ולכן אנו מתייחסים למוביילנס כאל מערכת מרומזת. המשמעות היא שכל סרט שמשתמש צפה בו הוא דוגמה חיובית, וכל סרט שלא ראה הוא דוגמא שלילית מרומזת.

יבוא

בואו קודם נסתלק מהיבוא שלנו.

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")

מערך הדירוג מחזיר מילון של מזהה סרט, מזהה משתמש, הדירוג שהוקצה, חותמת זמן, מידע על הסרט ומידע המשתמש:

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

מערך הסרטים מכיל את מזהה הסרט, שם הסרט ונתונים לאילו ז'אנרים הוא שייך. שים לב שהז'אנרים מקודדים בתוויות שלמות.

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

בדוגמה זו אנו נתמקד בנתוני הדירוג. מדריכים אחרים חוקרים כיצד להשתמש בנתוני המידע על הסרט וכן לשיפור איכות הדגם.

אנו שומרים רק את שדות 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)

בואו ונבין גם מזהי משתמש ושמות סרטים ייחודיים הנמצאים בנתונים.

זה חשוב מכיוון שאנחנו צריכים להיות מסוגלים למפות את הערכים הגולמיים של התכונות הקטגוריות שלנו להטמעת וקטורים במודלים שלנו. לשם כך אנו זקוקים לאוצר מילים הממפה ערך של תכונה גולמית למספר שלם בטווח רציף: הדבר מאפשר לנו לחפש את ההטבעות המתאימות בטבלאות ההטבעה שלנו.

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)

הטמעת מודל

הבחירה בארכיטקטורה של המודל שלנו היא חלק מרכזי בדוגמנות.

מכיוון שאנו בונים מודל אחזור של שני מגדלים, אנו יכולים לבנות כל מגדל בנפרד ואז לשלב אותם במודל הסופי.

מגדל השאילתות

נתחיל ממגדל השאילתות.

הצעד הראשון הוא להחליט על ממדי השאילתה ונציגויות המועמדים:

embedding_dimension = 32

ערכים גבוהים יותר יתאימו למודלים שעשויים להיות מדויקים יותר, אך יהיו איטיים יותר להתאמה ונוטים יותר להתאמת יתר.

השנייה היא הגדרת המודל עצמו. כאן, נשתמש בשכבות עיבוד מקדי של Keras כדי להמיר תחילה את מזהי המשתמשים למספרים שלמים, ולאחר מכן להמיר אותם לשביעות משתמשים באמצעות שכבת Embedding . שים לב שאנחנו משתמשים ברשימת מזהי המשתמש הייחודיים שחשבנו קודם כאוצר מילים:

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

מודל פשוט כזה תואם במדויק לגישה של פקטוריזציה מטריקס קלאסית. בעוד הגדרת תת מחלקה של tf.keras.Model עבור מודל פשוט זה יכול להיות מוגזם, נוכל להחיל אותה בקלות מודל מורכב באופן שרירותי באמצעות רכיבים סטנדרטיים Keras, כל עוד אנו להחזיר embedding_dimension פלט -wide בסוף.

מגדל המועמד

אנחנו יכולים לעשות את אותו הדבר עם מגדל המועמדים.

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

מדדים

בנתוני האימונים שלנו יש לנו זוגות חיוביים (משתמשים, סרטים). כדי להבין עד כמה המודל שלנו טוב, עלינו להשוות את ציון הזיקה שהמודל מחשב עבור זוג זה לציונים של כל שאר המועמדים האפשריים: אם הציון לזוג החיובי גבוה יותר מאשר לכל המועמדים האחרים, המודל שלנו מדויק ביותר.

לשם כך נוכל להשתמש בערך tfrs.metrics.FactorizedTopK . למדד טיעון נדרש אחד: מערך המועמדים המשמש כשליליות מרומזות להערכה.

במקרה שלנו, זה מערך movies , שהוסב להטבעות באמצעות מודל הסרט שלנו:

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

הֶפסֵד

המרכיב הבא הוא ההפסד ששימש להכשרת המודל שלנו. ל- TFRS מספר שכבות אובדן ומשימות כדי להקל על כך.

במקרה זה, נשתמש באובייקט המשימות Retrieval : עטיפת נוחות שמאגדת יחד את פונקציית האובדן וחישוב המטרי:

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

המשימה עצמה היא שכבת קרס שלוקחת את השאילתה והטבעות המועמדים כטיעונים ומחזירה את ההפסד המחושב: נשתמש בזה כדי ליישם את לולאת האימון של המודל.

הדגם המלא

כעת נוכל להרכיב את הכל למודל. 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 הבסיס tfrs.Model היא מחלקת נוחות פשוטה: היא מאפשרת לנו לחשב הפסדי אימון וגם מבחני מבחן באותה שיטה.

מתחת למכסה המנוע, זה עדיין מודל רגיל של קרס. אתה יכול להשיג את אותה פונקציונליות ידי בירושה מן 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 על שימוש tfrs.Model הבסיס tfrs.Model כדי לשמור על ההתמקדות שלנו בדוגמנות tfrs.Model חלק 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 [==============================] - 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>

ככל שהמודל מתאמן, ההפסד יורד ומתעדכן מערך מדדי אחזור מהשורה הראשונה. אלה אומרים לנו אם החיובי האמיתי נמצא בפריטים שנאספו מה- top-up מכל מערך המועמדים. לדוגמא, מדד דיוק קטגורי מוביל בחמישיה של 0.2 יגיד לנו שבממוצע, החיובי האמיתי נמצא בחמשת הפריטים הראשונים שנאספו 20% מהמקרים.

שים לב שבדוגמה זו אנו מעריכים את המדדים במהלך האימון וכן את ההערכה. מכיוון שהדבר יכול להיות איטי למדי עם קבוצות מועמדים גדולות, זה יכול להיות זהיר לבטל חישוב מדד באימונים, ולהפעיל אותו רק בהערכה.

לבסוף, אנו יכולים להעריך את המודל שלנו על ערכת הבדיקה:

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}

ביצועי ערכת המבחנים גרועים בהרבה מביצועי האימון. זה נובע משני גורמים:

  1. המודל שלנו עשוי להפיק ביצועים טובים יותר על הנתונים שהוא ראה, פשוט משום שהוא יכול לשנן אותם. תופעת התאמת יתר זו חזקה במיוחד כאשר לדגמים יש פרמטרים רבים. זה יכול להיות מתווך על ידי רגולציה של מודל ושימוש בתכונות משתמש וסרטים המסייעות למודל להכליל טוב יותר את הנתונים שלא נראים.
  2. הדגם ממליץ מחדש על כמה מהסרטים שכבר נצפו של המשתמשים. שעונים חיוביים ידועים אלה יכולים לצופף סרטי בדיקה מתוך המלצות K מובילות.

ניתן להתמודד עם התופעה השנייה על ידי אי הכללת סרטים שנראו בעבר מהמלצות הבדיקה. גישה זו נפוצה יחסית בספרות מערכות הממליצים, אך איננו עוקבים אחריה במדריכים אלה. אם לא חשוב להמליץ ​​על שעונים קודמים, עלינו לצפות ממודלים שצוינו כראוי שילמדו התנהגות זו באופן אוטומטי מהיסטוריית המשתמשים מהעבר ומהמידע ההקשר. בנוסף, לעתים קרובות מתאים להמליץ ​​על אותו פריט מספר רב של פעמים (נניח, סדרת טלוויזיה ירוקת עד או פריט שנרכש באופן קבוע).

להכין תחזיות

עכשיו כשיש לנו מודל, נרצה להיות מסוגלים לחזות. אנו יכולים להשתמש בשכבת 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(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)']

כמובן, שכבת BruteForce הולכת להיות איטית מדי לשרת מודל עם מועמדים אפשריים רבים. הסעיפים הבאים מראים כיצד לזרז זאת באמצעות אינדקס אחזור משוער.

הגשת דוגמניות

לאחר הכשרת המודל, אנו זקוקים לדרך לפרוס אותו.

במודל אחזור של שני מגדלים, ההגשה כוללת שני מרכיבים:

  • מודל שאילתת הגשה, לוקח תכונות של השאילתה והופך אותם להטמעת שאילתה, ו
  • מודל מועמד משרת. לרוב זה לובש צורה של אינדקס שכנים קרוב ביותר (ANN) המאפשר בדיקה מהירה של מועמדים בתגובה לשאילתה שהופקה על ידי מודל השאילתה.

ב- TFRS ניתן לארוז את שני הרכיבים לדגם אחד לייצוא, מה שמקנה לנו דגם שלוקח את מזהה המשתמש הגולמי ומחזיר את הכותרות של הסרטים המובילים עבור אותו משתמש. זה נעשה באמצעות ייצוא המודל לפורמט SavedModel , המאפשר הגשה באמצעות הגשת TensorFlow .

כדי לפרוס מודל כזה, אנו פשוט מייצאים את שכבת BruteForce שיצרנו לעיל:

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

אנו יכולים גם לייצא אינדקס אחזור משוער כדי להאיץ את התחזיות. זה יאפשר להעלות ביעילות המלצות ממערכות של עשרות מיליוני מועמדים.

לשם כך אנו יכולים להשתמש בחבילת scann . זוהי תלות אופציונלית של TFRS, והתקנו אותה בנפרד בתחילת הדרכה זו על ידי קריאת !pip install -q scann .

לאחר ההתקנה נוכל להשתמש בשכבת TFRS ScaNN :

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>

שכבה זו תבצע בדיקות משוערות : הדבר הופך את האחזור למעט פחות מדויק, אך סדרי גודל מהירים יותר בקבוצות מועמדים גדולות.

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

למידע נוסף על שימוש וכוונון של דגמי אחזור מקורבים מהירים, עיין במדריך ההגשה היעיל שלנו.

הצעדים הבאים

זה מסכם את מדריך האחזור.

להרחבה על המובא כאן, עיין ב:

  1. לימוד מודלים מרובי משימות: אופטימיזציה משותפת לדירוגים וקליקים.
  2. שימוש במטא נתונים של סרטים: בניית מודל סרט מורכב יותר להקל על התחלה קרה.