فیلم های پیشنهادی: رتبه بندی

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

سیستم های توصیه گر دنیای واقعی اغلب از دو مرحله تشکیل شده اند:

  1. مرحله بازیابی مسئولیت انتخاب مجموعه اولیه صدها نامزد از بین همه نامزدهای احتمالی است. هدف اصلی این مدل از بین بردن کارآمد همه نامزدهایی است که کاربر به آنها علاقه ای ندارد. از آنجایی که مدل بازیابی ممکن است با میلیون ها نامزد سر و کار داشته باشد، باید از نظر محاسباتی کارآمد باشد.
  2. مرحله رتبه‌بندی خروجی‌های مدل بازیابی را می‌گیرد و آنها را برای انتخاب بهترین توصیه‌های ممکن تنظیم می‌کند. وظیفه آن محدود کردن مجموعه مواردی است که کاربر ممکن است به آنها علاقه مند باشد به لیست کوتاهی از نامزدهای احتمالی.

ما روی مرحله دوم یعنی رتبه بندی تمرکز خواهیم کرد. اگر شما در مرحله بازیابی علاقه مند، یک نگاهی به ما بازیابی آموزش.

در این آموزش، ما قصد داریم:

  1. داده های ما را دریافت کنید و آن ها را به یک مجموعه آموزشی و آزمایشی تقسیم کنید.
  2. پیاده سازی مدل رتبه بندی
  3. مناسب و ارزیابی کنید.

واردات

بیایید ابتدا واردات خود را از سر راه برداریم.

pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
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

آماده سازی مجموعه داده

ما قصد داریم تا با استفاده از داده های مشابه به عنوان بازیابی آموزش. این بار، ما همچنین رتبه‌بندی‌ها را حفظ می‌کنیم: اینها اهدافی هستند که می‌خواهیم پیش‌بینی کنیم.

ratings = tfds.load("movielens/100k-ratings", split="train")

ratings = ratings.map(lambda x: {
    "movie_title": x["movie_title"],
    "user_id": x["user_id"],
    "user_rating": x["user_rating"]
})
2021-10-02 11:04:25.388548: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected

مانند قبل، داده ها را با قرار دادن 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 = ratings.batch(1_000_000).map(lambda x: x["movie_title"])
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)))

پیاده سازی یک مدل

معماری

مدل‌های رتبه‌بندی با محدودیت‌های کارایی مشابهی با مدل‌های بازیابی مواجه نیستند، و بنابراین ما کمی آزادی بیشتری در انتخاب معماری‌هایمان داریم.

مدلی متشکل از چندین لایه متراکم روی هم، یک معماری نسبتاً رایج برای رتبه‌بندی وظایف است. می توانیم آن را به صورت زیر پیاده سازی کنیم:

class RankingModel(tf.keras.Model):

  def __init__(self):
    super().__init__()
    embedding_dimension = 32

    # Compute embeddings for users.
    self.user_embeddings = tf.keras.Sequential([
      tf.keras.layers.StringLookup(
        vocabulary=unique_user_ids, mask_token=None),
      tf.keras.layers.Embedding(len(unique_user_ids) + 1, embedding_dimension)
    ])

    # Compute embeddings for movies.
    self.movie_embeddings = 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)
    ])

    # Compute predictions.
    self.ratings = tf.keras.Sequential([
      # Learn multiple dense layers.
      tf.keras.layers.Dense(256, activation="relu"),
      tf.keras.layers.Dense(64, activation="relu"),
      # Make rating predictions in the final layer.
      tf.keras.layers.Dense(1)
  ])

  def call(self, inputs):

    user_id, movie_title = inputs

    user_embedding = self.user_embeddings(user_id)
    movie_embedding = self.movie_embeddings(movie_title)

    return self.ratings(tf.concat([user_embedding, movie_embedding], axis=1))

این مدل شناسه‌های کاربر و عناوین فیلم را می‌گیرد و رتبه‌بندی پیش‌بینی‌شده را خروجی می‌دهد:

RankingModel()((["42"], ["One Flew Over the Cuckoo's Nest (1975)"]))
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ['42']
Consider rewriting this model with the Functional API.
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ['42']
Consider rewriting this model with the Functional API.
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ["One Flew Over the Cuckoo's Nest (1975)"]
Consider rewriting this model with the Functional API.
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'list'> input: ["One Flew Over the Cuckoo's Nest (1975)"]
Consider rewriting this model with the Functional API.
<tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.03740937]], dtype=float32)>

ضرر و معیارها

مؤلفه بعدی ضرری است که برای آموزش مدل ما استفاده می شود. TFRS چندین لایه از دست دادن و وظایف برای آسان کردن این کار دارد.

در این مثال، ما استفاده از را Ranking لفاف بسته بندی راحتی که با هم بسته نرم افزاری تابع زیان و محاسبات متریک: شی کار.

ما آن را با هم استفاده کنید با MeanSquaredError به منظور پیش بینی در رتبه بندی از دست دادن Keras.

task = tfrs.tasks.Ranking(
  loss = tf.keras.losses.MeanSquaredError(),
  metrics=[tf.keras.metrics.RootMeanSquaredError()]
)

وظیفه خود یک لایه Keras است که true و predicted را به عنوان آرگومان می گیرد و ضرر محاسبه شده را برمی گرداند. ما از آن برای پیاده سازی حلقه آموزشی مدل استفاده خواهیم کرد.

مدل کامل

اکنون می‌توانیم همه آن‌ها را در یک مدل قرار دهیم. TFRS در معرض یک کلاس مدل پایه ( tfrs.models.Model ) که ساده مدل های ساختمان های: همه ما نیاز به انجام است به راه اندازی اجزای سازنده در __init__ روش و پیاده سازی compute_loss روش، مصرف در ویژگی های خام و بازگرداندن مقداری از دست دادن .

سپس مدل پایه از ایجاد حلقه آموزشی مناسب متناسب با مدل ما مراقبت خواهد کرد.

class MovielensModel(tfrs.models.Model):

  def __init__(self):
    super().__init__()
    self.ranking_model: tf.keras.Model = RankingModel()
    self.task: tf.keras.layers.Layer = tfrs.tasks.Ranking(
      loss = tf.keras.losses.MeanSquaredError(),
      metrics=[tf.keras.metrics.RootMeanSquaredError()]
    )

  def call(self, features: Dict[str, tf.Tensor]) -> tf.Tensor:
    return self.ranking_model(
        (features["user_id"], features["movie_title"]))

  def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
    labels = features.pop("user_rating")

    rating_predictions = self(features)

    # The task computes the loss and the metrics.
    return self.task(labels=labels, predictions=rating_predictions)

تناسب و ارزیابی

پس از تعریف مدل، می‌توانیم از روش‌های استاندارد برازش و ارزیابی کراس برای برازش و ارزیابی مدل استفاده کنیم.

بیایید ابتدا مدل را نمونه سازی کنیم.

model = MovielensModel()
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 [==============================] - 2s 26ms/step - root_mean_squared_error: 2.1718 - loss: 4.3303 - regularization_loss: 0.0000e+00 - total_loss: 4.3303
Epoch 2/3
10/10 [==============================] - 0s 8ms/step - root_mean_squared_error: 1.1227 - loss: 1.2602 - regularization_loss: 0.0000e+00 - total_loss: 1.2602
Epoch 3/3
10/10 [==============================] - 0s 8ms/step - root_mean_squared_error: 1.1162 - loss: 1.2456 - regularization_loss: 0.0000e+00 - total_loss: 1.2456
<keras.callbacks.History at 0x7f28389eaa90>

همانطور که مدل آموزش می بیند، ضرر در حال کاهش است و متریک RMSE در حال بهبود است.

در نهایت، می‌توانیم مدل خود را در مجموعه آزمایشی ارزیابی کنیم:

model.evaluate(cached_test, return_dict=True)
5/5 [==============================] - 2s 14ms/step - root_mean_squared_error: 1.1108 - loss: 1.2287 - regularization_loss: 0.0000e+00 - total_loss: 1.2287
{'root_mean_squared_error': 1.1108061075210571,
 'loss': 1.2062578201293945,
 'regularization_loss': 0,
 'total_loss': 1.2062578201293945}

هرچه متریک RMSE کمتر باشد، مدل ما در پیش‌بینی رتبه‌بندی دقیق‌تر است.

تست مدل رتبه بندی

اکنون می‌توانیم مدل رتبه‌بندی را با محاسبه پیش‌بینی‌های مجموعه‌ای از فیلم‌ها آزمایش کنیم و سپس این فیلم‌ها را بر اساس پیش‌بینی‌ها رتبه‌بندی کنیم:

test_ratings = {}
test_movie_titles = ["M*A*S*H (1970)", "Dances with Wolves (1990)", "Speed (1994)"]
for movie_title in test_movie_titles:
  test_ratings[movie_title] = model({
      "user_id": np.array(["42"]),
      "movie_title": np.array([movie_title])
  })

print("Ratings:")
for title, score in sorted(test_ratings.items(), key=lambda x: x[1], reverse=True):
  print(f"{title}: {score}")
Ratings:
M*A*S*H (1970): [[3.584712]]
Dances with Wolves (1990): [[3.551556]]
Speed (1994): [[3.5215874]]

صادرات برای خدمت

مدل را می توان به راحتی برای خدمت صادر کرد:

tf.saved_model.save(model, "export")
2021-10-02 11:04:38.235611: 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 ranking_1_layer_call_and_return_conditional_losses, ranking_1_layer_call_fn, ranking_1_layer_call_fn, ranking_1_layer_call_and_return_conditional_losses, ranking_1_layer_call_and_return_conditional_losses while saving (showing 5 of 5). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: export/assets
INFO:tensorflow:Assets written to: export/assets

اکنون می‌توانیم آن را دوباره بارگذاری کنیم و پیش‌بینی‌ها را انجام دهیم:

loaded = tf.saved_model.load("export")

loaded({"user_id": np.array(["42"]), "movie_title": ["Speed (1994)"]}).numpy()
array([[3.5215874]], dtype=float32)

مراحل بعدی

مدل بالا شروع مناسبی برای ایجاد یک سیستم رتبه بندی به ما می دهد.

البته ایجاد یک سیستم رتبه بندی عملی نیاز به تلاش بسیار بیشتری دارد.

در بیشتر موارد، یک مدل رتبه‌بندی را می‌توان با استفاده از ویژگی‌های بیشتر به جای شناسه‌های کاربر و نامزد، به طور قابل ملاحظه‌ای بهبود بخشید. تا ببینید که چگونه به انجام این کار، یک نگاه در سمت ویژگی های آموزش.

درک دقیق اهدافی که ارزش بهینه سازی دارند نیز ضروری است. برای شروع بر روی ساختن یک پیشنهاد است که بهینه سازی اهداف چندگانه، یک نگاهی به ما چند کاره آموزش.