MuzzammilShah commited on
Commit
0da3d0b
·
verified ·
1 Parent(s): 4d145e7

Upload 3 files

Browse files
Files changed (3) hide show
  1. Main-notebook-part-5.ipynb +707 -0
  2. README.md +56 -0
  3. 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
+ [![Documentation](https://img.shields.io/badge/Documentation-Available-blue)](https://muzzammilshah.github.io/Road-to-GPT/Makemore-part5/)
4
+ ![Number of Commits](https://img.shields.io/github/commit-activity/m/MuzzammilShah/NeuralNetworks-LanguageModels-5?label=Commits)
5
+ [![Last Commit](https://img.shields.io/github/last-commit/MuzzammilShah/NeuralNetworks-LanguageModels-5.svg?style=flat)](https://github.com/MuzzammilShah/NeuralNetworks-LanguageModels-5/commits/main)
6
+ ![Project Status](https://img.shields.io/badge/Status-Done-success)
7
+
8
+ &nbsp;
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
+ &nbsp;
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
+ &nbsp;
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
+ &nbsp;
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
+ &nbsp;
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