Okay. So, you've seen how content-based filtering can be used to generate movie recommendations for a single user. We'd like to scale this technique so you can provide recommendations for multiple users at a time. Here we have a user-movie rating matrix, similar to the user-item interaction matrix we saw in the previous module. Each row corresponds to a user and each column represents a movie in our database. The value in row I and column J indicates the rating from one to 10 that user I gave movie J. Let's walk through the process we've previously implemented to see how this would look in theory and how you would implement this in TensorFlow. Here is our user-item rating matrix from earlier next to our item-feature matrix. Remember, the item-feature matrix is a K-hot encoding of the features we are using to describe our movies. Each row corresponds to a single movie, and a one indicates that the movie fits that genre. We can initialize these as constants in TensorFlow by creating constant tensor values for our movies and for our movie features. To do that, we use tf.constant to rank two tensors with the values for the user-item rating matrix and the movie features from before hard-coded. We want to scale the movie-feature matrix by their ratings given by each user. This will give us a weighted feature matrix for each user. For the first user, we will get this weighted feature matrix. We repeat this process for the second user, and the third, and so on. Once we have this collection of matrices, we can stack them together using tf.stack to get a complete weighted user feature tensor. The previous operations can be done in TensorFlow in the following way. We first build a list of the weighted feature matrices for each user, then use tf.stack applied to this list, setting the stack axis to be zero. What is the shape of the tensor resulting from stacking together all of the weighted feature matrices? The resulting tensor is rank three. So, we can immediately discard option A. Because we stack the weighted feature matrices on axis zero, the shape of this tensor is number of users by number of movies by number of features, or in this case four by five by five. To find the user feature tensor, we sum across the feature columns just as before, and individually normalize each of the resulting vectors. To normalize a user's movies features tensor, we first sum each column using tf.reduce_sum and setting the axis equal to one. The resulting tensor would then be ranked two, where each row represents the sum of the feature values for each user. Next, we find the total for each user, again using tf.reduce_sum with axis set to one. The normalization is then just the result of dividing the feature sum by the feature totals for each user. In the end, we stack the resulting tensors together to get the final users features tensor. This results in a user feature tensor, where each row corresponds to a specific user feature vector. To find the inferred movie rankings for our users, we compute the dot product between each user feature vector and each movie feature vector. In short, we're seeing how similar each user is with respect to each movie as measured across these five feature dimensions. For example, for our first user, the dot product with Star Wars gives 0.6. The dot product with the Dark Knight is 0.5. For Shrek, we get 0.4 and so on for the fourth movie, and our last movie. We do the same thing for user two, for user three, and finally user four. To achieve this in TensorFlow, we can use the map function. The TensorFlow map function is similar to map function in NumPy. It repeatedly apply some callable function on a sequence of elements from first to last. Here, we represent that function with Lambda. It's simply the dot product of each user feature vector with each movie feature vector. So, the variable user ratings holds the list of the resulting movie ratings for each user and each movie. We stack them together to get a tensor of all the users and their movie ratings. Once we had the user-movie ranking matrix, we can compare it with the original user-movie matrix to see which movies to recommend to wish user. Because our users have already seen and rated some of our movies, we want to mask the ranking for previously rated movies and focus only on unrated or unseen movies for each user. Which TensorFlow operation could be used to mask the previously rated movies in our user-movie ranking matrix? So, we only focus on previously unrated movies when providing recommendations. Look to the TensorFlow documentation to see which operation you could use here. That's right. Tf.where operates like NumPy's where operation. It returns elements based on the value of a condition. What condition will be used to mask out movies that do not have a rating? Think about it. We'll see the answer on the next slide. As we saw in the quiz, we can accomplish this with tf.where. Here, the condition variable is a Boolean, and tf.where will return either the tensor x or y, depending on the value of the condition. By setting a condition to be where the user-item interaction matrix does not have any values, we can return only those rankings for previously unrated movies. This results in this user ranking matrix. Finally, we can use the similarity rankings we've computed here to suggest new movies for each user. For example, for user one, the Incredibles has a higher similarity score than Blue, and so our new movie recommendation list for user one looks like this. We can also do the same thing for all the other users. Before we move on, let's take a closer look at our second user. She's a rating of zero for the Dark Knight. Why is that? If we look at the original user-movie rating matrix and compare it with the movie feature matrix, we can see why. Because this user has not rated anything containing action or sci-fi, and the features of the Dark Knight are solely action and sci-fi, our recommender system will infer a rating of zero for that movie. This actually highlights one of the drawbacks of content-based recommender systems. It can be difficult to expand the interest of a user. If the user hasn't rated movies within one of our predefined features, our recommender won't suggest new movies in that genre. In this sense, content-based recommenders aren't good at expanding the interest of users to new domains.