सूचीवार रैंकिंग

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

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

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

अलग-अलग क्वेरी/आइटम जोड़े पर मॉडल की भविष्यवाणियों को अनुकूलित करने के बजाय, हम समग्र रूप से सूची की मॉडल की रैंकिंग को अनुकूलित कर सकते हैं। इस विधि रैंकिंग listwise कहा जाता है।

इस ट्यूटोरियल में, हम सूची-वार रैंकिंग मॉडल बनाने के लिए TensorFlow Recommenders का उपयोग करेंगे। ऐसा करने के लिए, हम रैंकिंग नुकसान और मीट्रिक द्वारा प्रदान का उपयोग करेगा TensorFlow रैंकिंग , एक TensorFlow पैकेज पर केंद्रित पद के लिए सीखने

प्रारंभिक

यदि TensorFlow रैंकिंग अपने क्रम पर्यावरण में उपलब्ध नहीं है, तो आप इसे का उपयोग कर स्थापित कर सकते हैं pip :

pip install -q tensorflow-recommenders
pip install -q --upgrade tensorflow-datasets
pip install -q tensorflow-ranking

फिर हम सभी आवश्यक पैकेज आयात कर सकते हैं:

import pprint

import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/pkg_resources/__init__.py:119: PkgResourcesDeprecationWarning: 0.18ubuntu0.18.04.1 is an invalid version and will not be supported in a future release
  PkgResourcesDeprecationWarning,
import tensorflow_ranking as tfr
import tensorflow_recommenders as tfrs
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_addons/utils/ensure_tf_install.py:67: UserWarning: Tensorflow Addons supports using Python ops for all Tensorflow versions above or equal to 2.4.0 and strictly below 2.7.0 (nightly versions are not supported). 
 The versions of TensorFlow you are currently using is 2.7.0 and is not supported. 
Some things might work, some things might not.
If you were to encounter a bug, do not file an issue.
If you want to make sure you're using a tested and supported configuration, either change the TensorFlow version or the TensorFlow Addons's version. 
You can find the compatibility matrix in TensorFlow Addon's readme:
https://github.com/tensorflow/addons
  UserWarning,

हम MovieLens 100K डेटासेट का उपयोग करना जारी रखेंगे। पहले की तरह, हम डेटासेट लोड करते हैं और इस ट्यूटोरियल के लिए केवल यूजर आईडी, मूवी टाइटल और यूजर रेटिंग फीचर रखते हैं। हम अपनी शब्दावली तैयार करने के लिए कुछ हाउसकीपिंग भी करते हैं।

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

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

unique_movie_titles = np.unique(np.concatenate(list(movies.batch(1000))))
unique_user_ids = np.unique(np.concatenate(list(ratings.batch(1_000).map(
    lambda x: x["user_id"]))))

डेटा प्रीप्रोसेसिंग

हालाँकि, हम सीधे सूची अनुकूलन के लिए MovieLens डेटासेट का उपयोग नहीं कर सकते। सूचीवार अनुकूलन करने के लिए, हमें प्रत्येक उपयोगकर्ता द्वारा रेट की गई फिल्मों की एक सूची तक पहुंच की आवश्यकता है, लेकिन MovieLens 100K डेटासेट में प्रत्येक उदाहरण में केवल एक फिल्म की रेटिंग होती है।

इसे दूर करने के लिए हम डेटासेट को रूपांतरित करते हैं ताकि प्रत्येक उदाहरण में एक यूजर आईडी और उस उपयोगकर्ता द्वारा रेट की गई फिल्मों की एक सूची हो। सूची में कुछ फिल्मों को दूसरों की तुलना में उच्च स्थान दिया जाएगा; हमारे मॉडल का लक्ष्य इस क्रम से मेल खाने वाली भविष्यवाणियां करना होगा।

ऐसा करने के लिए, हम का उपयोग tfrs.examples.movielens.movielens_to_listwise सहायक कार्य करते हैं। यह MovieLens 100K डेटासेट लेता है और ऊपर चर्चा के अनुसार सूची उदाहरणों वाला डेटासेट बनाता है। कार्यान्वयन विवरण में पाया जा सकता स्रोत कोड

tf.random.set_seed(42)

# Split between train and tests sets, as before.
shuffled = ratings.shuffle(100_000, seed=42, reshuffle_each_iteration=False)

train = shuffled.take(80_000)
test = shuffled.skip(80_000).take(20_000)

# We sample 50 lists for each user for the training data. For each list we
# sample 5 movies from the movies the user rated.
train = tfrs.examples.movielens.sample_listwise(
    train,
    num_list_per_user=50,
    num_examples_per_list=5,
    seed=42
)
test = tfrs.examples.movielens.sample_listwise(
    test,
    num_list_per_user=1,
    num_examples_per_list=5,
    seed=42
)

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

for example in train.take(1):
  pprint.pprint(example)
{'movie_title': <tf.Tensor: shape=(5,), dtype=string, numpy=
array([b'Postman, The (1997)', b'Liar Liar (1997)', b'Contact (1997)',
       b'Welcome To Sarajevo (1997)',
       b'I Know What You Did Last Summer (1997)'], dtype=object)>,
 'user_id': <tf.Tensor: shape=(), dtype=string, numpy=b'681'>,
 'user_rating': <tf.Tensor: shape=(5,), dtype=float32, numpy=array([4., 5., 1., 4., 1.], dtype=float32)>}

मॉडल परिभाषा

हम एक ही मॉडल को तीन अलग-अलग नुकसानों के साथ प्रशिक्षित करेंगे:

  • मतलब चुकता त्रुटि,
  • जोड़ीदार काज नुकसान, और
  • एक सूचीवार ListMLE नुकसान।

ये तीन नुकसान पॉइंटवाइज, पेयरवाइज और लिस्टवाइज ऑप्टिमाइज़ेशन के अनुरूप हैं।

मॉडल हम उपयोग का मूल्यांकन करने के सामान्यीकृत संचयी लाभ (NDCG) रियायती । एनडीसीजी प्रत्येक उम्मीदवार की वास्तविक रेटिंग का भारित योग लेकर एक अनुमानित रैंकिंग को मापता है। मॉडल द्वारा कम रैंक वाली फिल्मों की रेटिंग पर अधिक छूट दी जाएगी। नतीजतन, एक अच्छा मॉडल जो उच्च-रेटेड फिल्मों को शीर्ष पर रखता है, उसका उच्च एनडीसीजी परिणाम होगा। चूंकि यह मीट्रिक प्रत्येक उम्मीदवार की रैंक की स्थिति को ध्यान में रखता है, यह एक सूचीवार मीट्रिक है।

class RankingModel(tfrs.Model):

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

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

    # Compute embeddings for movies.
    self.movie_embeddings = tf.keras.Sequential([
      tf.keras.layers.StringLookup(
        vocabulary=unique_movie_titles),
      tf.keras.layers.Embedding(len(unique_movie_titles) + 2, embedding_dimension)
    ])

    # Compute predictions.
    self.score_model = 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)
    ])

    self.task = tfrs.tasks.Ranking(
      loss=loss,
      metrics=[
        tfr.keras.metrics.NDCGMetric(name="ndcg_metric"),
        tf.keras.metrics.RootMeanSquaredError()
      ]
    )

  def call(self, features):
    # We first convert the id features into embeddings.
    # User embeddings are a [batch_size, embedding_dim] tensor.
    user_embeddings = self.user_embeddings(features["user_id"])

    # Movie embeddings are a [batch_size, num_movies_in_list, embedding_dim]
    # tensor.
    movie_embeddings = self.movie_embeddings(features["movie_title"])

    # We want to concatenate user embeddings with movie emebeddings to pass
    # them into the ranking model. To do so, we need to reshape the user
    # embeddings to match the shape of movie embeddings.
    list_length = features["movie_title"].shape[1]
    user_embedding_repeated = tf.repeat(
        tf.expand_dims(user_embeddings, 1), [list_length], axis=1)

    # Once reshaped, we concatenate and pass into the dense layers to generate
    # predictions.
    concatenated_embeddings = tf.concat(
        [user_embedding_repeated, movie_embeddings], 2)

    return self.score_model(concatenated_embeddings)

  def compute_loss(self, features, training=False):
    labels = features.pop("user_rating")

    scores = self(features)

    return self.task(
        labels=labels,
        predictions=tf.squeeze(scores, axis=-1),
    )

मॉडलों का प्रशिक्षण

अब हम तीनों मॉडलों में से प्रत्येक को प्रशिक्षित कर सकते हैं।

epochs = 30

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

माध्य चुकता त्रुटि मॉडल

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

mse_model = RankingModel(tf.keras.losses.MeanSquaredError())
mse_model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
mse_model.fit(cached_train, epochs=epochs, verbose=False)
<keras.callbacks.History at 0x7f64791a5d10>

जोड़ीदार काज नुकसान मॉडल

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

इस नुकसान की गणना अलग-अलग फिल्मों के लिए नहीं, बल्कि फिल्मों की जोड़ी के लिए की जाती है। इसलिए इस नुकसान का उपयोग करने वाला प्रशिक्षण जोड़ीदार है।

hinge_model = RankingModel(tfr.keras.losses.PairwiseHingeLoss())
hinge_model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
hinge_model.fit(cached_train, epochs=epochs, verbose=False)
<keras.callbacks.History at 0x7f647914f190>

सूचीवार मॉडल

ListMLE TensorFlow रैंकिंग व्यक्त से नुकसान की सूची अधिकतम संभावना अनुमान। ListMLE नुकसान की गणना करने के लिए, हम पहले उपयोगकर्ता रेटिंग का उपयोग इष्टतम रैंकिंग उत्पन्न करने के लिए करते हैं। इसके बाद हम अनुमानित अंकों का उपयोग करके इष्टतम रैंकिंग में प्रत्येक उम्मीदवार के नीचे किसी भी आइटम द्वारा आउट-रैंक किए जाने की संभावना की गणना करते हैं। यह मॉडल इस तरह की संभावना को कम करने की कोशिश करता है ताकि यह सुनिश्चित किया जा सके कि उच्च श्रेणी के उम्मीदवारों को निम्न श्रेणी के उम्मीदवारों द्वारा आउट-रैंक नहीं किया गया है। आप कागज की धारा 2.2 में ListMLE के विवरण के बारे में अधिक जान सकते स्थिति अवगत ListMLE: एक अनुक्रमिक सीखने की प्रक्रिया

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

listwise_model = RankingModel(tfr.keras.losses.ListMLELoss())
listwise_model.compile(optimizer=tf.keras.optimizers.Adagrad(0.1))
listwise_model.fit(cached_train, epochs=epochs, verbose=False)
<keras.callbacks.History at 0x7f647b35f350>

मॉडलों की तुलना

mse_model_result = mse_model.evaluate(cached_test, return_dict=True)
print("NDCG of the MSE Model: {:.4f}".format(mse_model_result["ndcg_metric"]))
1/1 [==============================] - 0s 405ms/step - ndcg_metric: 0.9053 - root_mean_squared_error: 0.9671 - loss: 0.9354 - regularization_loss: 0.0000e+00 - total_loss: 0.9354
NDCG of the MSE Model: 0.9053
hinge_model_result = hinge_model.evaluate(cached_test, return_dict=True)
print("NDCG of the pairwise hinge loss model: {:.4f}".format(hinge_model_result["ndcg_metric"]))
1/1 [==============================] - 0s 457ms/step - ndcg_metric: 0.9058 - root_mean_squared_error: 3.8330 - loss: 1.0180 - regularization_loss: 0.0000e+00 - total_loss: 1.0180
NDCG of the pairwise hinge loss model: 0.9058
listwise_model_result = listwise_model.evaluate(cached_test, return_dict=True)
print("NDCG of the ListMLE model: {:.4f}".format(listwise_model_result["ndcg_metric"]))
1/1 [==============================] - 0s 432ms/step - ndcg_metric: 0.9071 - root_mean_squared_error: 2.7224 - loss: 4.5401 - regularization_loss: 0.0000e+00 - total_loss: 4.5401
NDCG of the ListMLE model: 0.9071

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