|
661 | 661 | "metadata": {},
|
662 | 662 | "source": [
|
663 | 663 | "# 5. Creating Network Components in Pytorch\n",
|
664 |
| - "Before we move on to our focus on NLP, lets do an annotated example of building a network in Pytorch using only affine maps and non-linearities. We will also see how to compute a loss function, using Pytorch's built in negative log likelihood.\n", |
| 664 | + "Before we move on to our focus on NLP, lets do an annotated example of building a network in Pytorch using only affine maps and non-linearities. We will also see how to compute a loss function, using Pytorch's built in negative log likelihood, and update parameters by backpropagation.\n", |
665 | 665 | "\n",
|
666 | 666 | "All network components should inherit from nn.Module and override the forward() method. That is about it, as far as the boilerplate is concerned. Inheriting from nn.Module provides functionality to your component. For example, it makes it keep track of its trainable parameters, you can swap it between CPU and GPU with the .cuda() or .cpu() functions, etc.\n",
|
667 | 667 | "\n",
|
668 | 668 | "Let's write an annotated example of a network that takes in a sparse bag-of-words representation and outputs a probability distribution over two labels: \"English\" and \"Spanish\".\n",
|
669 | 669 | "\n",
|
670 |
| - "Note: This is just for demonstration, so that we can build Pytorch components in later sections and you will know what is going on. Handing in a sparse bag-of-words representation is not how you would actually want to do things." |
| 670 | + "Note: This is just for demonstration, so that we can build Pytorch components in later sections and you will know what is going on. Handing in a sparse bag-of-words representation is not how you would actually want to do things. There are better ways to do text classification. I made up this model to be extremely simple and to not use word embeddings (which we don't introduce until the next section)." |
671 | 671 | ]
|
672 | 672 | },
|
673 | 673 | {
|
|
1040 | 1040 | "metadata": {},
|
1041 | 1041 | "source": [
|
1042 | 1042 | "How can we solve this problem? That is, how could we actually encode semantic similarity in words?\n",
|
1043 |
| - "Maybe we think up some lexical attributes. For example, we see that both mathematicians and physicists can run, so maybe we give these words a high score for the \"is able to run\" semantic attribute. Think of some other attributes, and imagine what you might score some common words on those attributes.\n", |
| 1043 | + "Maybe we think up some semantic attributes. For example, we see that both mathematicians and physicists can run, so maybe we give these words a high score for the \"is able to run\" semantic attribute. Think of some other attributes, and imagine what you might score some common words on those attributes.\n", |
1044 | 1044 | "\n",
|
1045 | 1045 | "If each attribute is a dimension, then we might give each word a vector, like this:\n",
|
1046 | 1046 | "$$ q_\\text{mathematician} = \\left[ \\overbrace{2.3}^\\text{can run},\n",
|
|
1049 | 1049 | "\\overbrace{9.1}^\\text{likes coffee}, \\overbrace{6.4}^\\text{majored in Physics}, \\dots \\right] $$\n",
|
1050 | 1050 | "\n",
|
1051 | 1051 | "Then we can get a measure of similarity between these words by doing:\n",
|
1052 |
| - "$$ \\text{Similarity}(\\text{physicist}, \\text{mathematician}) = q_\\text{physicist} \\cdot q_\\text{mathematician} $$" |
| 1052 | + "$$ \\text{Similarity}(\\text{physicist}, \\text{mathematician}) = q_\\text{physicist} \\cdot q_\\text{mathematician} $$\n", |
| 1053 | + "\n", |
| 1054 | + "Although it is more common to normalize by the lengths:\n", |
| 1055 | + "$$ \\text{Similarity}(\\text{physicist}, \\text{mathematician}) = \\frac{q_\\text{physicist} \\cdot q_\\text{mathematician}}\n", |
| 1056 | + "{\\| q_\\text{\\physicist} \\| \\| q_\\text{mathematician} \\|} = \\cos (\\phi) $$\n", |
| 1057 | + "Where $\\phi$ is the angle between the two vectors. That way, extremely similar words (words whose embeddings point in the same direction) will have similarity 1. Extremely dissimilar words should have similarity -1." |
1053 | 1058 | ]
|
1054 | 1059 | },
|
1055 | 1060 | {
|
1056 | 1061 | "cell_type": "markdown",
|
1057 | 1062 | "metadata": {},
|
1058 | 1063 | "source": [
|
1059 |
| - "You can think of the sparse one-hot vectors from the beginning of this section as a special case of these new vectors we have defined, where each word basically has similarity 0.\n", |
| 1064 | + "You can think of the sparse one-hot vectors from the beginning of this section as a special case of these new vectors we have defined, where each word basically has similarity 0, and we gave each word some unique semantic attribute.\n", |
1060 | 1065 | "\n",
|
1061 |
| - "But these new vectors are a big pain: you could think of thousands of different lexical attributes that might be relevant to determining similarity, and how on earth would you set the values of the different attributes? Central to the idea of deep learning is that the neural network learns representations of the features, rather than requiring the programmer to design them herself. So why not just let the word embeddings be parameters in our model, and then be updated during training? This is exactly what we will do. We will have some *latent lexical attributes* that the network can, in principle, learn. Note that the word embeddings will probably not be interpretable. That is, although with our hand-crafted vectors above we can see that mathematicians and physicists are similar in that they both like coffee, if we allow a neural network to learn the embeddings and see that both mathematicians and physicisits have a large value in the second dimension, it is not clear what that means. They are similar in some latent semantic dimension, but this probably has no interpretation to us." |
| 1066 | + "But these new vectors are a big pain: you could think of thousands of different semantic attributes that might be relevant to determining similarity, and how on earth would you set the values of the different attributes? Central to the idea of deep learning is that the neural network learns representations of the features, rather than requiring the programmer to design them herself. So why not just let the word embeddings be parameters in our model, and then be updated during training? This is exactly what we will do. We will have some *latent semantic attributes* that the network can, in principle, learn. Note that the word embeddings will probably not be interpretable. That is, although with our hand-crafted vectors above we can see that mathematicians and physicists are similar in that they both like coffee, if we allow a neural network to learn the embeddings and see that both mathematicians and physicisits have a large value in the second dimension, it is not clear what that means. They are similar in some latent semantic dimension, but this probably has no interpretation to us." |
1062 | 1067 | ]
|
1063 | 1068 | },
|
1064 | 1069 | {
|
|
1116 | 1121 | "$$ P(w_i | w_{i-1}, w_{i-2}, \\dots, w_{i-n+1} ) $$\n",
|
1117 | 1122 | "Where $w_i$ is the ith word of the sequence.\n",
|
1118 | 1123 | "\n",
|
1119 |
| - "In this example, we will compute the loss function on some training examples. We won't yet train the network. We will expand on this example soon." |
| 1124 | + "In this example, we will compute the loss function on some training examples and update the parameters with backpropagation." |
1120 | 1125 | ]
|
1121 | 1126 | },
|
1122 | 1127 | {
|
|
1689 | 1694 | "print tag_scores"
|
1690 | 1695 | ]
|
1691 | 1696 | },
|
| 1697 | + { |
| 1698 | + "cell_type": "markdown", |
| 1699 | + "metadata": {}, |
| 1700 | + "source": [ |
| 1701 | + "### Example: An LSTM Language Model\n", |
| 1702 | + "TODO" |
| 1703 | + ] |
| 1704 | + }, |
1692 | 1705 | {
|
1693 | 1706 | "cell_type": "markdown",
|
1694 | 1707 | "metadata": {},
|
|
0 commit comments