Back to Index

Lesson 4: Deep Learning 2019 - NLP; Tabular data; Collaborative filtering; Embeddings


Chapters

0:0
4:18 Neural Networks
5:45 Transfer Learning
5:56 Transfer Learning in Nlp
6:44 Language Model
7:19 Engrams
8:34 Wiki Text 103 Data Set
12:2 Self Supervised Learning
15:20 Basic Process
20:29 Fine-Tuning Our Imdb Language Language Model
22:39 Create a Language Model Learner
23:43 Amount of Dropout
27:18 Create Our Classifier
34:31 Discriminative Learning Rates
35:3 Random Forest
36:41 Tabular Data
40:39 What Are the 10 % of Cases Where You Would Not Default to Neural Nets
42:42 Data Block Api
46:45 Normalization
48:14 Add Labels
52:16 Layers
53:5 Collaborative Filtering
59:14 The Cold Start Problem
67:29 Microsoft Excel
70:33 Matrix Multiplications
73:8 Loss Function
75:7 Gradient Descent Solver in Excel
81:0 Get Embedding

Transcript

Okay, welcome to lesson 4. We are going to finish our journey through these kind of key applications. We've already looked at a range of vision applications. We've looked at classification, localization, image regression. We've briefly touched on NLP. We're going to do a deeper dive into NLP transfer learning today.

We're going to then look at tabular data and we're going to look at a range of vision applications. Which are both super useful applications and then we're going to take a complete U turn. We're going to take that collaborative filtering example and dive deeply into it to understand exactly what's happening.

Mathematically exactly what's happening in the computer and we're going to use that to gradually go back in reverse order through the applications again. In order to understand exactly what's going on behind the scenes of all of those applications. Before we do, somebody on the forum was kind enough to point out that when we compared ourselves to what we think might be the state-of-the-art or was recently the state-of-the-art for Canvaard, it wasn't a fair comparison because the paper actually used a small subset of the classes and we used all of the classes.

So Jason in our study group was kind enough to rerun the experiments with the correct subset of classes from the paper and our accuracy went up to 94% compared to 91.5% in the paper. So I think that's a really cool result and a great example of how some pretty much just using the defaults nowadays can get you far beyond what was the best of a year or two ago.

Certainly the best last year when we were doing this course because we started it quite intensely. So that's really exciting. So what I wanted to start with is going back over NLP a little bit to understand really what was going on there. So first of all, a quick review.

So remember NLP is natural language processing. It's about taking text and doing something with it. And text classification is a particularly useful, kind of practically useful applications. It's what we're going to start off focusing on. Because classifying a text classifying a document can be used for anything from spam prevention to identifying fake news to finding a diagnosis through medical reports.

Finding mentions of your product in Twitter, so on and so forth. So it's pretty interesting and actually there was a great example. There was a great example during the week from one of our students who is a lawyer. And he mentioned on the forum that he had a really great results from classifying legal texts using this NLP approach.

And I thought this was a great example. So this is the poster that they presented at an academic conference this week describing the approach. And actually this series of three steps that you see here, and I'm sure you recognize this classification matrix, this series of three steps here is what we're going to start by digging into.

So we're going to start out with a movie review like this one and going to decide whether it's positive or negative sentiment about the movie. But here's the problem. We have in the training set 25,000 movie reviews. So we've got 25,000 movie reviews and for each one we have like one bit of information.

They liked it or they didn't like it. And as we're going to look into in a lot more detail today and in the current lessons, our neural networks, remember they're just a bunch of matrix multiplies and simple nonlinearities, particularly replacing negatives with zeros. Those weight matrices start out random.

And so if you start out with some random parameters and try to train those parameters to learn how to recognize positive versus negative movie reviews, you only have 20 literally 25,000 ones and zeros to actually tell you I like this one, I don't like that one. That's clearly not enough information to learn basically how to speak English, how to speak English well enough to recognize they liked this or they didn't like this.

And sometimes that can be pretty nuanced, right? The English language often, particularly with like movie reviews, people, because these are like online movie reviews in IMDB, people can often like use sarcasm, it could be really quite tricky. So for a long time, in fact until very recently, like this year, neural nets didn't do a good job at all of this kind of classification problem.

And that was why there's not enough information available. So the trick, hopefully you can all guess, it's to use transfer learning, it's always the trick. So last year in this course, I tried something crazy, which was I thought, what if I try transfer learning to demonstrate that it can work for NLP as well.

And I tried it out and it worked extraordinarily well. And so here we are a year later, and transfer learning in NLP is absolutely the hit thing now. And so I'm going to describe to you what happens. The key thing is we're going to start with the same kind of thing that we used for computer vision, a pre-trained model that's been trained to do something different to what we're doing with it.

And so for ImageNet, that was originally built as a model to predict which of a thousand categories each photo falls into. And people then fine-tuned that for all kinds of different things, as we've seen. So we're going to start with a pre-trained model that's going to do something else, not movie review classification.

We're going to start with a pre-trained model, which is called a language model. A language model has a very specific meaning in NLP, and it's this. A language model is a model that learns to predict the next word of a sentence. And to predict the next word of a sentence, you actually have to know quite a lot about English, assuming you're doing it in English, and quite a lot of world knowledge.

And by world knowledge, I'll give you an example. Here's your language model, and it's read, I'd like to eat a hot, what? Obviously, dog, right? It was a hot, what? Probably day, right? Now, previous approaches to NLP use something called n-grams, largely, which is basically saying how often do these pairs or triplets of words tend to appear next to each other?

And n-grams are terrible at this kind of thing. As you can see, there's not enough information here to decide what the next word probably is. But with a neural net, you absolutely can. So here's the nice thing. If you train a neural net to predict the next word of a sentence, then you actually have a lot of information, rather than having a single bit for every 2,000-word movie review, liked it or didn't like it, every single word you can try and predict the next word.

So in a 2,000-word movie review, there are 1,999 opportunities to predict the next word. Better still, you don't just have to look at movie reviews. Because really the hard thing isn't so much does this person like the movie or not, but how do you speak English? So you can learn how do you speak English, roughly, from some much bigger set of documents.

And so what we did was we started with Wikipedia. And Stephen Meridy and some of his colleagues built something called the Wikitext 103 dataset, which is simply a subset of most of the largest articles from Wikipedia with a little bit of preprocessing that's available for download. And so you're basically grabbing Wikipedia, and then I built a language model on all of Wikipedia.

So I've just built a neural net which would predict the next word in every significantly sized Wikipedia article. And that's a lot of information. If I remember correctly, it's something like a billion tokens. So we've got a billion separate things to predict. Every time we make a mistake on one of those predictions, the loss can get gradients from that, and we can update our weights and make them better and better until we can get pretty good at predicting the next word of Wikipedia.

Why is that useful? Because at that point I've got a model that knows probably how to complete sentences like this, and so it knows quite a lot about English and quite a lot about how the world works, what kinds of things tend to be hot in different situations, for instance.

I mean, ideally it would learn things like, in 1996, in a speech to the United Nations, the United States President Blah said, now that would be a really good language model because it would actually have to know who was the United States President in that year. So getting really good at training language models is a great way to learn a lot about, or teach a neural net, a lot about what is our world, what's in our world, how do things work in our world.

So it's a really fascinating topic, and it's actually one that philosophers have been studying for hundreds of years now. There's actually a whole theory of philosophy, which is about what can be learned from studying language alone. So it turns out, empirically, quite a lot. And so here's the interesting thing, you can start by training a language model on all of Wikipedia, and then we can make that available to all of you.

Just like a pre-trained image net model for vision, we've now made available a pre-trained wiki text model for NLP. Not because it's particularly useful of itself, predicting the next word of sentences is somewhat useful, but not normally what we want to do. But it tells us it's a model that understands a lot about language, and a lot about what language describes.

So then we can take that and we can do transfer learning to create a new language model that's specifically good at predicting the next word of movie reviews. So if we can build a language model that's good at predicting the next word of movie reviews, pre-trained with the wiki text model, then that's going to understand a lot about my favorite actor is Tom Hu.

I thought the photography was fantastic, but I wasn't really so happy about the director. It's going to learn a lot about specifically how movie reviews are written. It'll even learn things like what are the names of some popular movies. So that would then mean we can still use a huge corpus of lots of movie reviews, even if we don't know whether they're positive or negative, to learn a lot about how movie reviews are written.

So for all of this pre-training and all of this language model fine-tuning, we don't need any labels at all. It's what the researcher Yann LeCun calls self-supervised learning. In other words, it's a classic supervised model. We have labels, but the labels are not things that somebody else has created.

They're kind of built into the data set itself. So this is really, really neat. Because at this point we've now got something that's good at understanding movie reviews, and we can fine-tune that with transfer learning to do the thing we want to do, which in this case is to classify movie reviews to be positive or negative.

And so my hope was, and I tried this last year, that at that point 25,000 ones and zeros would be enough feedback to fine-tune that model. And it turned out it absolutely was. All right, Rachel, let's go with a question. Does the language model approach work for text and forums that are informal English, misspelled words or slang or short form like S6 instead of Samsung S6?

Yes, absolutely it does. Particularly if you start with your WikiText model and then fine-tune it with your, we call it a target corpus. A corpus is just a bunch of documents. It could be emails or tweets or medical reports or whatever. So you could fine-tune it so it can learn a bit about the specifics of the slang or abbreviations or whatever that didn't appear in the full corpus.

And so interestingly, this is one of the big things that people were surprised about when we did this research last year. People thought that learning from something like Wikipedia wouldn't be that helpful because it's not that representative of how people tend to write. But it turns out it's extremely helpful because there's a much bigger difference between Wikipedia and random words than there is between Wikipedia and Reddit.

So it kind of gets you 99% of the way there. So these language models themselves can be quite powerful. So for example, there was a blog post from, what do they call it, SwiftKey? SwiftKey, the folks that do the mobile phone predictive text keyboard. And they described how they kind of rewrote their underlying model to use neural nets.

So now, this was a year or two ago, now most phone keyboards seem to do this. You'll be typing away on your mobile phone and in the predictions there'll be something telling you what words you might want next. So that's a language model in your phone. Another example was the researcher Andre Kapathy, who now runs all this stuff at Tesla, back when he was a PhD student.

He created a language model of text in LaTeX documents and created these automatic generation of LaTeX documents that then became these kind of automatically generated papers. So that's pretty cute. So we're not really that interested in the output of the language model ourselves. We're just interested in it because it's helpful with this process.

So we briefly looked at the process last week, so let's just have a reminder. The basic process is we're going to start with the data in some format. So for example, we've prepared a little IMDB sample that you can use where it's in CSV file. So you can read it in with pandas and see there's negative or positive, the text of each movie review, and a boolean of is it in the validation set or the training set.

So there's an example of a movie review. And so you can just go text data bunch from CSV to grab a language model specific data bunch, and then you can create a learner from that in the usual way and fit it. You can save the data bunch, which means that the preprocessing that is done, you don't have to do it again, you can just load it.

So what goes on behind the scenes? Well, what happens behind the scenes if we now load it as a classification data bunch that's going to allow us to see the labels as well. Then as we described, it basically creates a separate unit. We call it a token for each separate part of a word.

So most of them are just four words, but sometimes if it's like an apostrophe S from its, it'll get its own token. Every bit of punctuation tends to get its own token like a comma or a full stop and so forth. And then the next thing that we do is numericalization, which is where we find what are all of the unique tokens that appear here, and we create a big list of them.

Here's the first 10 in order of frequency. And that big list of unique possible tokens is called the vocabulary. Nobody's called it vocab. And so what we then do is we replace the tokens with the ID of where is that token in the vocab. And that's numericalization. Here's the thing, though.

As you'll learn, every word in our vocab is going to require a separate row in a weight matrix in our neural net. And so to avoid that weight matrix getting too huge, we restrict the vocab to no more than by default 60,000 words. And if a word doesn't appear more than two times, we don't put it in the vocab either.

So we kind of keep the vocab to a reasonable size in that way. And so when you see these XXUNK, that's an unknown token. So when you see those unknown tokens, it just means this was something that was not a common enough word to appear in our vocab. OK, so there is the numericalized version.

We also have a couple of other special tokens like XX field. This is a special thing where if you've got like title, summary, abstract, body, like separate parts of a document, each one will get a separate field, so they all get numbered. Also, you'll find if there's something in all caps, it gets lowercase and a token called XX cap will get added to it.

Personally, I more often use the data block API because there's less to remember about exactly what data bunch to use and what parameters and so forth, and it can be a bit more flexible. So another approach to doing this is to just decide what kind of list you're creating.

So what's your independent variable? So in this case, my independent variable is text. What is it coming from? A CSV. How do you want to split it into validation versus training? So in this case, column number two is the validation flag. How do you want to label it with positive or negative sentiment, for example?

So column zero had that and then turn that into a data bunch. That's going to do the same thing. So now let's grab the whole dataset which has 25,000 reviews in training, 25,000 reviews in validation, and then 50,000 what they call unsupervised movie reviews. So 50,000 movie reviews that haven't been scored at all.

So there it is, positive, negative, unsupervised. So we're going to start, as we described, with the language model. Now the good news is we don't have to train the Wikitext 103 language model. Not that it's difficult. You can use exactly the same steps that you see here. Just download the Wikitext 103 corpus and run the same code.

But it takes two or three days on a decent GPU, so not much point you're doing it. You may as well start with hours. Even if you've got a big corpus of medical documents or legal documents, you should still start with Wikitext 103. There's just no reason to start with random weights.

It's always good to use transfer learning if you can. So we're going to start then at this point, which is fine-tuning our IMDB language model. So we can say, OK, it's a list of text files. And the full IMDB actually is not in a CSV. Each document is a separate text file.

So that's why we use a different constructor for our independent variable, text files list. Say where it is. And in this case we have to make sure we just don't include the train and test folders. And we randomly split it by 0.1. Now this is interesting, 10%. Why are we randomly splitting it by 10% rather than using the predefined train and test they gave us?

This is one of the cool things about transfer learning. Even though our test set or our validation set has to be held aside, it's actually only the labels that we have to keep aside. So we're not allowed to use the labels in the test set. So if you think about something like a Kaggle competition, you certainly can't use the labels because they don't even give them to you.

But you can certainly use the independent variables. So in this case you can absolutely use the text that is in the test set to train your language model. So this is a good trick, right? It's actually when you do the language model, concatenate the training and test set together and then just split out a smaller validation set.

So you've got more data to train your language model. So that's a little trick. And so if you're doing NLP stuff on Kaggle, for example, or you've just got a smaller subset of labeled data, make sure that you use all of the text you have to train your language model because there's no reason not to.

How are we going to label it? Well, remember a language model kind of has its own labels. So the text itself is labeled. So label for language model does that for us. And create a data bunch. And save it. And that takes a few minutes to tokenize and numericalize.

So since it takes a few minutes, we save it. Later on, you can just load it. No need to run that again. So here's what it looks like. And at this point, things are going to look very familiar. We create a learner. But instead of creating a CNN learner, we're going to create a language model learner.

So behind the scenes, this is actually not going to create a CNN, a convolutional neural network. It's going to create an RNN, a recurrent neural network. So we're going to be learning exactly how they're built over the coming lessons. But in short, they're the same basic structure. The input goes into a weight matrix.

So matrix multiply. Then you replace the negatives with zeros. And it goes into another matrix multiply. And so forth a bunch of times. So it's the same basic structure. So as usual, when we create a learner, you have to pass in two things. The data, so here's our language model data.

And in this case, what pre-trained model we want to use. And so here, the pre-trained model is the Wikitext 103 model. That will be downloaded for you from FastAI if you haven't used it before. Just like the same thing with things like ImageNet pre-trained models are downloaded for you.

This here sets the amount of dropout. We haven't talked about that yet. We've talked briefly about this idea that there's something called regularization. And you can reduce the regularization to avoid underfitting. So for now, just know that by using a number lower than one is because when I first tried to run this, I was underfitting.

And so if you reduce that number, then it will avoid underfitting. OK, so we've got a learner. We can LR find. Looks pretty standard. And so then we can fit one cycle. And so what's happening here is we are just fine-tuning the last layers. So normally after we fine-tuned the last layers, the next thing we do is we go unfreeze and train the whole thing.

And so here it is. Unfreeze and train the whole thing. And as you can see, even on a pretty beefy GPU, that takes two or three hours. And in fact, I'm still underfitting. So probably tonight I might train it overnight and try and do a little bit better. Because you can see, well, I guess I'm not underfitting.

I'm guessing I could probably train this a bit longer because you can see the accuracy hasn't started going down again. So I wouldn't mind trying to train that a bit longer. But the accuracy, it's interesting. Point three means we're guessing the next word of the movie review correctly about a third of the time.

That sounds like a pretty high number, the idea that you can actually guess the next word that often. So that's a good sign that my language model is doing pretty well. For more limited domain documents like medical transcripts and legal transcripts, you'll often find this accuracy gets a lot higher.

So sometimes this can be even 50% or more. But point three or more is pretty good. So you can now run learn.predict and pass in the start of a sentence. And it will try and finish off that sentence for you. Now I should mention this is not designed to be a good text generation system.

This is really more designed to kind of check that it seems to be creating something that's vaguely sensible. There's a lot of tricks that you can use to generate much higher quality text, none of which we're using here. But you can kind of see that it's certainly not random words that it's generating.

It sounds vaguely English-like, even though it doesn't make any sense. So at this point we have a movie review model. So now we're going to save that in order to load it into our classifier, to be our pre-trained model for the classifier. But I actually don't want to save the whole thing.

The second half of the language model is all about predicting the next word rather than about understanding the sentence so far. So the bit which is specifically about understanding the sentence so far is called the encoder. So I just save that. And again, we're going to learn the details of the coming weeks.

We're just going to save the encoder so the bit that understands the sentence rather than the bit that generates the word. So now we're ready to create our classifier. So step one, as per usual, is to create a data bunch. And we're going to do basically exactly the same thing.

Bring it in. And here's our path. But we want to make sure that it uses exactly the same vocab that it used for the language model. If word number 10 was "the" in the language model, we need to make sure that word number 10 is "the" in the classifier.

Because otherwise the pre-trained model is going to be totally meaningless. So that's why we pass in the vocab from the language model to make sure that this data bunch is going to have exactly the same vocab. That's an important step. Split by folder. And this time label -- so remember the last time we had split randomly.

But this time we need to make sure that the labels of the test set are not touched. So we split by folder. And then this time we label it, not for a language model, but we label these classes. And then finally create a data bunch. And remember sometimes you'll find that you run out of GPU memory.

This will very often happen to you if you -- so I was running this in an 11 gig machine. So you should make sure this number is a bit lower if you run out of memory. You may also want to make sure you restart the notebook and kind of start it just from here.

So batch size 50 is as high as I could get on an 11 gig card. If you're using a P2 or P3 on Amazon or the K80 on Google, for example, I think you'll get 16 gigs. So you might be able to make this a bit higher, get it up to 64.

So you can find whatever batch size fits on your card. So here's our data bunch, as we saw before, and the labels. So this time, rather than creating a language model learner, we're creating a text classifier learner. But again, same thing, pass in the data that we want, figure out how much regularization we need.

Again, if you're overfitting, then you can increase this number. If you're underfitting, you can decrease the number. And most importantly, load in our pre-trained model. And remember specifically it's this half of the model called the encoder, which is the bit that we want to load in. And freeze. Now I'll find the learning rate and fit for a little bit.

And we're already up nearly to 92% accuracy after less than three minutes of training. So this is a nice thing. In your particular domain, whether it be law or medicine or journalism or government or whatever, you probably only need to train your domain's language model once. And that might take overnight to train well.

But once you've got it, you can now very quickly create all kinds of different classifiers and models with that. In this case, already a pretty good model after three minutes. So when you first start doing this, you might find it a bit annoying that your first models take four hours or more to create that language model.

But the key thing to remember is you only have to do that once for your entire domain of stuff that you're interested in. And then you can build lots of different classifiers and other models on top of that in a few minutes. So we can save that to make sure we don't have to run it again.

And then here's something interesting. I'm going to explain this more in just a few minutes. I'm not going to say unfreeze. Instead I'm going to say freeze2. And what that says is unfreeze the last two layers. Don't unfreeze the whole thing. And so we've just found it really helps with these text classification.

Not to unfreeze the whole thing, but to unfreeze one layer at a time. So unfreeze the last two layers. Train it a little bit more. Unfreeze the next layer again. Train it a little bit more. Unfreeze the whole thing. Train it a little bit more. You'll also see I'm passing in this thing, momentums equals 0.8.7.

We're going to learn exactly what that means in the next week or two, probably next week. But for now, and we may even automate it. So maybe by the time you watch the video of this, this won't even be necessary anymore. Basically we found for training recurrent neural networks, RNNs, it really helps to decrease the momentum a little bit.

So that's what that is. So that gets us a 94.4 accuracy after about half an hour or less of training, actually quite a lot less, of training the actual classifier. And we can actually get this quite a bit better with a few tricks. I don't know if we'll learn all the tricks.

This part, it might be the next part. But even this very simple kind of standard approach is pretty great. If we compare it to last year's state-of-the-art on IMDB, this is from the Cove paper from McCann et al. at Salesforce Research, their paper was 91.8% accurate. In the best paper they could find, they found a fairly domain-specific sentiment analysis paper from 2017.

They've got 94.1. And here we've got 94.4. And the best models I've been able to build since have been about 95, 95.1. So if you're looking to do text classification, this really standardized transfer learning approach works super well. Any questions, Rachel? Okay, so that was NLP. And we'll be learning more about NLP later in this course.

But now I wanted to switch over and look at Tabula. Now, Tabula data is pretty interesting because it's the stuff that, for a lot of you, is actually what you use day-to-day at work in spreadsheets and relational databases. Just come close, I guess. So where does the magic number of 2.6 to the fourth in the learning rate come from?

Yeah, good question. So the learning rate is various things divided by 2.6 to the fourth. The reason it's to the fourth, you will learn about the end of today. So let's focus on the 2.6. Why 2.6? Basically, as we're going to see in more detail later today, the difference between the bottom of the slice and the top of the slice is basically, what's the difference between how quickly the lowest layer of the model learns versus the highest layer of the model learns?

So this is called discriminative learning rates. So really the question is, as you go from layer to layer, how much do I decrease the learning rate by? And we found out that for NLP RNNs, the answer is 2.6. How do we find out that it's 2.6? I ran lots and lots of different models, like a year ago or so, using lots of different sets of hyperparameters of various types, dropout, learning rates, and discriminative learning rate, and so forth.

And then I created something called a random forest, which is a kind of model where I attempted to predict how accurate my NLP classifier would be based on the hyperparameters. And then I used random forest interpretation methods to basically figure out what the optimal parameter settings were. And I found out that the answer for this number was 2.6.

So that's actually not something I've published, or I don't think I've even talked about it before. So there's a new piece of information. Actually, a few months after I did this, I think Stephen Merity and somebody else did publish a paper describing a similar approach, so the basic idea may be out there already.

Some of that idea comes from a researcher named Frank Hutter and one of his collaborators. They did some interesting work showing how you can use random forests to actually find optimal hyperparameters. So that's kind of a neat trick. A lot of people are very interested in this thing called AutoML, which is this idea of building models to figure out how to train your model.

We're not big fans of it on the whole, but we do find that building models to better understand how your hyperparameters work and then finding those rules of thumb, like basically it can always be 2.6, quite helpful. So that's just something we've kind of been playing with. So let's talk about tabular data.

Tabular data, such as you might see in a spreadsheet or a relational database or a financial report, it can contain all kinds of different things. It can contain all kinds of different things, and I kind of tried to make a little list of some of the kinds of things that I've seen tabular data analysis used for.

Using neural nets for analyzing tabular data is, or at least last year when I first presented this, maybe we started this two years ago. When I first presented this, people were deeply skeptical and they thought it was a terrible idea to use neural nets to analyze tabular data, because everybody knows that you should use logistic regression or random forests or gradient boosting machines, all of which have their place between certain types of things.

But since that time, it's become clear that the commonly held wisdom is wrong. It's not true that neural nets are not useful for tabular data. In fact, they're extremely useful. We've shown this in quite a few of our courses, but what's really kind of also helped is that some really effective organizations have started publishing papers and posts and stuff describing how they've been using neural nets for analyzing tabular data.

One of the key things that comes up again and again is that although feature engineering doesn't go away, it certainly becomes simpler. Pinterest, for example, replaced the gradient boosting machines that they were using to decide how to put stuff on their homepage with neural nets. They presented at a conference this approach and they described how it really made engineering a lot easier because a lot of the hand-created features weren't necessary anymore.

You still need some, but it was just simpler. So they ended up with something that was more accurate, but perhaps even more importantly, it required less maintenance. So I wouldn't say it's the only tool that you need in your toolbox for analyzing tabular data, but where else? I used to use random forests 99% of the time when I was doing machine learning with tabular data.

I now use neural nets 90% of the time. It's kind of my standard first go-to approach now and it tends to be pretty reliable, pretty effective. One of the things that's made it difficult is that until now there hasn't been an easy way to kind of create and train tabular neural nets, like nobody's really made it available on a library.

So we've actually just created fastai.tabular and I think this is pretty much the first time that it's become really easy to use neural nets with tabular data. So let me show you how easy it is. This is actually coming directly from the examples folder in the fastai repo. I haven't changed it at all.

And as per usual, as well as importing fastai, you should import your application. So in this case it's tabular. We assume that your data is in a pandas data frame. A pandas data frame is kind of the standard format for tabular data in Python and it's lots of ways to get it in there, but probably the most common might be pd.read_csv.

But whatever your data is in, you can probably get it into a pandas data frame easily enough. Okay, hit me with a question. What are the 10% of cases where you would not default to neural nets? Good question. I guess I still tend to kind of give them a try.

But, yeah, I don't know. As you do things for a while, you start to get a sense of the areas where things don't quite work as well. I have to think about that during the week. I don't think I have a rule of thumb. But I would say you may as well try both.

I would say try a random forest and try a neural net. They're both pretty quick and easy to run and see how it looks. And if they're roughly similar, I might try and dig into each and see if I can make them better and better. But if the random forest is doing way better, I'd probably just stick with that, use whatever works.

So I currently have the wrong notebook in the lesson repo, so I'll update it after the class, so sorry about that. So we start with the data in a data frame. And so we've got a little thing, adult sample. It's a classic old data set. I'll have to dig up the citation for it because I've got to put it in this notebook.

But it's a pretty small, simple old data set that's good for experimenting with, basically. And it's a CSV file, so you can read it into a data frame with pandas.read_csv, pd.read_csv. If your data is in a relational database, pandas can read from that. If it's in Spark or Hadoop, pandas can read from that.

Pandas can read from most stuff that you can throw at it. So that's why we kind of use it as a default starting point. And as per usual, I think it's nice to use the data block API. And so in this case, the list that we're trying to create is a tabular list, and we're going to create it from a data frame.

And so you can tell it what the data frame is and what the path that you're going to use to kind of save models and intermediate steps is. And then you need to tell it what are your categorical variables and what are your continuous variables. So we're going to be learning a lot more about what that means to the neural net next week.

But for now, the quick summary is this. Your independent variables are the things that you're using to make predictions with. So things like education and marital status and age and so forth. Some of those variables, like age, are basically numbers. They could be any number. You could be 13.36 years old or 19.4 years old or whatever.

Whereas things like marital status are options that can be selected from a discrete group. Married, single, divorce, whatever. Sometimes those options might be quite a lot more, like occupation. There's a lot of possible occupations. And sometimes they might be binary. It could be just true or false. But anything which you can select the answer from a small group of possibilities is called a categorical variable.

And so we're going to need to use a different approach to the neural net to modeling categorical variables to what we use for continuous variables. For categorical variables, we're going to be using something called embeddings, which we'll be learning about later today. For continuous variables, they could just be sent in to the neural net just like pixels in a neural net can.

Because pixels in a neural net are already numbers. These continuous things are already numbers as well. So that's easy. So that's why you have to tell the tabular list from DataFrame which ones are which. There are some other ways to do that by preprocessing them in pandas to make things categorical variables.

It's kind of nice to have one API for doing everything. You don't have to think too much about it. Then we've got something which is a lot like transforms in computer vision. Transforms in computer vision do things like flip a photo when it's accessed or turn it a bit or brighten it or normalize it.

But for tabular data, instead of having transforms, we have things called processes. And they're nearly identical, but the key difference, which is quite important, is that a processor is something that happens ahead of time. So we basically preprocess the DataFrame rather than doing it as we go. So transformations are really for data augmentation where you want to randomize it and do it differently each time.

Whereas processes are things that you want to do once ahead of time. So we have a number of processes in the FastAI library, and the ones we're going to use this time are fill missing. So that's going to look for missing values and deal with them some way. We're going to find categorical variables and turn them into pandas categories.

And we're going to do normalization ahead of time, which is to take continuous variables and subtract their mean and divide them by their standard deviation, so they're 0, 1 variables. The way we deal with missing data, we'll talk more about next week, but in short we replace it with a median and add a new column, which is a binary column of saying whether that was missing or not.

Normalization, there's an important thing here, which is, in fact, for all of these things, whatever you do to the training set, you need to do exactly the same thing to the validation set and the test set. So whatever you replace your missing values with, you need to replace them with exactly the same thing in the validation set.

So FastAI handles all these details for you. There are kinds of things that if you have to do it manually, at least if you're like me, you'll screw it up lots of times until you finally get it right. So that's what these processes are here. Then we're going to split into training versus validation sets, and in this case we do it by providing a list of indexes, so the indexes from 800 to 1,000.

It's very common. I don't quite remember the details of this data set, but it's very common for wanting to keep your validation sets to be contiguous groups of things, like if they're map tiles, they should be the map tiles that are next to each other. If they're time periods, they should be days that are next to each other.

If they're video frames, they should be video frames next to each other, because otherwise you're kind of cheating. So it's often a good idea to use split by IDX and to grab a range that's next to each other if your data has some kind of structure like that or find some other way to structure it in that way.

All right, so that's now given us a training and a validation set. We now need to add labels, and in this case the labels can come straight from the data frame we grabbed earlier, so we just have to tell it which column it is. And so the dependent variable is, I think it's whether they're making over $50,000 salary.

That's the thing we're trying to predict in this case. We'll talk about test sets later, but in this case we can add a test set and finally get our data bunch. So at that point we have something that looks like this. So there is our data. And then to use it, it looks very familiar.

You get a learner, in this case it's a tabular learner, passing in the data, some information about your architecture, and some metrics, and you then call fit. You had some questions? All right, let's hit the questions. >> How to combine NLP tokenized data with metadata, such as tabular data with fast AI?

For instance, for IMBD classification, how to use information like who the actors are, year made, genre, et cetera? >> Yeah, we're not quite up to that yet, so I need to learn a little bit more about how neural net architectures work. Conceptually, it's kind of the same as the way we combine categorical variables and continuous variables.

Basically, in the neural network you can have two different sets of inputs merging together into some layer. It could go into an early layer or into a later layer. It kind of depends. If it's like text and an image and some metadata, you probably want the text going into an RNN, the image going into a CNN, the metadata going into some kind of tabular model like this, and then you'd have them basically all concatenated together and then go through some fully connected layers and train them end to end.

We'll probably largely get into that in part two. In fact, we might entirely get into part two. I'm not sure if we'll have time to cover it in part one. Conceptually, it's a fairly simple extension of what we'll be learning in the next three weeks. Next question is, do you think things like scikit-learn and xgboost will eventually become outdated?

Will everyone use deep learning tools in the future except for maybe small data sets? I have no idea. I'm not good at making predictions. I'm not a machine learning model. I mean, xgboost is a really nice piece of software. There's quite a few really nice pieces of software for gradient boosting in particular.

They have some really nice features, or actually random forests in particular, have some really nice features for interpretation, which I'm sure we'll find similar versions for neural nets, but they don't necessarily exist yet. So I don't know. For now, they're both useful tools. Scikit-learn is a library that's often used for preprocessing and running models.

Again, it's hard to predict where things will end up. In some ways, it's more focused on some older approaches to modeling, but I don't know. They keep on adding new things, so we'll see. I keep trying to incorporate more scikit-learn stuff into FastAI, and then I keep finding ways I think I can do it better, and I throw it away again.

So that's why there's still no scikit-learn dependencies in FastAI. I keep finding other ways to do stuff. Okay, so we're going to learn what layers equals means either towards the end of class today or the start of class next week, where we're basically defining our architecture, just like when we chose ResNet 34 or whatever for ConvNets.

We'll look at more about metrics in a moment, but just to remind you, metrics are just the things that get printed out. They don't change our model at all. So in this case, we're saying I want you to print out the accuracy to see how we're doing. Okay, so that's how to do Tabular.

This is going to work really well, and we're going to hit our break soon. And the idea was that after three and a half lessons, we're going to hit the end of all of the quick overview of applications, and then we're going to go down on the other side.

I think we're going to be to the minute we're going to hit it, because the next one is collaborative filtering. So collaborative filtering is where you have information about who bought what or who liked what. It's basically something where you have something like a user or a reviewer or whatever, and information about what they've bought or what they've written about or what they reviewed.

So in the most basic version of collaborative filtering, you just have two columns, something like user ID and movie ID, and that just says this user bought that movie, this user bought that movie, this user bought that movie. So for example, Amazon has a really big list of user IDs and product IDs of like, what did you buy?

Then you can add additional information to that table, such as, oh, they left a review. What review did they give it? So it's now like user ID, movie ID, number of stars. You could add a time code, so like this user bought this product at this time and gave it this review.

But they're all basically the same kind of structure. So there's kind of like two ways you could draw that collaborative filtering structure. One is kind of a two-column approach where you've got like user and, I don't know, movie. And you've got user ID, movie ID, user ID, you know.

Each pair basically describes that user, watch that movie, possibly also plus number of stars, you know, three, four, one, whatever. Well, the other way that you could write it would be you could have like all the users down here and all the movies along here. And then, you know, you can look and find a particular cell in there to find out, you know, could be the rating of that user for that movie or there's just a one there if that user watched that movie or whatever.

So there's like two different ways of representing the same information. Conceptually, it's often easier to think of it this way, right? But most of the time you won't store it that way explicitly because most of the time you'll have what's called a very sparse matrix, which is to say most users haven't watched most movies or most customers haven't purchased most products.

So if you store it as a matrix where every combination of customer and product is a separate cell in that matrix, it's going to be enormous. So you tend to store it like this or you can store it as a matrix using some kind of special sparse matrix format.

And if that sounds interesting, you should check out Rachel's computational linear algebra course on FastAI where we have lots and lots and lots of information about sparse matrix storage approaches. For now, though, we're just going to kind of keep it in this format on the left-hand side. So for collaborative filtering, there's a really nice data set called movie lens created by the group lens group very hopefully.

And you can download various different sizes, 20 million. So 100,000 ratings. We've actually created an extra small version for playing around with, which is what we'll start with today. And then probably next week we'll use the bigger version. But so you can grab the small version using urls.ml sample.

And it's a CSV, so you can read it with pandas. And here it is, right? It's basically a list of user IDs. We don't actually know anything about who these users are. There's some movie IDs. There is some information about what the movies are, but we won't look at that until next week.

And then there's the rating. And then there's the timestamp. We're going to ignore the timestamp for now. So that's a subset of our data that's the head. So the head in pandas is just the first few rows. So now that we've got a data frame, the nice thing about collaborative filtering is it's incredibly simple.

That's all the data that we need. So you can now go ahead and say get collaborative learner, and you can actually just pass in the data frame directly. The architecture, you have to tell it how many factors you want to use, and we're going to learn what that means after the break.

And then something that can be helpful is to tell it what the range of scores are, and we're going to see how that helps after the break as well. So in this case, the minimum score is zero, the maximum score is five. So now that you've got a learner, you can go ahead and call fit one cycle.

And trains for a few epochs, and there it is. So at the end of it, you now have something where you can pick a user ID and a movie ID and guess whether or not that user will like that movie. So this is obviously a super useful application that a lot of you are probably going to try during the week in past classes.

A lot of people have taken this collaborative filtering approach back to their workplaces and discovered that using it in practice is much more tricky than this because in practice you have something called the cold start problem. So the cold start problem is that the time you particularly want to be good at recommending movies is when you have a new user, and the time you particularly care about recommending a movie is when it's a new movie.

But at that point, you don't have any data in your collaborative filtering system, and it's really hard. As I say this, we don't currently have anything built in to fast AI to handle the cold start problem. And that's really because the cold start problem, the only way I know of to solve it, in fact the only way I think that conceptually you can solve it, is to have a second model, which is not a collaborative filtering model, but a metadata driven model for new users or new movies.

I don't know if Netflix still does this, but certainly what they used to do when I signed up to Netflix was they started showing me lots of movies and saying, "Have you seen this? Did you like it? Have you seen this? Did you like it?" So they fixed the cold start problem through the UX.

So there was no cold start problem. They found like 20 really common movies and asked me if I liked them. They used my replies to those 20 to show me 20 more that I might have seen. And by the time I had gone through 60, there was no cold start problem anymore.

And for new movies, it's not really a problem because like the first 100 users who haven't seen the movie, you know, go in and say whether they liked it and then the next 100,000, the next million, it's not a cold start problem anymore. But the other thing you can do if you, for whatever reason, kind of can't go through that UX of like asking people, "Did you like those things?" So for example, if you're selling products and you don't really want to show them like a big selection of your products and say, "Did you like this?" because you just want them to buy.

You can instead try and use a metadata-based kind of tabular model. You know, what geography did they come from? Maybe you know their age and sex. You can try and make some guesses about the initial recommendations. So collaborative filtering is specifically for once you have a bit of information about your users and movies or customers and products or whatever.

Yeah, okay. How does the language model trained in this manner perform on code switch data such as Hindi written in English words or text with a lot of emojis? And then do you want the second question? Yeah, that's a good question. So text with emojis, it'll be fine. There's not many emojis in Wikipedia.

And where they are in Wikipedia, it's more like a Wikipedia page about the emoji rather than the emoji being used in a sensible place. But you can and should do this language model fine-tuning where you take a corpus of text where people are using emojis in usual ways. And so you fine-tune the wiki text language model to your Reddit or Twitter or whatever language model.

And there aren't that many emojis. If you think about it, there's hundreds of thousands of possible words that people can be using, but a small number of possible emojis. So it'll very quickly learn how those emojis are being used. So that's a piece of cake. So I'm not very familiar with Hindi, but I'll take an example.

I'm very familiar with, which is Mandarin. In Mandarin, you could have a model that's trained with Chinese characters. So there's kind of five or six thousand Chinese characters in common use. But there's also a romanization of those characters called pinyin. And it's a bit tricky because although there's a nearly direct mapping from the character to the pinyin, I mean there is a direct mapping, the pronunciation's not exactly direct, there isn't direct mapping from the pinyin to the character because one pinyin corresponds to multiple characters.

So the first thing to note is that if you're going to use this approach for Chinese, you would need to start with a Chinese language model. So actually, FastAI has something called a model zoo where we're adding more and more language models for different languages and also increasingly for different domain areas like English medical texts or even language models for things other than NLP like genome sequences, molecular data, musical MIDI notes, and so forth.

So you would obviously start there. To then convert that, that'll be in either simplified or traditional Chinese, to then convert that into, if you want to do pinyin, you could either kind of map the vocab directly or as you'll learn, these multi-layer models, it's only the first layer that basically converts the tokens into a set of vectors.

You could actually throw that away and fine-tune just the first layer of the model. So that second part is going to require a few more weeks of learning before you exactly understand how to do that and so forth. But if it's something you're interested in doing, we can talk about it on the forum because it's a kind of a nice test of understanding.

So what about time series on tabular data? Is there an RNN model involved in tabular.models? So we're going to look at time series tabular data next week. But the short answer is, generally speaking, you don't use a RNN for time series tabular data, but instead you extract a bunch of columns for things like day of week, is it a weekend, is it a holiday, was the store open, stuff like that.

It turns out that adding those extra columns, which you can do somewhat automatically, basically gives you state-of-the-art results. There are some good uses of RNNs for time series, but not really for these kind of tabular style time series, like retail store logistics databases and stuff like that. And is there a source to learn more about the cold start problem?

I'm going to have to look that up. If you know a good resource, please mention it on the forums. So that is both the break and the middle of lesson four. It's the halfway point of the course, and it's the point at which we have now seen an example of all the key applications.

And so the rest of this course is going to be digging deeper into how they actually work behind the scenes, more of the theory, more of how the source code is written, and so forth. So it's a good time to have a nice break, come back. And furthermore, it's my birthday today, so it's really a special moment.

So let's have a break and come back at 5 past 8. So Microsoft Excel, this is one of my favorite ways to explore data and understand models. I'll make sure I put this in the repo. And actually, this one we can probably largely do in Google Sheets. I've tried to move as much as I can over the last few weeks into Google Sheets, but I just keep finding this is such a terrible product.

Please try to find a copy of Microsoft Excel because there's nothing close. I've tried everything. Spreadsheets get a bad rap from people that basically don't know how to use them, just like people who spend their lives on Excel and then they start using Python. And they're like, what the hell is this stupid thing?

It takes thousands of hours to get really good at spreadsheets, but a few dozen hours to get competent at them. And once you're competent at them, you can see everything in front of you. It's all laid out. It's really great. I'll give you one spreadsheet tip today, which is if you hold down the control key or command key on your keyboard and press the arrow keys, here's control right.

It takes you to the end of a block of a table that you're in, and it's by far the best way to move around the place. So there you go. In this case, I want to skip around through this table, so I can hit control down right to get to the bottom right, control left up to get to the top left, skip around and see what's going on.

So here's some data, and as we talked about, one way to look at collaborative filtering data is like this. And so what we did was we grabbed from the movie lens data the people that watched the most movies and the movies that were the most watched and just filtered the data set down to those 15.

And as you can see, when you do it that way, it's not sparse anymore. There's just a small number of gaps. So this is something that we can now build a model with. And so how can we build a model? What we want to do is we want to create something which can predict for user 293 will they like movie 49, for example.

So we've got to come up with some way of, you know, some function that can represent that decision. And so here's a simple possible approach. And so we're going to take this idea of doing some matrix multiplications. So I've created here a random matrix. So here's one matrix of random numbers.

And I've created here another matrix of random numbers. More specifically, for each movie I've created five random numbers. And for each user I've created five random numbers. And so we could say then that user 14, movie 27, did they like it or not? Well the rating, what we could do would be to multiply together this vector and that vector.

We could do a dot product, and here's a dot product. And so then we can basically do that for every possible thing in here. We've got the dot product. And, you know, thanks to spreadsheets we can just do that in one place and copy it over and it fills in the whole thing for us.

Why would we do it this way? Well, this is the basic starting point of a neural net, isn't it? The basic starting point of a neural net is that you take the matrix multiplication of two matrices and that's what your first layer always is. And so we just have to come up with some way of saying like, well, what are two matrices that we can multiply?

And so clearly, you know, you need a matrix for a user, you know, or a vector for a user, a matrix for all the users, and a vector for a movie, or a matrix for all the movies, and multiply them together and you get some numbers, right? Like, so they don't mean anything yet, they're just random, right?

But we can now use gradient descent to try to make these numbers, and these numbers give us results that are closer to what we wanted. So how do we do that? Well, we've set this up now as a linear model, right? So the next thing we need is a loss function.

So we can calculate our loss function by saying, well, okay, movie 3 for user_id 14 should have been a rating of 3. With this random matrices, it's actually a rating of 0.91. So we can find the sum of squared errors would be 3 minus 0.91 squared. And then we can add them up.

So there's actually a sum squared in Excel already, some x minus y squared, so we can use just some x minus y squared function passing in those two ranges. And then divide by the count to get the mean. So here is a number that is the square root of the mean squared error.

So sometimes you'll see people talk about MSE, so that's the mean squared error. Sometimes you'll see RMSE, that's the root mean squared error. So since I've got a square root at the front, this is the square root mean squared error. So we have a loss. So now all we need to do is use gradient descent to try to modify our weight matrices to make that loss smaller.

So Excel will do that for me. So it's probably worth knowing how to do that, so we have to install add-ins. Solver's there. It's obviously forgotten where it was. So the gradient descent solver in Excel is called solver, and it just does normal gradient descent. So you just go data, solver.

You'll need to make sure that in your settings that you've enabled the solver extension, it comes with Excel. And all you need to do is say, which cell represents my loss function? So there it is, V41. So where is your loss function stored? Which cells contain your variables? So you can see here I've got H19 to V23, which is up here, and B25 to F39, which is over there.

And then you can just say, okay, set your loss function to a minimum by changing those cells and solve. And you'll see it starts at 2.81, and you can see the numbers going down. And so all that's doing is using gradient descent exactly the same way that we did when we did it manually in the notebook the other day.

But it's rather than solving the mean squared error for a at x in the Python. Instead, it is solving the loss function here, which is the mean squared error of the dot product of each of those vectors by each of these vectors. And so there it goes. So we'll let that run for a little while and see what happens.

But basically in micro, here is a simple way of creating a neural network, which is really in this case, it's like just a single linear layer with gradient descent to solve a collaborative filtering problem. So let's go back and see what we do over here. So over here we used get collab learner.

Okay, so the function that was called in the notebook was get collab learner. And so as you dig deeper into deep learning, one of the really good ways to dig deeper into deep learning is to dig into the fastai source code and see what's going on. And so if you're going to be able to do that, you need to know how to use your editor well enough to dig through the source code.

And basically there's two main things you need to know how to do. One is to jump to a particular symbol, like a particular class or function by its name. And the other is that when you're looking at a particular symbol, to be able to jump to its implementation. So for example, in this case I want to find get collab learner.

So in most editors, including the one I used, VIM, you can set it up so that you can kind of hit tab or something and it jumps through all the possible completions and you can hit enter and it jumps straight to the definition for you. So here is the definition of get collab learner.

And as you can see, it's pretty small as these things tend to be. And in this case it kind of wraps a data frame and automatically creates a data bunch for you because it's so simple. But the key thing it does then is to create a model of a particular kind, which is an embedding.bias model passing in the various things you asked for.

So you want to find out in your editor how you jump to the definition of that, which in VIM you just hit control right square bracket. And here is the definition of embedding.bias. And so now we have everything on screen at once and as you can see there's not much going on.

So the models that are being created for you by FastAI are actually PyTorch models. And a PyTorch model is called an nn.module. That's the name in PyTorch of their models. It's a little more nuanced than that but that's a good starting point for now. And when a PyTorch nn.module is run, when you calculate the result of that layer or neural net or whatever, specifically it always calls a method for you called forward.

So it's in here that you get to find out how this thing is actually calculated. When the model is built at the start it calls this thing called underscore underscore init underscore underscore. And as I think we briefly mentioned before in Python, people tend to call this dunder init, double underscore init.

So dunder init is how we create the model and forward is how we run the model. One thing if you're watching carefully you might notice is there's nothing here saying how to calculate the gradients of the model and that's because PyTorch does it for us. So you only have to tell it how to calculate the output of your model and PyTorch will go ahead and calculate the gradients for you.

And so in this case, the model contains a set of weights for a user, a set of weights for an item, a set of biases for a user, a set of biases for an item, and each one of those is coming from this thing called get embedding. So let's see get embedding.

So here is the definition of get embedding. And all it does basically is it calls this PyTorch thing called nn.embedding. So in PyTorch they have a lot of like standard neural network layers set up for you. So it creates an embedding. And then this thing here is, it just randomizes it.

So this is something which creates normal random numbers for the embedding. So what's an embedding? An embedding, not surprisingly, is a matrix of weights. Specifically it's a matrix of weights. Specifically an embedding is a matrix of weights that looks something like this. It's a matrix of weights which you can basically look up into and grab one item out of it.

So basically any kind of weight matrix, and we're going to be digging into this in a lot more detail in the coming lessons, but an embedding matrix is just a weight matrix that is designed to be something that you kind of index into it as an array and grab one vector out of it.

That's what an embedding matrix is. And so in our case we have an embedding matrix for a user and an embedding matrix for a movie. And here we have been taking the dot product of them. But if you think about it, that's not quite enough because we're missing this idea that like, maybe there are certain movies that everybody likes more.

Maybe there are some users that just tend to like movies more. So I don't really just want to multiply these two vectors together but I really want to add a single number of how popular is this movie and add a single number of how much does this user like movies in general.

So those are called bias terms. Remember how I said there's this kind of idea of bias and the way we dealt with that in our gradient descent notebook was we added a column of ones. But what we tend to do in practice is we actually explicitly say I want to add a bias term.

So we don't just want to have prediction equals dot product of these two things. We want to say it's the dot product of those two things plus a bias term for a movie plus a bias term for a user ID. So that's basically what happens. When we set up the model, we set up the embedding matrix for the users and the embedding matrix for the items and then we also set up the bias vector for the users and the bias vector for the items.

And then when we calculate the model, we literally just multiply the two together. Just like we did, right? We just take that product, call it dot, right? And then we add the bias and then putting aside the min and max score for a moment, that's what we return. So you can see that our model is literally doing what we did here with the tweak that we're also adding the bias.

So it's an incredibly simple linear model. And for these kinds of collaborative filtering problems, this kind of simple linear model actually tends to work pretty well. And then there's one tweak that we do at the end, which is that in our case we said that there's a min score of 0 and a max score of 5.

And so here's something to point out. So if you have a range, so you do that dot product and you add on the two biases and that could give you any possible number along the number line from very negative through to very positive numbers. But we know that we always want to end up with a number between 0 and 5.

Let's say that's 5, and of course this is 0. So what if we mapped that number line like so to this function? And so the shape of that function is called a sigmoid. And so it's going to asymptote to 5 and it's going to asymptote to 0. And so that way whatever number comes out of our dot product and adding the biases, if we then stick it through this function, it's never going to be higher than 5 and never going to be smaller than 0.

Now strictly speaking, that's not necessary because our parameters could learn a set of weights that gives about the right number. So why would we do this extra thing if it's not necessary? Well the reason is we want to make life as easy for our model as possible. So if we actually set it up, so it's impossible for it to ever predict too much or ever predict too little, then it can spend more of its weights predicting the thing we care about which is deciding who's going to like what movie.

So this is an idea we're going to keep coming back to when it comes to making neural networks work better. It's about all these little decisions that we make to basically make it easier for the network to learn the right thing. So that's the last tweak here, which is we take the result of this dot product plus biases, we put it through a sigmoid, and so a sigmoid is just a function, it's basically 1 over 1 plus e^x, the definition doesn't much matter but it just has the shape that I just mentioned, and that goes between 0 and 1.

And if you then multiply that by max minus min plus min, then that's going to give you something that's between min score and max score. So that means that this tiny little neural network, I mean it's a push to call it a neural network, but it is. It's a neural network with one weight matrix and no non-linearities, so it's kind of the world's most boring neural network with a sigmoid at the end.

That's actually, I guess it does have a non-linearity, the sigmoid at the end is the non-linearity. It only has one layer of weights. That actually turns out to give close to state-of-the-art performance, like I've looked up online to find out what are the best results people have on this movie lens 100K database, and the results I get from this little thing are better than any of the results I can find from the standard commercial products that you can download that are specialized for this.

And the trick seems to be that adding this little sigmoid makes a big difference. And did you have a question? There was a question about how you set up your VIN, and I've already linked to your .VIMRC, but I wanted to know if you had more to say about that.

What do they want to know about VIM? They really like your setup. You like my setup? There's almost nothing in my setup. It's pretty bare, honestly. Whatever you're doing with your editor, you probably want it to look like this. When you've got a class that you're not currently working on, this is called "folded." It should be closed up so you can't see it.

You basically want something where it's easy to close and open-fold. VIM already does all this for you. And then, as I mentioned, you also want something where you can jump to the definition of things, which in VIM it's called "using tags." So if you want to jump to the definition of "learner." Basically, VIM already does all this for you.

You just have to read the instructions. My VIMRC is minimal. I basically hardly use any extensions or anything. Another great editor to use is VS Code, Visual Studio Code. It's free, and it's awesome, and it has all the same features that you're seeing that VIM does. Basically, VS Code does all of those things as well.

I quite like using VIM because I can use it on the remote machine and play around, but you can of course just clone the Git repo onto your local computer and open it up in VS Code to play around with it. Just don't try and look through the code just on GitHub or something.

That's going to drive you crazy. You need to be able to open it and close it and jump and jump back. Maybe people can create some threads on the forum for VIM tips, VS Code tips, Sublime tips, whatever. For me, I would say if you're going to pick an editor, if you want to use something on your local, I would go with VS Code today.

I think it's the best. If you want to use something on the terminal side, I would go with VIM or Emacs. To me, they're clear winners. What I wanted to close with today is to take this collaborative filtering example and describe how we're going to build on top of it for the next three lessons to create the more complex neural networks we've been seeing.

Roughly speaking, this is the bunch of concepts that we need to learn about. Let's think about what happens when you're using a CNN or a neural network to do image recognition. Basically, let's take a single pixel. You've got lots of pixels, but let's take a single pixel. You've got a red, a green and a blue pixel.

Each one of those is some number between 0 and 255. We kind of normalize them so they're a floating point with the mean of 0 and standard deviation of 1. Let's do the 0 to 255 version. What do we do with these? We basically treat that as a vector and we multiply it by a matrix.

Depending on how you think of the rows and the columns, let's treat the matrix as having three rows and then how many columns? Well, you get to pick. Just like with the collaborative filtering version, I decided to pick a vector of size 5 for each of my embedding vectors.

That would mean that that's an embedding of size 5. You can get to pick how big your weight matrix is. Let's make it size 5. This is 355. Initially, this weight matrix contains random numbers. Remember when we looked up get embedding matrix just now? There were like two lines.

The first line was like create the matrix and the second was fill it with random numbers. That's what we do. It all gets hidden behind the scenes by fast AI and PyTorch. That's all it's doing. It's creating a matrix of random numbers when you set it up. The number of rows has to be 3 to match the input.

The number of columns can be as big as you like. After you multiply the input vector by that weight matrix, you're going to end up with a vector of size 5. People often ask how much linear algebra do I need to know to be able to do deep learning?

This is the amount you need. If you're not familiar with this, that's fine. You need to know about matrix products. You don't need to know a lot about them. You just need to know computationally what do they do. You've got to be very comfortable with a matrix of size blah times a matrix of size blah gives a matrix of size blah.

How do the dimensions match up? If you have 3 and then remember in NumPy and PyTorch we use at times 3 by 5 gives a vector of size 5. What happens next? It goes through an activation function such as ReLU, which is just max 0, x, and spits out a new vector which is of course going to be exactly the same size.

Because no activation function changes the size. It only changes the contents, so that's still a size 5. What happens next? We multiply it by another matrix. And again, it can be any number of columns, but the number of rows has to map nicely. So it's going to be 5 by whatever.

So maybe this one has 5, say, by 10. And so that's going to give some output. Which will be size 10. And again, we put that through ReLU. And again, that gives us something of the same size. And then we can put that through another matrix. Actually, just to make this a bit clearer, you'll see why in a moment, I'm going to use 8, not 10.

Let's say we're doing digit recognition. So there are 10 possible digits. So my last weight matrix has to be 10 in size. Because then that's going to mean my final output is a vector of 10 in size. And remember, if we're doing digit recognition, what happens? We take our actuals, which is 10 in size.

And if the number that we're trying to predict was the number 3, that's the thing we're trying to predict. Then that means that there is a 3, 0, 0, 0, in the third position. So what happens is our neural net runs along, starting with our input. And going weight matrix, ReLU, weight matrix, ReLU, weight matrix, final output.

And then we compare these two together to see how close they are, how close they match, using some loss function. We'll learn about all the loss functions that we use next week. For now, the only one we've learned is mean squared error. And we compare the actual, you can think of them as probabilities for each of the 10 to the actual each of the 10 to get a loss.

And then we find the gradients of every one of the weight matrices with respect to that, and we update the weight matrices. So the main thing I wanted to show right now is the terminology we use, because it's really important. These things contain numbers. Specifically, they initially are matrices containing random numbers.

And we can refer to these yellow things, in PyTorch they're called parameters. Sometimes we'll refer to them as weights, although weights is slightly less accurate because there can also be biases. But we kind of use the terms a little bit interchangeably, but strictly speaking we should call them parameters.

And then after each of those matrix products, that calculates a vector of numbers. So here are some numbers that are calculated by a weight matrix, multiply. And then there are some other sets of numbers that are calculated as a result of a ReLU, as a relevant activation function. Okay, either one is called activations.

So activations and parameters both refer to numbers, they are numbers. The parameters are numbers that are stored, they're used to make a calculation. Activations are the result of a calculation, they're numbers that are calculated. So they're the two key things you need to remember. So use these terms, and use them correctly and accurately.

And if you read these terms they mean these very specific things, so don't mix them up in your head. And remember they're nothing weird and magical, they're very simple things. An activation is the result of either a matrix multiply or an activation function. And a parameter are the numbers inside the matrices that we multiply by.

Okay, that's it. And then there are some special layers, so every one of these things that does a calculation, all of these things that does a calculation, are all called layers. They're the layers of our neural net. So every layer results in a set of activations, because there's a calculation that results in a set of results.

There's a special layer at the start, which is called the input layer, and then at the end you just have a set of activations. And we can refer to those special, I mean they're not special mathematically, but they're semantically special, we can call those the outputs. So the important point to realize here is the outputs of a neural net are not actually mathematically special, they're just the activations of a layer.

And so what we did in our collaborative filtering example, we did something interesting, we actually added an additional activation function right at the very end. We added an extra activation function, which was sigmoid. Specifically it was a scaled sigmoid, between 0 and 5. And that's really common. It's very common to have an activation function as your last layer.

And it's almost never going to be a value, because it's very unlikely that what you actually want is something that stops, that truncates at 0. It's very often going to be a sigmoid or something similar, because it's very likely that actually what you want is something that's between two values, and kind of scaled in that way.

So that's nearly it, right? So we've got inputs, weights, activations, activation functions, which we sometimes call non-linearities, output. And then the function that compares those two things together is called the loss function, which so far we've used MSE. Yeah, okay. And that's enough for today. So what we're going to do next week is we're going to kind of add in a few more extra bits, which is we're going to learn the loss function that's used for classification, which is called cross-entropy.

We're going to use the activation function that's used for single-label classification, which is called softmax. And we're also going to learn exactly what happens when we do fine-tuning in terms of how these layers actually, what happens with unfreeze and what happens when we create transfer learning. So thanks, everybody.

Looking forward to seeing you next week.