फिल्मों की सिफारिश करना: रैंकिंग

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

कार्य स्वयं एक केरस परत है जो तर्क के रूप में सत्य और भविष्यवाणी करता है, और गणना की गई हानि देता है। हम इसका उपयोग मॉडल के प्रशिक्षण लूप को लागू करने के लिए करेंगे।

पूरा मॉडल

अब हम इन सबको मिलाकर एक मॉडल बना सकते हैं। TFRS एक बेस मॉडल वर्ग (उजागर करता tfrs.models.Model ) जो bulding मॉडल को सुव्यवस्थित: सब हम क्या करने की जरूरत में घटकों की स्थापना के लिए है __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>

मॉडल ट्रेन के रूप में, नुकसान कम हो रहा है और आरएमएसई मीट्रिक में सुधार हो रहा है।

अंत में, हम परीक्षण सेट पर अपने मॉडल का मूल्यांकन कर सकते हैं:

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}

आरएमएसई मीट्रिक जितना कम होगा, हमारा मॉडल रेटिंग की भविष्यवाणी करने में उतना ही सटीक होगा।

रैंकिंग मॉडल का परीक्षण

अब हम फिल्मों के एक सेट के लिए भविष्यवाणियों की गणना करके रैंकिंग मॉडल का परीक्षण कर सकते हैं और फिर इन फिल्मों को भविष्यवाणियों के आधार पर रैंक कर सकते हैं:

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)

अगले कदम

ऊपर दिया गया मॉडल हमें एक रैंकिंग प्रणाली बनाने की दिशा में एक अच्छी शुरुआत देता है।

बेशक, एक व्यावहारिक रैंकिंग प्रणाली बनाने के लिए बहुत अधिक प्रयास की आवश्यकता होती है।

ज्यादातर मामलों में, केवल उपयोगकर्ता और उम्मीदवार पहचानकर्ताओं के बजाय अधिक सुविधाओं का उपयोग करके रैंकिंग मॉडल में काफी सुधार किया जा सकता है। कि कैसे करना है देखने के लिए, पर एक नजर है सुविधाओं पक्ष ट्यूटोरियल।

अनुकूलन योग्य उद्देश्यों की सावधानीपूर्वक समझ भी आवश्यक है। एक recommender कि कई उद्देश्यों का अनुकूलन के निर्माण पर आरंभ करने के लिए, हमारे पर एक नजर है बहु-कार्य ट्यूटोरियल।