<br />

|---|---|---|---|
| [![](https://www.tensorflow.org/images/tf_logo_32px.png)View on TensorFlow.org](https://www.tensorflow.org/recommenders/quickstart) | [![](https://www.tensorflow.org/images/colab_logo_32px.png)Run in Google Colab](https://colab.research.google.com/github/tensorflow/recommenders/blob/main/docs/examples/quickstart.ipynb) | [![](https://www.tensorflow.org/images/GitHub-Mark-32px.png)View source on GitHub](https://github.com/tensorflow/recommenders/blob/main/docs/examples/quickstart.ipynb) | [![](https://www.tensorflow.org/images/download_logo_32px.png)Download notebook](https://storage.googleapis.com/tensorflow_docs/recommenders/docs/examples/quickstart.ipynb) |

In this tutorial, we build a simple matrix factorization model using the [MovieLens 100K dataset](https://grouplens.org/datasets/movielens/100k/) with TFRS. We can use this model to recommend movies for a given user.

### Import TFRS

First, install and import TFRS:

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

    from typing import Dict, Text

    import numpy as np
    import tensorflow as tf

    import tensorflow_datasets as tfds
    import tensorflow_recommenders as tfrs

### Read the data

    # Ratings data.
    ratings = tfds.load('movielens/100k-ratings', split="train")
    # Features of all the available movies.
    movies = tfds.load('movielens/100k-movies', split="train")

    # Select the basic features.
    ratings = ratings.map(lambda x: {
        "movie_title": x["movie_title"],
        "user_id": x["user_id"]
    })
    movies = movies.map(lambda x: x["movie_title"])

Build vocabularies to convert user ids and movie titles into integer indices for embedding layers:

    user_ids_vocabulary = tf.keras.layers.StringLookup(mask_token=None)
    user_ids_vocabulary.adapt(ratings.map(lambda x: x["user_id"]))

    movie_titles_vocabulary = tf.keras.layers.StringLookup(mask_token=None)
    movie_titles_vocabulary.adapt(movies)

### Define a model

We can define a TFRS model by inheriting from [`tfrs.Model`](https://www.tensorflow.org/recommenders/api_docs/python/tfrs/models/Model) and implementing the `compute_loss` method:

    class MovieLensModel(tfrs.Model):
      # We derive from a custom base class to help reduce boilerplate. Under the hood,
      # these are still plain Keras Models.

      def __init__(
          self,
          user_model: tf.keras.Model,
          movie_model: tf.keras.Model,
          task: tfrs.tasks.Retrieval):
        super().__init__()

        # Set up user and movie representations.
        self.user_model = user_model
        self.movie_model = movie_model

        # Set up a retrieval task.
        self.task = task

      def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
        # Define how the loss is computed.

        user_embeddings = self.user_model(features["user_id"])
        movie_embeddings = self.movie_model(features["movie_title"])

        return self.task(user_embeddings, movie_embeddings)

Define the two models and the retrieval task.

    # Define user and movie models.
    user_model = tf.keras.Sequential([
        user_ids_vocabulary,
        tf.keras.layers.Embedding(user_ids_vocabulary.vocab_size(), 64)
    ])
    movie_model = tf.keras.Sequential([
        movie_titles_vocabulary,
        tf.keras.layers.Embedding(movie_titles_vocabulary.vocab_size(), 64)
    ])

    # Define your objectives.
    task = tfrs.tasks.Retrieval(metrics=tfrs.metrics.FactorizedTopK(
        movies.batch(128).map(movie_model)
      )
    )

```
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
```

### Fit and evaluate it.

Create the model, train it, and generate predictions:

    # Create a retrieval model.
    model = MovieLensModel(user_model, movie_model, task)
    model.compile(optimizer=tf.keras.optimizers.Adagrad(0.5))

    # Train for 3 epochs.
    model.fit(ratings.batch(4096), epochs=3)

    # Use brute-force search to set up retrieval using the trained representations.
    index = tfrs.layers.factorized_top_k.BruteForce(model.user_model)
    index.index_from_dataset(
        movies.batch(100).map(lambda title: (title, model.movie_model(title))))

    # Get some recommendations.
    _, titles = index(np.array(["42"]))
    print(f"Top 3 recommendations for user 42: {titles[0, :3]}")

```
Epoch 1/3
25/25 [==============================] - 8s 255ms/step - factorized_top_k/top_1_categorical_accuracy: 7.0000e-05 - factorized_top_k/top_5_categorical_accuracy: 0.0016 - factorized_top_k/top_10_categorical_accuracy: 0.0051 - factorized_top_k/top_50_categorical_accuracy: 0.0442 - factorized_top_k/top_100_categorical_accuracy: 0.1000 - loss: 33087.9238 - regularization_loss: 0.0000e+00 - total_loss: 33087.9238
Epoch 2/3
25/25 [==============================] - 6s 244ms/step - factorized_top_k/top_1_categorical_accuracy: 1.6000e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0045 - factorized_top_k/top_10_categorical_accuracy: 0.0145 - factorized_top_k/top_50_categorical_accuracy: 0.1054 - factorized_top_k/top_100_categorical_accuracy: 0.2106 - loss: 31014.9355 - regularization_loss: 0.0000e+00 - total_loss: 31014.9355
Epoch 3/3
25/25 [==============================] - 6s 245ms/step - factorized_top_k/top_1_categorical_accuracy: 3.8000e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0078 - factorized_top_k/top_10_categorical_accuracy: 0.0213 - factorized_top_k/top_50_categorical_accuracy: 0.1438 - factorized_top_k/top_100_categorical_accuracy: 0.2673 - loss: 30424.1900 - regularization_loss: 0.0000e+00 - total_loss: 30424.1900
Top 3 recommendations for user 42: [b'Rent-a-Kid (1995)'
 b'Land Before Time III: The Time of the Great Giving (1995) (V)'
 b'House Arrest (1996)']
```