Upload 3 files
Browse files- Main-notebook-part-5.ipynb +707 -0
- README.md +56 -0
- names.txt +0 -0
Main-notebook-part-5.ipynb
ADDED
|
@@ -0,0 +1,707 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": null,
|
| 6 |
+
"metadata": {
|
| 7 |
+
"id": "7lDFibCgbHwr"
|
| 8 |
+
},
|
| 9 |
+
"outputs": [],
|
| 10 |
+
"source": [
|
| 11 |
+
"import torch\n",
|
| 12 |
+
"import torch.nn.functional as F\n",
|
| 13 |
+
"import matplotlib.pyplot as plt # for making figures\n",
|
| 14 |
+
"%matplotlib inline"
|
| 15 |
+
]
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"cell_type": "code",
|
| 19 |
+
"execution_count": null,
|
| 20 |
+
"metadata": {
|
| 21 |
+
"id": "htdQCnUPbhS9"
|
| 22 |
+
},
|
| 23 |
+
"outputs": [],
|
| 24 |
+
"source": [
|
| 25 |
+
"# download the names.txt file from github\n",
|
| 26 |
+
"!wget https://raw.githubusercontent.com/karpathy/makemore/master/names.txt"
|
| 27 |
+
]
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
"cell_type": "code",
|
| 31 |
+
"execution_count": null,
|
| 32 |
+
"metadata": {
|
| 33 |
+
"id": "ylW9Ir3GbHws",
|
| 34 |
+
"outputId": "0c874340-2a0f-4d12-fcb0-2035564cebf3"
|
| 35 |
+
},
|
| 36 |
+
"outputs": [
|
| 37 |
+
{
|
| 38 |
+
"name": "stdout",
|
| 39 |
+
"output_type": "stream",
|
| 40 |
+
"text": [
|
| 41 |
+
"32033\n",
|
| 42 |
+
"15\n",
|
| 43 |
+
"['emma', 'olivia', 'ava', 'isabella', 'sophia', 'charlotte', 'mia', 'amelia']\n"
|
| 44 |
+
]
|
| 45 |
+
}
|
| 46 |
+
],
|
| 47 |
+
"source": [
|
| 48 |
+
"# read in all the words\n",
|
| 49 |
+
"words = open('names.txt', 'r').read().splitlines()\n",
|
| 50 |
+
"print(len(words))\n",
|
| 51 |
+
"print(max(len(w) for w in words))\n",
|
| 52 |
+
"print(words[:8])"
|
| 53 |
+
]
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"cell_type": "code",
|
| 57 |
+
"execution_count": null,
|
| 58 |
+
"metadata": {
|
| 59 |
+
"id": "GPwi-_rEbHwt",
|
| 60 |
+
"outputId": "237fb410-4940-448b-a00b-0ab334f768e3"
|
| 61 |
+
},
|
| 62 |
+
"outputs": [
|
| 63 |
+
{
|
| 64 |
+
"name": "stdout",
|
| 65 |
+
"output_type": "stream",
|
| 66 |
+
"text": [
|
| 67 |
+
"{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i', 10: 'j', 11: 'k', 12: 'l', 13: 'm', 14: 'n', 15: 'o', 16: 'p', 17: 'q', 18: 'r', 19: 's', 20: 't', 21: 'u', 22: 'v', 23: 'w', 24: 'x', 25: 'y', 26: 'z', 0: '.'}\n",
|
| 68 |
+
"27\n"
|
| 69 |
+
]
|
| 70 |
+
}
|
| 71 |
+
],
|
| 72 |
+
"source": [
|
| 73 |
+
"# build the vocabulary of characters and mappings to/from integers\n",
|
| 74 |
+
"chars = sorted(list(set(''.join(words))))\n",
|
| 75 |
+
"stoi = {s:i+1 for i,s in enumerate(chars)}\n",
|
| 76 |
+
"stoi['.'] = 0\n",
|
| 77 |
+
"itos = {i:s for s,i in stoi.items()}\n",
|
| 78 |
+
"vocab_size = len(itos)\n",
|
| 79 |
+
"print(itos)\n",
|
| 80 |
+
"print(vocab_size)"
|
| 81 |
+
]
|
| 82 |
+
},
|
| 83 |
+
{
|
| 84 |
+
"cell_type": "code",
|
| 85 |
+
"execution_count": null,
|
| 86 |
+
"metadata": {
|
| 87 |
+
"id": "j8JdduA3bHwu"
|
| 88 |
+
},
|
| 89 |
+
"outputs": [],
|
| 90 |
+
"source": [
|
| 91 |
+
"# shuffle up the words\n",
|
| 92 |
+
"import random\n",
|
| 93 |
+
"random.seed(42)\n",
|
| 94 |
+
"random.shuffle(words)"
|
| 95 |
+
]
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"cell_type": "code",
|
| 99 |
+
"execution_count": null,
|
| 100 |
+
"metadata": {
|
| 101 |
+
"id": "kcrfsUG_bHwu",
|
| 102 |
+
"outputId": "4d05c8d0-9d1f-4b1e-dfdb-db2becfe8afc"
|
| 103 |
+
},
|
| 104 |
+
"outputs": [
|
| 105 |
+
{
|
| 106 |
+
"name": "stdout",
|
| 107 |
+
"output_type": "stream",
|
| 108 |
+
"text": [
|
| 109 |
+
"torch.Size([182625, 8]) torch.Size([182625])\n",
|
| 110 |
+
"torch.Size([22655, 8]) torch.Size([22655])\n",
|
| 111 |
+
"torch.Size([22866, 8]) torch.Size([22866])\n"
|
| 112 |
+
]
|
| 113 |
+
}
|
| 114 |
+
],
|
| 115 |
+
"source": [
|
| 116 |
+
"# build the dataset\n",
|
| 117 |
+
"block_size = 8 # context length: how many characters do we take to predict the next one?\n",
|
| 118 |
+
"\n",
|
| 119 |
+
"def build_dataset(words):\n",
|
| 120 |
+
" X, Y = [], []\n",
|
| 121 |
+
"\n",
|
| 122 |
+
" for w in words:\n",
|
| 123 |
+
" context = [0] * block_size\n",
|
| 124 |
+
" for ch in w + '.':\n",
|
| 125 |
+
" ix = stoi[ch]\n",
|
| 126 |
+
" X.append(context)\n",
|
| 127 |
+
" Y.append(ix)\n",
|
| 128 |
+
" context = context[1:] + [ix] # crop and append\n",
|
| 129 |
+
"\n",
|
| 130 |
+
" X = torch.tensor(X)\n",
|
| 131 |
+
" Y = torch.tensor(Y)\n",
|
| 132 |
+
" print(X.shape, Y.shape)\n",
|
| 133 |
+
" return X, Y\n",
|
| 134 |
+
"\n",
|
| 135 |
+
"n1 = int(0.8*len(words))\n",
|
| 136 |
+
"n2 = int(0.9*len(words))\n",
|
| 137 |
+
"Xtr, Ytr = build_dataset(words[:n1]) # 80%\n",
|
| 138 |
+
"Xdev, Ydev = build_dataset(words[n1:n2]) # 10%\n",
|
| 139 |
+
"Xte, Yte = build_dataset(words[n2:]) # 10%"
|
| 140 |
+
]
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"cell_type": "code",
|
| 144 |
+
"execution_count": null,
|
| 145 |
+
"metadata": {
|
| 146 |
+
"id": "9aFDMks6bHwv",
|
| 147 |
+
"outputId": "2bb77886-1172-4b43-f446-b2e990e549aa"
|
| 148 |
+
},
|
| 149 |
+
"outputs": [
|
| 150 |
+
{
|
| 151 |
+
"name": "stdout",
|
| 152 |
+
"output_type": "stream",
|
| 153 |
+
"text": [
|
| 154 |
+
"........ --> y\n",
|
| 155 |
+
".......y --> u\n",
|
| 156 |
+
"......yu --> h\n",
|
| 157 |
+
".....yuh --> e\n",
|
| 158 |
+
"....yuhe --> n\n",
|
| 159 |
+
"...yuhen --> g\n",
|
| 160 |
+
"..yuheng --> .\n",
|
| 161 |
+
"........ --> d\n",
|
| 162 |
+
".......d --> i\n",
|
| 163 |
+
"......di --> o\n",
|
| 164 |
+
".....dio --> n\n",
|
| 165 |
+
"....dion --> d\n",
|
| 166 |
+
"...diond --> r\n",
|
| 167 |
+
"..diondr --> e\n",
|
| 168 |
+
".diondre --> .\n",
|
| 169 |
+
"........ --> x\n",
|
| 170 |
+
".......x --> a\n",
|
| 171 |
+
"......xa --> v\n",
|
| 172 |
+
".....xav --> i\n",
|
| 173 |
+
"....xavi --> e\n"
|
| 174 |
+
]
|
| 175 |
+
}
|
| 176 |
+
],
|
| 177 |
+
"source": [
|
| 178 |
+
"for x,y in zip(Xtr[:20], Ytr[:20]):\n",
|
| 179 |
+
" print(''.join(itos[ix.item()] for ix in x), '-->', itos[y.item()])"
|
| 180 |
+
]
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"cell_type": "code",
|
| 184 |
+
"execution_count": null,
|
| 185 |
+
"metadata": {
|
| 186 |
+
"id": "-goFZmrabHww"
|
| 187 |
+
},
|
| 188 |
+
"outputs": [],
|
| 189 |
+
"source": [
|
| 190 |
+
"# Near copy paste of the layers we have developed in Part 3\n",
|
| 191 |
+
"\n",
|
| 192 |
+
"# -----------------------------------------------------------------------------------------------\n",
|
| 193 |
+
"class Linear:\n",
|
| 194 |
+
"\n",
|
| 195 |
+
" def __init__(self, fan_in, fan_out, bias=True):\n",
|
| 196 |
+
" self.weight = torch.randn((fan_in, fan_out)) / fan_in**0.5 # note: kaiming init\n",
|
| 197 |
+
" self.bias = torch.zeros(fan_out) if bias else None\n",
|
| 198 |
+
"\n",
|
| 199 |
+
" def __call__(self, x):\n",
|
| 200 |
+
" self.out = x @ self.weight\n",
|
| 201 |
+
" if self.bias is not None:\n",
|
| 202 |
+
" self.out += self.bias\n",
|
| 203 |
+
" return self.out\n",
|
| 204 |
+
"\n",
|
| 205 |
+
" def parameters(self):\n",
|
| 206 |
+
" return [self.weight] + ([] if self.bias is None else [self.bias])\n",
|
| 207 |
+
"\n",
|
| 208 |
+
"# -----------------------------------------------------------------------------------------------\n",
|
| 209 |
+
"class BatchNorm1d:\n",
|
| 210 |
+
"\n",
|
| 211 |
+
" def __init__(self, dim, eps=1e-5, momentum=0.1):\n",
|
| 212 |
+
" self.eps = eps\n",
|
| 213 |
+
" self.momentum = momentum\n",
|
| 214 |
+
" self.training = True\n",
|
| 215 |
+
" # parameters (trained with backprop)\n",
|
| 216 |
+
" self.gamma = torch.ones(dim)\n",
|
| 217 |
+
" self.beta = torch.zeros(dim)\n",
|
| 218 |
+
" # buffers (trained with a running 'momentum update')\n",
|
| 219 |
+
" self.running_mean = torch.zeros(dim)\n",
|
| 220 |
+
" self.running_var = torch.ones(dim)\n",
|
| 221 |
+
"\n",
|
| 222 |
+
" def __call__(self, x):\n",
|
| 223 |
+
" # calculate the forward pass\n",
|
| 224 |
+
" if self.training:\n",
|
| 225 |
+
" if x.ndim == 2:\n",
|
| 226 |
+
" dim = 0\n",
|
| 227 |
+
" elif x.ndim == 3:\n",
|
| 228 |
+
" dim = (0,1)\n",
|
| 229 |
+
" xmean = x.mean(dim, keepdim=True) # batch mean\n",
|
| 230 |
+
" xvar = x.var(dim, keepdim=True) # batch variance\n",
|
| 231 |
+
" else:\n",
|
| 232 |
+
" xmean = self.running_mean\n",
|
| 233 |
+
" xvar = self.running_var\n",
|
| 234 |
+
" xhat = (x - xmean) / torch.sqrt(xvar + self.eps) # normalize to unit variance\n",
|
| 235 |
+
" self.out = self.gamma * xhat + self.beta\n",
|
| 236 |
+
" # update the buffers\n",
|
| 237 |
+
" if self.training:\n",
|
| 238 |
+
" with torch.no_grad():\n",
|
| 239 |
+
" self.running_mean = (1 - self.momentum) * self.running_mean + self.momentum * xmean\n",
|
| 240 |
+
" self.running_var = (1 - self.momentum) * self.running_var + self.momentum * xvar\n",
|
| 241 |
+
" return self.out\n",
|
| 242 |
+
"\n",
|
| 243 |
+
" def parameters(self):\n",
|
| 244 |
+
" return [self.gamma, self.beta]\n",
|
| 245 |
+
"\n",
|
| 246 |
+
"# -----------------------------------------------------------------------------------------------\n",
|
| 247 |
+
"class Tanh:\n",
|
| 248 |
+
" def __call__(self, x):\n",
|
| 249 |
+
" self.out = torch.tanh(x)\n",
|
| 250 |
+
" return self.out\n",
|
| 251 |
+
" def parameters(self):\n",
|
| 252 |
+
" return []\n",
|
| 253 |
+
"\n",
|
| 254 |
+
"# -----------------------------------------------------------------------------------------------\n",
|
| 255 |
+
"class Embedding:\n",
|
| 256 |
+
"\n",
|
| 257 |
+
" def __init__(self, num_embeddings, embedding_dim):\n",
|
| 258 |
+
" self.weight = torch.randn((num_embeddings, embedding_dim))\n",
|
| 259 |
+
"\n",
|
| 260 |
+
" def __call__(self, IX):\n",
|
| 261 |
+
" self.out = self.weight[IX]\n",
|
| 262 |
+
" return self.out\n",
|
| 263 |
+
"\n",
|
| 264 |
+
" def parameters(self):\n",
|
| 265 |
+
" return [self.weight]\n",
|
| 266 |
+
"\n",
|
| 267 |
+
"# -----------------------------------------------------------------------------------------------\n",
|
| 268 |
+
"class FlattenConsecutive:\n",
|
| 269 |
+
"\n",
|
| 270 |
+
" def __init__(self, n):\n",
|
| 271 |
+
" self.n = n\n",
|
| 272 |
+
"\n",
|
| 273 |
+
" def __call__(self, x):\n",
|
| 274 |
+
" B, T, C = x.shape\n",
|
| 275 |
+
" x = x.view(B, T//self.n, C*self.n)\n",
|
| 276 |
+
" if x.shape[1] == 1:\n",
|
| 277 |
+
" x = x.squeeze(1)\n",
|
| 278 |
+
" self.out = x\n",
|
| 279 |
+
" return self.out\n",
|
| 280 |
+
"\n",
|
| 281 |
+
" def parameters(self):\n",
|
| 282 |
+
" return []\n",
|
| 283 |
+
"\n",
|
| 284 |
+
"# -----------------------------------------------------------------------------------------------\n",
|
| 285 |
+
"class Sequential:\n",
|
| 286 |
+
"\n",
|
| 287 |
+
" def __init__(self, layers):\n",
|
| 288 |
+
" self.layers = layers\n",
|
| 289 |
+
"\n",
|
| 290 |
+
" def __call__(self, x):\n",
|
| 291 |
+
" for layer in self.layers:\n",
|
| 292 |
+
" x = layer(x)\n",
|
| 293 |
+
" self.out = x\n",
|
| 294 |
+
" return self.out\n",
|
| 295 |
+
"\n",
|
| 296 |
+
" def parameters(self):\n",
|
| 297 |
+
" # get parameters of all layers and stretch them out into one list\n",
|
| 298 |
+
" return [p for layer in self.layers for p in layer.parameters()]\n"
|
| 299 |
+
]
|
| 300 |
+
},
|
| 301 |
+
{
|
| 302 |
+
"cell_type": "code",
|
| 303 |
+
"execution_count": null,
|
| 304 |
+
"metadata": {
|
| 305 |
+
"id": "v01gpFOSbHwx"
|
| 306 |
+
},
|
| 307 |
+
"outputs": [],
|
| 308 |
+
"source": [
|
| 309 |
+
"torch.manual_seed(42); # seed rng for reproducibility"
|
| 310 |
+
]
|
| 311 |
+
},
|
| 312 |
+
{
|
| 313 |
+
"cell_type": "code",
|
| 314 |
+
"execution_count": null,
|
| 315 |
+
"metadata": {
|
| 316 |
+
"id": "vHMDMtvpbHwx",
|
| 317 |
+
"outputId": "dbb414a9-5753-4f41-c545-34957779b09e"
|
| 318 |
+
},
|
| 319 |
+
"outputs": [
|
| 320 |
+
{
|
| 321 |
+
"name": "stdout",
|
| 322 |
+
"output_type": "stream",
|
| 323 |
+
"text": [
|
| 324 |
+
"76579\n"
|
| 325 |
+
]
|
| 326 |
+
}
|
| 327 |
+
],
|
| 328 |
+
"source": [
|
| 329 |
+
"# original network\n",
|
| 330 |
+
"# n_embd = 10 # the dimensionality of the character embedding vectors\n",
|
| 331 |
+
"# n_hidden = 300 # the number of neurons in the hidden layer of the MLP\n",
|
| 332 |
+
"# model = Sequential([\n",
|
| 333 |
+
"# Embedding(vocab_size, n_embd),\n",
|
| 334 |
+
"# FlattenConsecutive(8), Linear(n_embd * 8, n_hidden, bias=False), BatchNorm1d(n_hidden), Tanh(),\n",
|
| 335 |
+
"# Linear(n_hidden, vocab_size),\n",
|
| 336 |
+
"# ])\n",
|
| 337 |
+
"\n",
|
| 338 |
+
"# hierarchical network\n",
|
| 339 |
+
"n_embd = 24 # the dimensionality of the character embedding vectors\n",
|
| 340 |
+
"n_hidden = 128 # the number of neurons in the hidden layer of the MLP\n",
|
| 341 |
+
"model = Sequential([\n",
|
| 342 |
+
" Embedding(vocab_size, n_embd),\n",
|
| 343 |
+
" FlattenConsecutive(2), Linear(n_embd * 2, n_hidden, bias=False), BatchNorm1d(n_hidden), Tanh(),\n",
|
| 344 |
+
" FlattenConsecutive(2), Linear(n_hidden*2, n_hidden, bias=False), BatchNorm1d(n_hidden), Tanh(),\n",
|
| 345 |
+
" FlattenConsecutive(2), Linear(n_hidden*2, n_hidden, bias=False), BatchNorm1d(n_hidden), Tanh(),\n",
|
| 346 |
+
" Linear(n_hidden, vocab_size),\n",
|
| 347 |
+
"])\n",
|
| 348 |
+
"\n",
|
| 349 |
+
"# parameter init\n",
|
| 350 |
+
"with torch.no_grad():\n",
|
| 351 |
+
" model.layers[-1].weight *= 0.1 # last layer make less confident\n",
|
| 352 |
+
"\n",
|
| 353 |
+
"parameters = model.parameters()\n",
|
| 354 |
+
"print(sum(p.nelement() for p in parameters)) # number of parameters in total\n",
|
| 355 |
+
"for p in parameters:\n",
|
| 356 |
+
" p.requires_grad = True"
|
| 357 |
+
]
|
| 358 |
+
},
|
| 359 |
+
{
|
| 360 |
+
"cell_type": "code",
|
| 361 |
+
"execution_count": null,
|
| 362 |
+
"metadata": {
|
| 363 |
+
"id": "Sh9SEATabHwy",
|
| 364 |
+
"outputId": "4238b680-4e09-4da1-a52f-5153a4119ba5"
|
| 365 |
+
},
|
| 366 |
+
"outputs": [
|
| 367 |
+
{
|
| 368 |
+
"name": "stdout",
|
| 369 |
+
"output_type": "stream",
|
| 370 |
+
"text": [
|
| 371 |
+
" 0/ 200000: 3.3167\n",
|
| 372 |
+
" 10000/ 200000: 2.0576\n",
|
| 373 |
+
" 20000/ 200000: 2.0723\n",
|
| 374 |
+
" 30000/ 200000: 2.5134\n",
|
| 375 |
+
" 40000/ 200000: 2.1476\n",
|
| 376 |
+
" 50000/ 200000: 1.7836\n",
|
| 377 |
+
" 60000/ 200000: 2.2592\n",
|
| 378 |
+
" 70000/ 200000: 1.9331\n",
|
| 379 |
+
" 80000/ 200000: 1.6875\n",
|
| 380 |
+
" 90000/ 200000: 2.0395\n",
|
| 381 |
+
" 100000/ 200000: 1.7736\n",
|
| 382 |
+
" 110000/ 200000: 1.9570\n",
|
| 383 |
+
" 120000/ 200000: 1.7465\n",
|
| 384 |
+
" 130000/ 200000: 1.8126\n",
|
| 385 |
+
" 140000/ 200000: 1.7406\n",
|
| 386 |
+
" 150000/ 200000: 1.7466\n",
|
| 387 |
+
" 160000/ 200000: 1.8806\n",
|
| 388 |
+
" 170000/ 200000: 1.6266\n",
|
| 389 |
+
" 180000/ 200000: 1.6476\n",
|
| 390 |
+
" 190000/ 200000: 1.8555\n"
|
| 391 |
+
]
|
| 392 |
+
}
|
| 393 |
+
],
|
| 394 |
+
"source": [
|
| 395 |
+
"# same optimization as last time\n",
|
| 396 |
+
"max_steps = 200000\n",
|
| 397 |
+
"batch_size = 32\n",
|
| 398 |
+
"lossi = []\n",
|
| 399 |
+
"\n",
|
| 400 |
+
"for i in range(max_steps):\n",
|
| 401 |
+
"\n",
|
| 402 |
+
" # minibatch construct\n",
|
| 403 |
+
" ix = torch.randint(0, Xtr.shape[0], (batch_size,))\n",
|
| 404 |
+
" Xb, Yb = Xtr[ix], Ytr[ix] # batch X,Y\n",
|
| 405 |
+
"\n",
|
| 406 |
+
" # forward pass\n",
|
| 407 |
+
" logits = model(Xb)\n",
|
| 408 |
+
" loss = F.cross_entropy(logits, Yb) # loss function\n",
|
| 409 |
+
"\n",
|
| 410 |
+
" # backward pass\n",
|
| 411 |
+
" for p in parameters:\n",
|
| 412 |
+
" p.grad = None\n",
|
| 413 |
+
" loss.backward()\n",
|
| 414 |
+
"\n",
|
| 415 |
+
" # update: simple SGD\n",
|
| 416 |
+
" lr = 0.1 if i < 150000 else 0.01 # step learning rate decay\n",
|
| 417 |
+
" for p in parameters:\n",
|
| 418 |
+
" p.data += -lr * p.grad\n",
|
| 419 |
+
"\n",
|
| 420 |
+
" # track stats\n",
|
| 421 |
+
" if i % 10000 == 0: # print every once in a while\n",
|
| 422 |
+
" print(f'{i:7d}/{max_steps:7d}: {loss.item():.4f}')\n",
|
| 423 |
+
" lossi.append(loss.log10().item())\n"
|
| 424 |
+
]
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"cell_type": "code",
|
| 428 |
+
"execution_count": null,
|
| 429 |
+
"metadata": {
|
| 430 |
+
"id": "XrOSTEFzbHwz",
|
| 431 |
+
"outputId": "64b7e0c9-a0a0-4daa-cee0-0c12541fa959"
|
| 432 |
+
},
|
| 433 |
+
"outputs": [
|
| 434 |
+
{
|
| 435 |
+
"data": {
|
| 436 |
+
"text/plain": [
|
| 437 |
+
"[<matplotlib.lines.Line2D at 0x7fb5a03e3b50>]"
|
| 438 |
+
]
|
| 439 |
+
},
|
| 440 |
+
"execution_count": 11,
|
| 441 |
+
"metadata": {},
|
| 442 |
+
"output_type": "execute_result"
|
| 443 |
+
},
|
| 444 |
+
{
|
| 445 |
+
"data": {
|
| 446 |
+
"image/png": "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",
|
| 447 |
+
"text/plain": [
|
| 448 |
+
"<Figure size 432x288 with 1 Axes>"
|
| 449 |
+
]
|
| 450 |
+
},
|
| 451 |
+
"metadata": {
|
| 452 |
+
"needs_background": "light"
|
| 453 |
+
},
|
| 454 |
+
"output_type": "display_data"
|
| 455 |
+
}
|
| 456 |
+
],
|
| 457 |
+
"source": [
|
| 458 |
+
"plt.plot(torch.tensor(lossi).view(-1, 1000).mean(1))"
|
| 459 |
+
]
|
| 460 |
+
},
|
| 461 |
+
{
|
| 462 |
+
"cell_type": "code",
|
| 463 |
+
"execution_count": null,
|
| 464 |
+
"metadata": {
|
| 465 |
+
"id": "ehknU7xtbHwz"
|
| 466 |
+
},
|
| 467 |
+
"outputs": [],
|
| 468 |
+
"source": [
|
| 469 |
+
"# put layers into eval mode (needed for batchnorm especially)\n",
|
| 470 |
+
"for layer in model.layers:\n",
|
| 471 |
+
" layer.training = False"
|
| 472 |
+
]
|
| 473 |
+
},
|
| 474 |
+
{
|
| 475 |
+
"cell_type": "code",
|
| 476 |
+
"execution_count": null,
|
| 477 |
+
"metadata": {
|
| 478 |
+
"id": "5W1wFpKubHwz",
|
| 479 |
+
"outputId": "a965238b-34f8-42de-e6d6-3777a6837cd1"
|
| 480 |
+
},
|
| 481 |
+
"outputs": [
|
| 482 |
+
{
|
| 483 |
+
"name": "stdout",
|
| 484 |
+
"output_type": "stream",
|
| 485 |
+
"text": [
|
| 486 |
+
"train 1.7690284252166748\n",
|
| 487 |
+
"val 1.9936515092849731\n"
|
| 488 |
+
]
|
| 489 |
+
}
|
| 490 |
+
],
|
| 491 |
+
"source": [
|
| 492 |
+
"# evaluate the loss\n",
|
| 493 |
+
"@torch.no_grad() # this decorator disables gradient tracking inside pytorch\n",
|
| 494 |
+
"def split_loss(split):\n",
|
| 495 |
+
" x,y = {\n",
|
| 496 |
+
" 'train': (Xtr, Ytr),\n",
|
| 497 |
+
" 'val': (Xdev, Ydev),\n",
|
| 498 |
+
" 'test': (Xte, Yte),\n",
|
| 499 |
+
" }[split]\n",
|
| 500 |
+
" logits = model(x)\n",
|
| 501 |
+
" loss = F.cross_entropy(logits, y)\n",
|
| 502 |
+
" print(split, loss.item())\n",
|
| 503 |
+
"\n",
|
| 504 |
+
"split_loss('train')\n",
|
| 505 |
+
"split_loss('val')"
|
| 506 |
+
]
|
| 507 |
+
},
|
| 508 |
+
{
|
| 509 |
+
"cell_type": "markdown",
|
| 510 |
+
"metadata": {
|
| 511 |
+
"id": "yQdB3cZYbHw0"
|
| 512 |
+
},
|
| 513 |
+
"source": [
|
| 514 |
+
"### performance log\n",
|
| 515 |
+
"\n",
|
| 516 |
+
"- original (3 character context + 200 hidden neurons, 12K params): train 2.058, val 2.105\n",
|
| 517 |
+
"- context: 3 -> 8 (22K params): train 1.918, val 2.027\n",
|
| 518 |
+
"- flat -> hierarchical (22K params): train 1.941, val 2.029\n",
|
| 519 |
+
"- fix bug in batchnorm: train 1.912, val 2.022\n",
|
| 520 |
+
"- scale up the network: n_embd 24, n_hidden 128 (76K params): train 1.769, val 1.993\n"
|
| 521 |
+
]
|
| 522 |
+
},
|
| 523 |
+
{
|
| 524 |
+
"cell_type": "code",
|
| 525 |
+
"execution_count": null,
|
| 526 |
+
"metadata": {
|
| 527 |
+
"id": "CSE5ZEgebHw0",
|
| 528 |
+
"outputId": "b8f5baf1-143e-4fd6-8e14-cc1d1bd3a0b3"
|
| 529 |
+
},
|
| 530 |
+
"outputs": [
|
| 531 |
+
{
|
| 532 |
+
"name": "stdout",
|
| 533 |
+
"output_type": "stream",
|
| 534 |
+
"text": [
|
| 535 |
+
"arlij.\n",
|
| 536 |
+
"chetta.\n",
|
| 537 |
+
"heago.\n",
|
| 538 |
+
"rocklei.\n",
|
| 539 |
+
"hendrix.\n",
|
| 540 |
+
"jamylie.\n",
|
| 541 |
+
"broxin.\n",
|
| 542 |
+
"denish.\n",
|
| 543 |
+
"anslibt.\n",
|
| 544 |
+
"marianah.\n",
|
| 545 |
+
"astavia.\n",
|
| 546 |
+
"annayve.\n",
|
| 547 |
+
"aniah.\n",
|
| 548 |
+
"jayce.\n",
|
| 549 |
+
"nodiel.\n",
|
| 550 |
+
"remita.\n",
|
| 551 |
+
"niyelle.\n",
|
| 552 |
+
"jaylene.\n",
|
| 553 |
+
"aiyan.\n",
|
| 554 |
+
"aubreana.\n"
|
| 555 |
+
]
|
| 556 |
+
}
|
| 557 |
+
],
|
| 558 |
+
"source": [
|
| 559 |
+
"# sample from the model\n",
|
| 560 |
+
"for _ in range(20):\n",
|
| 561 |
+
"\n",
|
| 562 |
+
" out = []\n",
|
| 563 |
+
" context = [0] * block_size # initialize with all ...\n",
|
| 564 |
+
" while True:\n",
|
| 565 |
+
" # forward pass the neural net\n",
|
| 566 |
+
" logits = model(torch.tensor([context]))\n",
|
| 567 |
+
" probs = F.softmax(logits, dim=1)\n",
|
| 568 |
+
" # sample from the distribution\n",
|
| 569 |
+
" ix = torch.multinomial(probs, num_samples=1).item()\n",
|
| 570 |
+
" # shift the context window and track the samples\n",
|
| 571 |
+
" context = context[1:] + [ix]\n",
|
| 572 |
+
" out.append(ix)\n",
|
| 573 |
+
" # if we sample the special '.' token, break\n",
|
| 574 |
+
" if ix == 0:\n",
|
| 575 |
+
" break\n",
|
| 576 |
+
"\n",
|
| 577 |
+
" print(''.join(itos[i] for i in out)) # decode and print the generated word"
|
| 578 |
+
]
|
| 579 |
+
},
|
| 580 |
+
{
|
| 581 |
+
"cell_type": "markdown",
|
| 582 |
+
"metadata": {
|
| 583 |
+
"id": "5w054JOpbHw1"
|
| 584 |
+
},
|
| 585 |
+
"source": [
|
| 586 |
+
"### Next time:\n",
|
| 587 |
+
"Why convolutions? Brief preview/hint"
|
| 588 |
+
]
|
| 589 |
+
},
|
| 590 |
+
{
|
| 591 |
+
"cell_type": "code",
|
| 592 |
+
"execution_count": null,
|
| 593 |
+
"metadata": {
|
| 594 |
+
"id": "zBP4pbSnbHw1",
|
| 595 |
+
"outputId": "5dc847b5-d40b-4e6a-f25b-55eedc770b39"
|
| 596 |
+
},
|
| 597 |
+
"outputs": [
|
| 598 |
+
{
|
| 599 |
+
"name": "stdout",
|
| 600 |
+
"output_type": "stream",
|
| 601 |
+
"text": [
|
| 602 |
+
"........ --> d\n",
|
| 603 |
+
".......d --> i\n",
|
| 604 |
+
"......di --> o\n",
|
| 605 |
+
".....dio --> n\n",
|
| 606 |
+
"....dion --> d\n",
|
| 607 |
+
"...diond --> r\n",
|
| 608 |
+
"..diondr --> e\n",
|
| 609 |
+
".diondre --> .\n"
|
| 610 |
+
]
|
| 611 |
+
}
|
| 612 |
+
],
|
| 613 |
+
"source": [
|
| 614 |
+
"for x,y in zip(Xtr[7:15], Ytr[7:15]):\n",
|
| 615 |
+
" print(''.join(itos[ix.item()] for ix in x), '-->', itos[y.item()])"
|
| 616 |
+
]
|
| 617 |
+
},
|
| 618 |
+
{
|
| 619 |
+
"cell_type": "code",
|
| 620 |
+
"execution_count": null,
|
| 621 |
+
"metadata": {
|
| 622 |
+
"id": "HhUwWXX8bHw2",
|
| 623 |
+
"outputId": "9d5d20ce-180c-4178-fd22-3e7a7dcc38ff"
|
| 624 |
+
},
|
| 625 |
+
"outputs": [
|
| 626 |
+
{
|
| 627 |
+
"data": {
|
| 628 |
+
"text/plain": [
|
| 629 |
+
"torch.Size([1, 27])"
|
| 630 |
+
]
|
| 631 |
+
},
|
| 632 |
+
"execution_count": 16,
|
| 633 |
+
"metadata": {},
|
| 634 |
+
"output_type": "execute_result"
|
| 635 |
+
}
|
| 636 |
+
],
|
| 637 |
+
"source": [
|
| 638 |
+
"# forward a single example:\n",
|
| 639 |
+
"logits = model(Xtr[[7]])\n",
|
| 640 |
+
"logits.shape"
|
| 641 |
+
]
|
| 642 |
+
},
|
| 643 |
+
{
|
| 644 |
+
"cell_type": "code",
|
| 645 |
+
"execution_count": null,
|
| 646 |
+
"metadata": {
|
| 647 |
+
"id": "gBDyYGUWbHw2",
|
| 648 |
+
"outputId": "f288231e-6a20-4940-845f-596944950912"
|
| 649 |
+
},
|
| 650 |
+
"outputs": [
|
| 651 |
+
{
|
| 652 |
+
"data": {
|
| 653 |
+
"text/plain": [
|
| 654 |
+
"torch.Size([8, 27])"
|
| 655 |
+
]
|
| 656 |
+
},
|
| 657 |
+
"execution_count": 17,
|
| 658 |
+
"metadata": {},
|
| 659 |
+
"output_type": "execute_result"
|
| 660 |
+
}
|
| 661 |
+
],
|
| 662 |
+
"source": [
|
| 663 |
+
"# forward all of them\n",
|
| 664 |
+
"logits = torch.zeros(8, 27)\n",
|
| 665 |
+
"for i in range(8):\n",
|
| 666 |
+
" logits[i] = model(Xtr[[7+i]])\n",
|
| 667 |
+
"logits.shape"
|
| 668 |
+
]
|
| 669 |
+
},
|
| 670 |
+
{
|
| 671 |
+
"cell_type": "code",
|
| 672 |
+
"execution_count": null,
|
| 673 |
+
"metadata": {
|
| 674 |
+
"id": "PCoo_TvZbHw3"
|
| 675 |
+
},
|
| 676 |
+
"outputs": [],
|
| 677 |
+
"source": [
|
| 678 |
+
"# convolution is a \"for loop\"\n",
|
| 679 |
+
"# allows us to forward Linear layers efficiently over space"
|
| 680 |
+
]
|
| 681 |
+
}
|
| 682 |
+
],
|
| 683 |
+
"metadata": {
|
| 684 |
+
"colab": {
|
| 685 |
+
"provenance": []
|
| 686 |
+
},
|
| 687 |
+
"kernelspec": {
|
| 688 |
+
"display_name": "Python 3",
|
| 689 |
+
"language": "python",
|
| 690 |
+
"name": "python3"
|
| 691 |
+
},
|
| 692 |
+
"language_info": {
|
| 693 |
+
"codemirror_mode": {
|
| 694 |
+
"name": "ipython",
|
| 695 |
+
"version": 3
|
| 696 |
+
},
|
| 697 |
+
"file_extension": ".py",
|
| 698 |
+
"mimetype": "text/x-python",
|
| 699 |
+
"name": "python",
|
| 700 |
+
"nbconvert_exporter": "python",
|
| 701 |
+
"pygments_lexer": "ipython3",
|
| 702 |
+
"version": "3.8.5"
|
| 703 |
+
}
|
| 704 |
+
},
|
| 705 |
+
"nbformat": 4,
|
| 706 |
+
"nbformat_minor": 0
|
| 707 |
+
}
|
README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
## SET 1 - MAKEMORE (PART 5) 🔗
|
| 2 |
+
|
| 3 |
+
[](https://muzzammilshah.github.io/Road-to-GPT/Makemore-part5/)
|
| 4 |
+

|
| 5 |
+
[](https://github.com/MuzzammilShah/NeuralNetworks-LanguageModels-5/commits/main)
|
| 6 |
+

|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
### **Overview**
|
| 11 |
+
|
| 12 |
+
We take the 2-layer MLP from previous video and make it deeper with a tree-like structure, arriving at a convolutional neural network architecture similar to the WaveNet (2016) from DeepMind. In the WaveNet paper, the same hierarchical architecture is implemented more efficiently using causal dilated convolutions (not yet covered). Along the way we get a better sense of `torch.nn` and what it is and how it works under the hood, and what a typical deep learning development process looks like.
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
### **🗂️Repository Structure**
|
| 17 |
+
|
| 18 |
+
```plaintext
|
| 19 |
+
├── .gitignore
|
| 20 |
+
├── Main-notebook-part-5.ipynb
|
| 21 |
+
├── README.md
|
| 22 |
+
├── notes/
|
| 23 |
+
│ ├── Main-makemore-part-5.md
|
| 24 |
+
│ └── README.md
|
| 25 |
+
└── names.txt
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
- **Notes Directory**: Contains detailed notes corresponding to each notebook section.
|
| 29 |
+
- **Jupyter Notebooks**: Step-by-step implementation and exploration of the concepts.
|
| 30 |
+
- **README.md**: Overview and guide for this repository.
|
| 31 |
+
- **names.txt**: Supplementary data file used in training the model.
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
### **📄Instructions**
|
| 36 |
+
|
| 37 |
+
To get the best understanding:
|
| 38 |
+
|
| 39 |
+
1. Start by reading the notes in the `notes/` directory. Each section corresponds to a notebook for step-by-step explanations.
|
| 40 |
+
2. Open the corresponding Jupyter Notebook.
|
| 41 |
+
3. Follow the code and comments for a deeper dive into the implementation details.
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
### **⭐Documentation**
|
| 46 |
+
|
| 47 |
+
For a better reading experience and detailed notes, visit my **[Road to GPT Documentation Site](https://muzzammilshah.github.io/Road-to-GPT/)**.
|
| 48 |
+
|
| 49 |
+
> **💡Pro Tip**: This site provides an interactive and visually rich explanation of the notes and code. It is highly recommended you view this project from there.
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
### **✍🏻Acknowledgments**
|
| 54 |
+
Notes and implementations inspired by the **Makemore - Part 5** video by [Andrej Karpathy](https://karpathy.ai/).
|
| 55 |
+
|
| 56 |
+
For more of my projects, visit my [Portfolio Site](https://muhammedshah.com).
|
names.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|