In this lecture we are going to look at how to build a recommender system using deep learning.
This lecture is going to walk you through a prepared code lab notebook.
Although a very good exercise which I always recommend is once you know how this is done to try and
recreate it yourself with as few references as possible.
As usual you can look at the title of the notebook to determine what notebook we are currently looking
at.
So none of the imports are too surprising so let's start with downloading the data.
This data is hosted at group lens dot org and we'll be looking at the famous movie lens 20 million dataset.
Note that there are multiple versions of the movie lens dataset and most tutorials and courses use the
version of the dataset which only has 100000 ratings.
But that's kind of lame so we're going to demonstrate that we can do better.
Now since this is a zip file we're going to unzip it
so you'll see that it comes with quite a few files.
I'd recommend looking at these since I've already done the hard work for you by figuring out which is
which.
But you want to do that yourself at some point since you know that's part of being a data scientist.
So next we do an Alice to see what we now have in our working directory.
Next I load in the data using panties and of course the data is a CSP so the first column is the user
I.D..
The second column is the movie Eddie.
The third column is the rating and the fourth column is the timestamp.
So if you wanted to make some kind of really complex recommender system that maybe recommends the right
thing at the right time you could take into account the timestamp or the order of the events as they
occur.
But that's not really a thing that people usually teach in recommender systems.
So we're not going to discuss it.
Next we recognize that although the dataset already uses integers for the use righties and movie ideas
they might not be in the format that we want.
Remember what these integers are eventually used for their use to index and embedding so user I.D. 0
will index the first row is user right one will index the second row and so on.
So think of a really not ideal scenario.
Let's say you have one hundred users but these one hundred users have the ideas 1 million 1 million
and 1 1 million and 2 and so forth.
Well what happens is that since each IP must be an index into an array that array must have size 1 million
and one hundred that's about 1 million rows of wasted space space that you won't be using.
Therefore you would like your user I.D. to be numbered from zero up to and minus one.
The thing is we can't just trust that the data is formatted in this way.
In fact I would recommend checking to verify this for yourself as an exercise.
In any case that's what this next block of code does.
So I've commented out some code that you might use if you wanted to implement an index assignment from
first principles using the apply function.
Of course if you read the documentation for long enough eventually you'd stumble upon this useful thing
where you can just cast the entire column to be a PD dot categorical object which automatically assigns
integer ideas starting from zero.
Then we can grab those ideas by calling dot cat dot codes.
So next it's the same story for the movie ideas.
Again as an exercise you want to verify that the original ideas were or were not in the format.
We would like them
next since our data is currently in a data frame.
We're going to split them into individual num pie arrays we can do that by calling dot values on the
relevant columns.
Also we're going to center the ratings data which is part of the standardization process.
The reason I'm not also dividing by the standard deviation is because in recommender systems literature
results are often reported in terms of the root means squared error.
The RNC of course this metric is reported on the scale of the original ratings.
So if we change the scale our results won't be directly comparable to other results.
One alternative is just scale your predictions and targets back before calculating the metric.
But I leave that up to you.
Next we're going to find N the number of users and m the number of movies.
We'll also set d of the embedding dimension.
The next step is to define our custom neural network for recommenders in the constructor.
We'll take in the number of users the number of movies the embedding dimension and the number of hitting
units as an exercise.
You could extend this to have multiple hidden layers inside the constructor.
We create all the necessary modules we have to embedding and two linear layers
in the forward function.
We define how to get a prediction given some input user and some input movie.
As usual it's important and useful to pay attention to the shapes the UI variable starts out as a num
sample's length array as does the M variable.
The first step is to pass the user I.D. in the movie ideas into their respective embedding.
This gives us two things of size num samples by D next week in cabinet these along the 1 axis and we
get back a thing of size and num samples by 2.
After this it's just a regular neural net where we pass it through a dense layer to a real you and then
a final dense layer
next we create a device object.
Next we instantiate our model and move it to the jeep.
You X. We create the laws an atomizer and we shuffle the data.
This is so that we effectively randomize the train to split speed convert the data to torch tensor is
next we create tensor data set objects for both the train set and the test set.
We defined the train set to be the first 80 percent of the shuffled data and the test set to be the
last 20 percent.
Next we create data loader objects from our data sets
after this.
Things are more or less the same as usual.
We create our training function which by the way has to move the data to the jeep.
You manually now previously the special vision and text libraries were doing that for us.
Next we run the training function.
You'll notice that I've got this special P run magic command.
This is a profiler that tells us things like how much time we spent any function.
So why did I want to do this.
Well you'll notice that each epoch took quite a long time over five minutes.
I thought this was very strange.
And so if you look at the outputs from the profiler you can see that a majority of the timespan isn't
coming from our for loops or the model since our model is quite small.
It's actually coming from the PI torch data set functions.
So while you might assume that if you're using pi torch you should use pi torches data loaders.
Maybe that's not always the best idea.
Sure you could try to figure out if maybe there's some arguments we could have set to improve the performance
or something like that but for a basic data set like this you shouldn't have to it should just work
which is the whole point of built in functions in the first place.
In any case we'll discuss that more in the next lecture
so the final step is to plug the lost per iteration
and that shows us that the model has converged.
Although you should pay attention to the final MSE here because we are going to improve this value in
the next lecture.