YouTube2Text

Building makemore Part 5: Building a WaveNet — Transcript

by Andrej Karpathy · 10,385 words · 1,559 segments · language en · Watch on YouTube

Full transcript

  1. 0:00hi everyone today we are continuing our
  2. 0:02implementation of make more our favorite
  3. 0:04character level language model
  4. 0:06now you'll notice that the background
  5. 0:07behind me is different that's because I
  6. 0:09am in Kyoto and it is awesome so I'm in
  7. 0:12a hotel room here
  8. 0:13now over the last few lectures we've
  9. 0:15built up to this architecture that is a
  10. 0:17multi-layer perceptron character level
  11. 0:19language model so we see that it
  12. 0:21receives three previous characters and
  13. 0:23tries to predict the fourth character in
  14. 0:24a sequence using a very simple multi
  15. 0:26perceptron using one hidden layer of
  16. 0:28neurons with 10ational neuralities
  17. 0:31so we'd like to do now in this lecture
  18. 0:33is I'd like to complexify this
  19. 0:34architecture in particular we would like
  20. 0:36to take more characters in a sequence as
  21. 0:38an input not just three and in addition
  22. 0:41to that we don't just want to feed them
  23. 0:42all into a single hidden layer because
  24. 0:45that squashes too much information too
  25. 0:46quickly instead we would like to make a
  26. 0:49deeper model that progressively fuses
  27. 0:51this information to make its guess about
  28. 0:53the next character in a sequence
  29. 0:55and so we'll see that as we make this
  30. 0:57architecture more complex we're actually
  31. 0:59going to arrive at something that looks
  32. 1:01very much like a wavenet
  33. 1:03the witness is this paper published by
  34. 1:05the point in 2016 and it is also a
  35. 1:09language model basically but it tries to
  36. 1:11predict audio sequences instead of
  37. 1:13character level sequences or Word level
  38. 1:15sequences but fundamentally the modeling
  39. 1:18setup is identical it is an auto
  40. 1:20aggressive model and it tries to predict
  41. 1:23next character in a sequence and the
  42. 1:25architecture actually takes this
  43. 1:26interesting hierarchical sort of
  44. 1:29approach to predicting the next
  45. 1:31character in a sequence uh with the
  46. 1:33street-like structure and this is the
  47. 1:35architecture and we're going to
  48. 1:36implement it in the course of this video
  49. 1:38so let's get started so the starter code
  50. 1:41for part five is very similar to where
  51. 1:43we ended up in in part three recall that
  52. 1:46part four was the manual black
  53. 1:47replication exercise that is kind of an
  54. 1:49aside so we are coming back to part
  55. 1:51three copy pasting chunks out of it and
  56. 1:53that is our starter code for part five
  57. 1:55I've changed very few things otherwise
  58. 1:57so a lot of this should look familiar to
  59. 1:59if you've gone through part three so in
  60. 2:01particular very briefly we are doing
  61. 2:03Imports we are reading our our data set
  62. 2:05of words and we are processing their set
  63. 2:09of words into individual examples and
  64. 2:11none of this data generation code has
  65. 2:13changed and basically we have lots and
  66. 2:15lots of examples in particular we have
  67. 2:17182 000 examples of three characters try
  68. 2:21to predict the fourth one and we've
  69. 2:24broken up every one of these words into
  70. 2:25little problems of given three
  71. 2:27characters predict the fourth one so
  72. 2:29this is our data set and this is what
  73. 2:30we're trying to get the neural lot to do
  74. 2:32now in part three we started to develop
  75. 2:35our code around these layer modules
  76. 2:39um that are for example like class
  77. 2:40linear and we're doing this because we
  78. 2:42want to think of these modules as
  79. 2:44building blocks and like a Lego building
  80. 2:47block bricks that we can sort of like
  81. 2:49stack up into neural networks and we can
  82. 2:51feed data between these layers and stack
  83. 2:53them up into a sort of graphs
  84. 2:56now we also developed these layers to
  85. 2:59have apis and signatures very similar to
  86. 3:01those that are found in pytorch so we
  87. 3:04have torch.nn and it's got all these
  88. 3:05layer building blocks that you would use
  89. 3:07in practice and we were developing all
  90. 3:09of these to mimic the apis of these so
  91. 3:11for example we have linear so there will
  92. 3:13also be a torch.nn.linear and its
  93. 3:17signature will be very similar to our
  94. 3:18signature and the functionality will be
  95. 3:20also quite identical as far as I'm aware
  96. 3:22so we have the linear layer with the
  97. 3:24Bass from 1D layer and the 10h layer
  98. 3:27that we developed previously
  99. 3:29and linear just as a matrix multiply in
  100. 3:32the forward pass of this module batch
  101. 3:35number of course is this crazy layer
  102. 3:36that we developed in the previous
  103. 3:37lecture and what's crazy about it is
  104. 3:40well there's many things number one it
  105. 3:42has these running mean and variances
  106. 3:44that are trained outside of back
  107. 3:46propagation they are trained using
  108. 3:49exponential moving average inside this
  109. 3:52layer when we call the forward pass
  110. 3:54in addition to that
  111. 3:56there's this training plug because the
  112. 3:58behavior of bathroom is different during
  113. 3:59train time and evaluation time and so
  114. 4:02suddenly we have to be very careful that
  115. 4:03bash form is in its correct state that
  116. 4:05it's in the evaluation state or training
  117. 4:07state so that's something to now keep
  118. 4:08track of something that sometimes
  119. 4:10introduces bugs
  120. 4:11uh because you forget to put it into the
  121. 4:13right mode and finally we saw that
  122. 4:15Bachelor couples the statistics or the
  123. 4:18the activations across the examples in
  124. 4:20the batch so normally we thought of the
  125. 4:22bat as just an efficiency thing but now
  126. 4:25we are coupling the computation across
  127. 4:28batch elements and it's done for the
  128. 4:30purposes of controlling the automation
  129. 4:32statistics as we saw in the previous
  130. 4:33video
  131. 4:34so it's a very weird layer at least a
  132. 4:36lot of bugs
  133. 4:38partly for example because you have to
  134. 4:40modulate the training in eval phase and
  135. 4:42so on
  136. 4:44um in addition for example you have to
  137. 4:46wait for uh the mean and the variance to
  138. 4:49settle and to actually reach a steady
  139. 4:51state and so um you have to make sure
  140. 4:53that you basically there's state in this
  141. 4:55layer and state is harmful uh usually
  142. 4:59now I brought out the generator object
  143. 5:02previously we had a generator equals g
  144. 5:04and so on inside these layers I've
  145. 5:07discarded that in favor of just
  146. 5:08initializing the torch RNG outside here
  147. 5:12use it just once globally just for
  148. 5:15Simplicity
  149. 5:16and then here we are starting to build
  150. 5:18out some of the neural network elements
  151. 5:19this should look very familiar we are we
  152. 5:22have our embedding table C and then we
  153. 5:24have a list of players and uh it's a
  154. 5:27linear feeds to Bachelor feeds to 10h
  155. 5:29and then a linear output layer and its
  156. 5:32weights are scaled down so we are not
  157. 5:33confidently wrong at the initialization
  158. 5:36we see that this is about 12 000
  159. 5:38parameters we're telling pytorch that
  160. 5:40the parameters require gradients
  161. 5:42the optimization is as far as I'm aware
  162. 5:44identical and should look very very
  163. 5:46familiar
  164. 5:47nothing changed here
  165. 5:49uh loss function looks very crazy we
  166. 5:52should probably fix this and that's
  167. 5:54because 32 batch elements are too few
  168. 5:56and so you can get very lucky lucky or
  169. 5:59unlucky in any one of these batches and
  170. 6:01it creates a very thick loss function
  171. 6:04um so we're going to fix that soon
  172. 6:06now once we want to evaluate the trained
  173. 6:08neural network we need to remember
  174. 6:09because of the bathroom layers to set
  175. 6:11all the layers to be training equals
  176. 6:13false so this only matters for the
  177. 6:15bathroom layer so far
  178. 6:17and then we evaluate
  179. 6:19we see that currently we have validation
  180. 6:22loss of 2.10 which is fairly good but
  181. 6:25there's still ways to go but even at
  182. 6:282.10 we see that when we sample from the
  183. 6:30model we actually get relatively
  184. 6:31name-like results that do not exist in a
  185. 6:34training set so for example Yvonne kilo
  186. 6:37Pros
  187. 6:40Alaia Etc so certainly not
  188. 6:43reasonable not unreasonable I would say
  189. 6:46but not amazing and we can still push
  190. 6:48this validation loss even lower and get
  191. 6:50much better samples that are even more
  192. 6:52name-like
  193. 6:53so let's improve this model
  194. 6:56okay first let's fix this graph because
  195. 6:58it is daggers in my eyes and I just
  196. 7:00can't take it anymore
  197. 7:01um so last I if you recall is a python
  198. 7:05list of floats so for example the first
  199. 7:0710 elements
  200. 7:10now what we'd like to do basically is we
  201. 7:12need to average up
  202. 7:14um some of these values to get a more
  203. 7:16sort of Representative uh value along
  204. 7:19the way so one way to do this is the
  205. 7:20following
  206. 7:21in part torch if I create for example
  207. 7:24a tensor of the first 10 numbers
  208. 7:27then this is currently a one-dimensional
  209. 7:29array but recall that I can view this
  210. 7:31array as two-dimensional so for example
  211. 7:33I can use it as a two by five array and
  212. 7:36this is a 2d tensor now two by five and
  213. 7:39you see what petroch has done is that
  214. 7:40the first row of this tensor is the
  215. 7:42first five elements and the second row
  216. 7:44is the second five elements
  217. 7:46I can also view it as a five by two as
  218. 7:48an example
  219. 7:50and then recall that I can also
  220. 7:52use negative one in place of one of
  221. 7:55these numbers
  222. 7:55and pytorch will calculate what that
  223. 7:58number must be in order to make the
  224. 7:59number of elements work out so this can
  225. 8:01be
  226. 8:03this or like that but it will work of
  227. 8:06course this would not work
  228. 8:09okay so this allows it to spread out
  229. 8:11some of the consecutive values into rows
  230. 8:13so that's very helpful because what we
  231. 8:15can do now is first of all we're going
  232. 8:17to create a torshot tensor out of the a
  233. 8:21list of floats
  234. 8:22and then we're going to view it as
  235. 8:24whatever it is but we're going to
  236. 8:26stretch it out into rows of 1000
  237. 8:29consecutive elements so the shape of
  238. 8:31this now becomes 200 by 1000. and each
  239. 8:35row is one thousand um consecutive
  240. 8:37elements in this list
  241. 8:39so that's very helpful because now we
  242. 8:41can do a mean along the rows
  243. 8:43and the shape of this will just be 200.
  244. 8:47and so we've taken basically the mean on
  245. 8:48every row so plt.plot of that should be
  246. 8:51something nicer
  247. 8:53much better
  248. 8:55so we see that we basically made a lot
  249. 8:56of progress and then here this is the
  250. 8:59learning rate Decay so here we see that
  251. 9:01the learning rate Decay subtracted a ton
  252. 9:03of energy out of the system and allowed
  253. 9:05us to settle into sort of the local
  254. 9:07minimum in this optimization
  255. 9:09so this is a much nicer plot let me come
  256. 9:12up and delete the monster and we're
  257. 9:15going to be using this going forward now
  258. 9:16next up what I'm bothered by is that you
  259. 9:19see our forward pass is a little bit
  260. 9:22gnarly and takes way too many lines of
  261. 9:24code
  262. 9:24so in particular we see that we've
  263. 9:26organized some of the layers inside the
  264. 9:28layers list but not all of them uh for
  265. 9:30no reason so in particular we see that
  266. 9:32we still have the embedding table a
  267. 9:34special case outside of the layers and
  268. 9:37in addition to that the viewing
  269. 9:39operation here is also outside of our
  270. 9:40layers so let's create layers for these
  271. 9:43and then we can add those layers to just
  272. 9:45our list
  273. 9:46so in particular the two things that we
  274. 9:48need is here we have this embedding
  275. 9:50table and we are indexing at the
  276. 9:53integers inside uh the batch XB uh
  277. 9:56inside the tensor xB
  278. 9:58so that's an embedding table lookup just
  279. 10:00done with indexing and then here we see
  280. 10:03that we have this view operation which
  281. 10:04if you recall from the previous video
  282. 10:06Simply rearranges the character
  283. 10:09embeddings and stretches them out into a
  284. 10:12row and effectively what print that does
  285. 10:14is the concatenation operation basically
  286. 10:16except it's free because viewing is very
  287. 10:19cheap in pytorch no no memory is being
  288. 10:22copied we're just re-representing how we
  289. 10:24view that tensor so let's create
  290. 10:27um
  291. 10:28modules for both of these operations the
  292. 10:31embedding operation and flattening
  293. 10:32operation
  294. 10:33so I actually wrote the code in just to
  295. 10:37save some time
  296. 10:38so we have a module embedding and a
  297. 10:40module pattern and both of them simply
  298. 10:43do the indexing operation in the forward
  299. 10:45pass and the flattening operation here
  300. 10:49and this C now will just become a salt
  301. 10:53dot weight inside an embedding module
  302. 10:56and I'm calling these layers
  303. 10:58specifically embedding a platinum
  304. 10:59because it turns out that both of them
  305. 11:01actually exist in pi torch so in
  306. 11:03phytorch we have n and Dot embedding and
  307. 11:06it also takes the number of embeddings
  308. 11:07and the dimensionality of the bedding
  309. 11:09just like we have here but in addition
  310. 11:11python takes in a lot of other keyword
  311. 11:13arguments that we are not using for our
  312. 11:15purposes yet
  313. 11:17and for flatten that also exists in
  314. 11:19pytorch and it also takes additional
  315. 11:21keyword arguments that we are not using
  316. 11:23so we have a very simple platform
  317. 11:26but both of them exist in pytorch
  318. 11:28they're just a bit more simpler and now
  319. 11:30that we have these we can simply take
  320. 11:33out some of these special cased
  321. 11:36um things so instead of C we're just
  322. 11:40going to have an embedding
  323. 11:41and of a cup size and N embed
  324. 11:45and then after the embedding we are
  325. 11:47going to flatten
  326. 11:48so let's construct those modules and now
  327. 11:51I can take out this the
  328. 11:53and here I don't have to special case
  329. 11:54anymore because now C is the embeddings
  330. 11:57weight and it's inside layers
  331. 12:01so this should just work
  332. 12:03and then here our forward pass
  333. 12:06simplifies substantially because we
  334. 12:08don't need to do these now outside of
  335. 12:10these layer outside and explicitly
  336. 12:13they're now inside layers
  337. 12:15so we can delete those
  338. 12:17but now to to kick things off we want
  339. 12:19this little X which in the beginning is
  340. 12:21just XB uh the tensor of integers
  341. 12:24specifying the identities of these
  342. 12:26characters at the input
  343. 12:27and so these characters can now directly
  344. 12:29feed into the first layer and this
  345. 12:31should just work
  346. 12:32so let me come here and insert a break
  347. 12:35because I just want to make sure that
  348. 12:36the first iteration of this runs and
  349. 12:38then there's no mistake so that ran
  350. 12:40properly and basically we substantially
  351. 12:42simplified the forward pass here okay
  352. 12:45I'm sorry I changed my microphone so
  353. 12:46hopefully the audio is a little bit
  354. 12:48better
  355. 12:49now one more thing that I would like to
  356. 12:51do in order to pytortify our code even
  357. 12:53further is that right now we are
  358. 12:54maintaining all of our modules in a
  359. 12:56naked list of layers and we can also
  360. 12:59simplify this uh because we can
  361. 13:01introduce the concept of Pi torch
  362. 13:03containers so in tors.nn which we are
  363. 13:05basically rebuilding from scratch here
  364. 13:07there's a concept of containers
  365. 13:09and these containers are basically a way
  366. 13:10of organizing layers into
  367. 13:13lists or dicts and so on so in
  368. 13:16particular there's a sequential which
  369. 13:18maintains a list of layers and is a
  370. 13:20module class in pytorch and it basically
  371. 13:23just passes a given input through all
  372. 13:25the layers sequentially exactly as we
  373. 13:27are doing here
  374. 13:28so let's write our own sequential
  375. 13:31I've written a code here and basically
  376. 13:33the code for sequential is quite
  377. 13:35straightforward we pass in a list of
  378. 13:37layers which we keep here and then given
  379. 13:39any input in a forward pass we just call
  380. 13:41all the layers sequentially and return
  381. 13:43the result in terms of the parameters
  382. 13:45it's just all the parameters of the
  383. 13:46child modules
  384. 13:48so we can run this and we can again
  385. 13:50simplify this substantially because we
  386. 13:52don't maintain this naked list of layers
  387. 13:54we now have a notion of a model which is
  388. 13:57a module and in particular is a
  389. 14:00sequential of all these layers
  390. 14:04and now parameters are simply just a
  391. 14:07model about parameters
  392. 14:09and so that list comprehension now lives
  393. 14:11here
  394. 14:13and then here we are press here we are
  395. 14:15doing all the things we used to do
  396. 14:17now here the code again simplifies
  397. 14:19substantially because we don't have to
  398. 14:22do this forwarding here instead of just
  399. 14:24call the model on the input data and the
  400. 14:26input data here are the integers inside
  401. 14:28xB so we can simply do logits which are
  402. 14:31the outputs of our model are simply the
  403. 14:33model called on xB
  404. 14:36and then the cross entropy here takes
  405. 14:38the logits and the targets
  406. 14:41so this simplifies substantially
  407. 14:43and then this looks good so let's just
  408. 14:46make sure this runs that looks good
  409. 14:49now here we actually have some work to
  410. 14:51do still here but I'm going to come back
  411. 14:52later for now there's no more layers
  412. 14:54there's a model that layers but it's not
  413. 14:57a to access attributes of these classes
  414. 15:00directly so we'll come back and fix this
  415. 15:01later
  416. 15:03and then here of course this simplifies
  417. 15:05substantially as well because logits are
  418. 15:07the model called on x
  419. 15:10and then these low Jets come here
  420. 15:14so we can evaluate the train and
  421. 15:15validation loss which currently is
  422. 15:17terrible because we just initialized the
  423. 15:19neural net and then we can also sample
  424. 15:21from the model and this simplifies
  425. 15:22dramatically as well
  426. 15:24because we just want to call the model
  427. 15:25onto the context and outcome logits
  428. 15:30and these logits go into softmax and get
  429. 15:32the probabilities Etc so we can sample
  430. 15:35from this model
  431. 15:37what did I screw up
  432. 15:42okay so I fixed the issue and we now get
  433. 15:44the result that we expect which is
  434. 15:46gibberish because the model is not
  435. 15:48trained because we re-initialize it from
  436. 15:49scratch
  437. 15:50the problem was that when I fixed this
  438. 15:52cell to be modeled out layers instead of
  439. 15:54just layers I did not actually run the
  440. 15:56cell and so our neural net was in a
  441. 15:58training mode and what caused the issue
  442. 16:01here is the bathroom layer as bathroom
  443. 16:03layer of the likes to do because
  444. 16:05Bachelor was in a training mode and here
  445. 16:07we are passing in an input which is a
  446. 16:09batch of just a single example made up
  447. 16:11of the context
  448. 16:12and so if you are trying to pass in a
  449. 16:15single example into a bash Norm that is
  450. 16:16in the training mode you're going to end
  451. 16:18up estimating the variance using the
  452. 16:20input and the variance of a single
  453. 16:21number is is not a number because it is
  454. 16:24a measure of a spread so for example the
  455. 16:26variance of just the single number five
  456. 16:28you can see is not a number and so
  457. 16:31that's what happened in the master
  458. 16:33basically caused an issue and then that
  459. 16:35polluted all of the further processing
  460. 16:37so all that we have to do was make sure
  461. 16:39that this runs and we basically made the
  462. 16:43issue of
  463. 16:45again we didn't actually see the issue
  464. 16:46with the loss we could have evaluated
  465. 16:48the loss but we got the wrong result
  466. 16:49because basharm was in the training mode
  467. 16:52and uh and so we still get a result it's
  468. 16:54just the wrong result because it's using
  469. 16:56the uh sample statistics of the batch
  470. 16:59whereas we want to use the running mean
  471. 17:00and running variants inside the bachelor
  472. 17:02and so
  473. 17:04again an example of introducing a bug
  474. 17:06inline because we did not properly
  475. 17:09maintain the state of what is training
  476. 17:10or not okay so I Rewritten everything
  477. 17:12and here's where we are as a reminder we
  478. 17:15have the training loss of 2.05 and
  479. 17:17validation 2.10
  480. 17:18now because these losses are very
  481. 17:21similar to each other we have a sense
  482. 17:22that we are not overfitting too much on
  483. 17:24this task and we can make additional
  484. 17:26progress in our performance by scaling
  485. 17:28up the size of the neural network and
  486. 17:29making everything bigger and deeper
  487. 17:32now currently we are using this
  488. 17:33architecture here where we are taking in
  489. 17:35some number of characters going into a
  490. 17:37single hidden layer and then going to
  491. 17:39the prediction of the next character
  492. 17:41the problem here is we don't have a
  493. 17:43naive way of making this bigger in a
  494. 17:46productive way we could of course use
  495. 17:48our layers sort of building blocks and
  496. 17:51materials to introduce additional layers
  497. 17:53here and make the network deeper but it
  498. 17:55is still the case that we are crushing
  499. 17:56all of the characters into a single
  500. 17:58layer all the way at the beginning
  501. 18:00and even if we make this a bigger layer
  502. 18:02and add neurons it's still kind of like
  503. 18:04silly to squash all that information so
  504. 18:07fast in a single step
  505. 18:09so we'd like to do instead is we'd like
  506. 18:11our Network to look a lot more like this
  507. 18:13in the wavenet case so you see in the
  508. 18:15wavenet when we are trying to make the
  509. 18:17prediction for the next character in the
  510. 18:18sequence it is a function of the
  511. 18:20previous characters that are feeding
  512. 18:22that feed in but not all of these
  513. 18:25different characters are not just
  514. 18:26crushed to a single layer and then you
  515. 18:28have a sandwich they are crushed slowly
  516. 18:31so in particular we take two characters
  517. 18:34and we fuse them into sort of like a
  518. 18:36diagram representation and we do that
  519. 18:38for all these characters consecutively
  520. 18:40and then we take the bigrams and we fuse
  521. 18:42those into four character level chunks
  522. 18:46and then we fuse that again and so we do
  523. 18:49that in this like tree-like hierarchical
  524. 18:51manner so we fuse the information from
  525. 18:53the previous context slowly into the
  526. 18:56network as it gets deeper and so this is
  527. 18:58the kind of architecture that we want to
  528. 18:59implement
  529. 19:00now in the wave Nets case this is a
  530. 19:02visualization of a stack of dilated
  531. 19:04causal convolution layers and this makes
  532. 19:07it sound very scary but actually the
  533. 19:08idea is very simple and the fact that
  534. 19:10it's a dilated causal convolution layer
  535. 19:12is really just an implementation detail
  536. 19:14to make everything fast we're going to
  537. 19:16see that later but for now let's just
  538. 19:18keep the basic idea of it which is this
  539. 19:20Progressive Fusion so we want to make
  540. 19:22the network deeper and at each level we
  541. 19:24want to fuse only two consecutive
  542. 19:26elements two characters then two bigrams
  543. 19:29then two four grams and so on so let's
  544. 19:32unplant this okay so first up let me
  545. 19:34scroll to where we built the data set
  546. 19:35and let's change the block size from 3
  547. 19:37to 8. so we're going to be taking eight
  548. 19:39characters of context to predict the
  549. 19:42ninth character so the data set now
  550. 19:44looks like this we have a lot more
  551. 19:45context feeding in to predict any next
  552. 19:47character in a sequence and these eight
  553. 19:49characters are going to be processed in
  554. 19:51this tree like structure
  555. 19:53now if we scroll here everything here
  556. 19:56should just be able to work so we should
  557. 19:58be able to redefine the network
  558. 19:59you see the number of parameters has
  559. 20:01increased by 10 000 and that's because
  560. 20:03the block size has grown so this first
  561. 20:06linear layer is much much bigger our
  562. 20:08linear layer now takes eight characters
  563. 20:10into this middle layer so there's a lot
  564. 20:13more parameters there but this should
  565. 20:15just run let me just break right after
  566. 20:18the very first iteration so you see that
  567. 20:20this runs just fine it's just that this
  568. 20:22network doesn't make too much sense
  569. 20:23we're crushing way too much information
  570. 20:25way too fast
  571. 20:26so let's now come in and see how we
  572. 20:29could try to implement the hierarchical
  573. 20:30scheme now before we dive into the
  574. 20:33detail of the re-implementation here I
  575. 20:35was just curious to actually run it and
  576. 20:37see where we are in terms of the
  577. 20:38Baseline performance of just lazily
  578. 20:40scaling up the context length so I'll
  579. 20:42let it run we get a nice loss curve and
  580. 20:45then evaluating the loss we actually see
  581. 20:46quite a bit of improvement just from
  582. 20:48increasing the context line length so I
  583. 20:51started a little bit of a performance
  584. 20:52log here and previously where we were is
  585. 20:54we were getting a performance of 2.10 on
  586. 20:57the validation loss and now simply
  587. 20:59scaling up the contact length from 3 to
  588. 21:018 gives us a performance of 2.02 so
  589. 21:05quite a bit of an improvement here and
  590. 21:07also when you sample from the model you
  591. 21:08see that the names are definitely
  592. 21:10improving qualitatively as well
  593. 21:13so we could of course spend a lot of
  594. 21:14time here tuning
  595. 21:16um uh tuning things and making it even
  596. 21:18bigger and scaling up the network
  597. 21:19further even with the simple
  598. 21:21um sort of setup here but let's continue
  599. 21:24and let's Implement here model and treat
  600. 21:27this as just a rough Baseline
  601. 21:28performance but there's a lot of
  602. 21:30optimization like left on the table in
  603. 21:32terms of some of the hyper parameters
  604. 21:34that you're hopefully getting a sense of
  605. 21:35now okay so let's scroll up now
  606. 21:38and come back up and what I've done here
  607. 21:41is I've created a bit of a scratch space
  608. 21:42for us to just like look at the forward
  609. 21:45pass of the neural net and inspect the
  610. 21:47shape of the tensor along the way as the
  611. 21:49neural net uh forwards so here I'm just
  612. 21:53temporarily for debugging creating a
  613. 21:55batch of just say four examples so four
  614. 21:58random integers then I'm plucking out
  615. 22:00those rows from our training set
  616. 22:02and then I'm passing into the model the
  617. 22:04input xB
  618. 22:06now the shape of XB here because we have
  619. 22:08only four examples is four by eight and
  620. 22:11this eight is now the current block size
  621. 22:14so uh inspecting XP we just see that we
  622. 22:18have four examples each one of them is a
  623. 22:19row of xB
  624. 22:21and we have eight characters here and
  625. 22:24this integer tensor just contains the
  626. 22:26identities of those characters
  627. 22:29so the first layer of our neural net is
  628. 22:31the embedding layer so passing XB this
  629. 22:33integer tensor through the embedding
  630. 22:35layer creates an output that is four by
  631. 22:37eight by ten
  632. 22:39so our embedding table has for each
  633. 22:42character a 10-dimensional vector that
  634. 22:44we are trying to learn
  635. 22:46and so what the embedding layer does
  636. 22:48here is it plucks out the embedding
  637. 22:50Vector for each one of these integers
  638. 22:53and organizes it all in a four by eight
  639. 22:56by ten tensor now
  640. 22:58so all of these integers are translated
  641. 23:00into 10 dimensional vectors inside this
  642. 23:02three-dimensional tensor now
  643. 23:04passing that through the flattened layer
  644. 23:06as you recall what this does is it views
  645. 23:09this tensor as just a 4 by 80 tensor and
  646. 23:12what that effectively does is that all
  647. 23:15these 10 dimensional embeddings for all
  648. 23:16these eight characters just end up being
  649. 23:18stretched out into a long row
  650. 23:21and that looks kind of like a
  651. 23:22concatenation operation basically so by
  652. 23:25viewing the tensor differently we now
  653. 23:27have a four by eighty and inside this 80
  654. 23:29it's all the 10 dimensional uh
  655. 23:32vectors just uh concatenate next to each
  656. 23:35other
  657. 23:36and then the linear layer of course
  658. 23:37takes uh 80 and creates 200 channels
  659. 23:40just via matrix multiplication
  660. 23:43so so far so good now I'd like to show
  661. 23:45you something surprising
  662. 23:47let's look at the insides of the linear
  663. 23:50layer and remind ourselves how it works
  664. 23:52the linear layer here in the forward
  665. 23:54pass takes the input X multiplies it
  666. 23:56with a weight and then optionally adds
  667. 23:58bias and the weight here is
  668. 24:00two-dimensional as defined here and the
  669. 24:02bias is one dimensional here
  670. 24:04so effectively in terms of the shapes
  671. 24:06involved what's happening inside this
  672. 24:08linear layer looks like this right now
  673. 24:10and I'm using random numbers here but
  674. 24:12I'm just illustrating the shapes and
  675. 24:15what happens
  676. 24:16basically a 4 by 80 input comes into the
  677. 24:18linear layer that's multiplied by this
  678. 24:2080 by 200 weight Matrix inside and
  679. 24:23there's a plus 200 bias and the shape of
  680. 24:25the whole thing that comes out of the
  681. 24:26linear layer is four by two hundred as
  682. 24:28we see here
  683. 24:30now notice here by the way that this
  684. 24:32here will create a 4x200 tensor and then
  685. 24:36plus 200 there's a broadcasting
  686. 24:38happening here about 4 by 200 broadcasts
  687. 24:41with 200 uh so everything works here
  688. 24:44so now the surprising thing that I'd
  689. 24:46like to show you that you may not expect
  690. 24:47is that this input here that is being
  691. 24:49multiplied uh doesn't actually have to
  692. 24:52be two-dimensional this Matrix multiply
  693. 24:55operator in pytorch is quite powerful
  694. 24:56and in fact you can actually pass in
  695. 24:58higher dimensional arrays or tensors and
  696. 25:00everything works fine so for example
  697. 25:02this could be four by five by eighty and
  698. 25:04the result in that case will become four
  699. 25:06by five by two hundred
  700. 25:08you can add as many dimensions as you
  701. 25:09like on the left here
  702. 25:11and so effectively what's happening is
  703. 25:13that the matrix multiplication only
  704. 25:15works on the last Dimension and the
  705. 25:17dimensions before it in the input tensor
  706. 25:19are left unchanged
  707. 25:24so that is basically these um these
  708. 25:27dimensions on the left are all treated
  709. 25:29as just a batch Dimension so we can have
  710. 25:32multiple batch dimensions and then in
  711. 25:34parallel over all those Dimensions we
  712. 25:36are doing the matrix multiplication on
  713. 25:38the last dimension
  714. 25:39so this is quite convenient because we
  715. 25:41can use that in our Network now
  716. 25:44because remember that we have these
  717. 25:46eight characters coming in
  718. 25:49and we don't want to now uh flatten all
  719. 25:51of it out into a large eight-dimensional
  720. 25:53vector
  721. 25:54because we don't want to Matrix multiply
  722. 25:5780.
  723. 25:59into a weight Matrix multiply
  724. 26:01immediately instead we want to group
  725. 26:03these
  726. 26:04like this
  727. 26:06so every consecutive two elements
  728. 26:09one two and three and four and five and
  729. 26:11six and seven and eight all of these
  730. 26:12should be now
  731. 26:14basically flattened out and multiplied
  732. 26:17by weight Matrix but all of these four
  733. 26:19groups here we'd like to process in
  734. 26:21parallel so it's kind of like a batch
  735. 26:23Dimension that we can introduce
  736. 26:25and then we can in parallel basically
  737. 26:28process all of these uh bigram groups in
  738. 26:33the four batch dimensions of an
  739. 26:34individual example and also over the
  740. 26:37actual batch dimension of the you know
  741. 26:39four examples in our example here so
  742. 26:42let's see how that works effectively
  743. 26:43what we want is right now we take a 4 by
  744. 26:4680
  745. 26:47and multiply it by 80 by 200
  746. 26:50to in the linear layer this is what
  747. 26:52happens
  748. 26:53but instead what we want is we don't
  749. 26:56want 80 characters or 80 numbers to come
  750. 26:58in we only want two characters to come
  751. 27:00in on the very first layer and those two
  752. 27:02characters should be fused
  753. 27:04so in other words we just want 20 to
  754. 27:07come in right 20 numbers would come in
  755. 27:11and here we don't want a 4 by 80 to feed
  756. 27:13into the linear layer we actually want
  757. 27:15these groups of two to feed in so
  758. 27:17instead of four by eighty we want this
  759. 27:19to be a 4 by 4 by 20.
  760. 27:23so these are the four groups of two and
  761. 27:27each one of them is ten dimensional
  762. 27:28vector
  763. 27:29so what we want is now is we need to
  764. 27:31change the flattened layer so it doesn't
  765. 27:33output a four by eighty but it outputs a
  766. 27:35four by four by Twenty where basically
  767. 27:38these um
  768. 27:39every two consecutive characters are uh
  769. 27:43packed in on the very last Dimension and
  770. 27:46then these four is the first batch
  771. 27:48Dimension and this four is the second
  772. 27:50batch Dimension referring to the four
  773. 27:52groups inside every one of these
  774. 27:54examples
  775. 27:55and then this will just multiply like
  776. 27:57this so this is what we want to get to
  777. 27:59so we're going to have to change the
  778. 28:01linear layer in terms of how many inputs
  779. 28:02it expects it shouldn't expect 80 it
  780. 28:05should just expect 20 numbers and we
  781. 28:07have to change our flattened layer so it
  782. 28:09doesn't just fully flatten out this
  783. 28:11entire example it needs to create a 4x4
  784. 28:14by 20 instead of four by eighty so let's
  785. 28:17see how this could be implemented
  786. 28:19basically right now we have an input
  787. 28:21that is a four by eight by ten that
  788. 28:23feeds into the flattened layer and
  789. 28:25currently the flattened layer just
  790. 28:27stretches it out so if you remember the
  791. 28:29implementation of flatten
  792. 28:31it takes RX and it just views it as
  793. 28:34whatever the batch Dimension is and then
  794. 28:35negative one
  795. 28:37so effectively what it does right now is
  796. 28:39it does e dot view of 4 negative one and
  797. 28:42the shape of this of course is 4 by 80.
  798. 28:45so that's what currently happens and we
  799. 28:48instead want this to be a four by four
  800. 28:49by Twenty where these consecutive
  801. 28:51ten-dimensional vectors get concatenated
  802. 28:54so you know how in Python you can take a
  803. 28:57list of range of 10
  804. 29:00so we have numbers from zero to nine and
  805. 29:03we can index like this to get all the
  806. 29:05even parts
  807. 29:06and we can also index like starting at
  808. 29:08one and going in steps up two to get all
  809. 29:11the odd parts
  810. 29:13so one way to implement this it would be
  811. 29:15as follows we can take e and we can
  812. 29:18index into it for all the batch elements
  813. 29:21and then just even elements in this
  814. 29:24Dimension so at indexes 0 2 4 and 8.
  815. 29:29and then all the parts here from this
  816. 29:31last dimension
  817. 29:33and this gives us the even characters
  818. 29:37and then here
  819. 29:39this gives us all the odd characters and
  820. 29:42basically what we want to do is we make
  821. 29:43sure we want to make sure that these get
  822. 29:44concatenated in pi torch and then we
  823. 29:47want to concatenate these two tensors
  824. 29:49along the second dimension
  825. 29:53so this and the shape of it would be
  826. 29:55four by four by Twenty this is
  827. 29:57definitely the result we want we are
  828. 29:58explicitly grabbing the even parts and
  829. 30:01the odd parts and we're arranging those
  830. 30:03four by four by ten right next to each
  831. 30:06other and concatenate
  832. 30:08so this works but it turns out that what
  833. 30:10also works is you can simply use a view
  834. 30:13again and just request the right shape
  835. 30:16and it just so happens that in this case
  836. 30:18those vectors will again end up being
  837. 30:21arranged in exactly the way we want so
  838. 30:23in particular if we take e and we just
  839. 30:25view it as a four by four by Twenty
  840. 30:27which is what we want
  841. 30:28we can check that this is exactly equal
  842. 30:30to but let me call this this is the
  843. 30:33explicit concatenation I suppose
  844. 30:36um
  845. 30:36so explosives dot shape is 4x4 by 20. if
  846. 30:40you just view it as 4x4 by 20 you can
  847. 30:42check that when you compare to explicit
  848. 30:46uh you got a big this is element wise
  849. 30:48operation so making sure that all of
  850. 30:49them are true that is the truth so
  851. 30:53basically long story short we don't need
  852. 30:54to make an explicit call to concatenate
  853. 30:56Etc we can simply take this input tensor
  854. 31:00to flatten and we can just view it in
  855. 31:03whatever way we want
  856. 31:04and in particular you don't want to
  857. 31:07stretch things out with negative one we
  858. 31:09want to actually create a
  859. 31:10three-dimensional array and depending on
  860. 31:12how many vectors that are consecutive we
  861. 31:15want to
  862. 31:16um fuse like for example two then we can
  863. 31:20just simply ask for this Dimension to be
  864. 31:2120. and um
  865. 31:24use a negative 1 here and python will
  866. 31:26figure out how many groups it needs to
  867. 31:27pack into this additional batch
  868. 31:29dimension
  869. 31:30so let's now go into flatten and
  870. 31:32implement this okay so I scroll up here
  871. 31:34to flatten and what we'd like to do is
  872. 31:36we'd like to change it now so let me
  873. 31:38create a Constructor and take the number
  874. 31:40of elements that are consecutive that we
  875. 31:42would like to concatenate now in the
  876. 31:44last dimension of the output
  877. 31:46so here we're just going to remember
  878. 31:48solve.n equals n
  879. 31:50and then I want to be careful here
  880. 31:52because pipe pytorch actually has a
  881. 31:54torch to flatten and its keyword
  882. 31:56arguments are different and they kind of
  883. 31:58like function differently so R flatten
  884. 32:00is going to start to depart from patreon
  885. 32:02flatten so let me call it flat flatten
  886. 32:04consecutive or something like that just
  887. 32:06to make sure that our apis are about
  888. 32:08equal
  889. 32:09so this uh basically flattens only some
  890. 32:13n consecutive elements and puts them
  891. 32:15into the last dimension
  892. 32:17now here the shape of X is B by T by C
  893. 32:21so let me
  894. 32:23pop those out into variables and recall
  895. 32:26that in our example down below B was 4 T
  896. 32:28was 8 and C was 10.
  897. 32:33now instead of doing x dot view of B by
  898. 32:37negative one
  899. 32:39right this is what we had before
  900. 32:44we want this to be B by
  901. 32:47um negative 1 by
  902. 32:49and basically here we want c times n
  903. 32:52that's how many consecutive elements we
  904. 32:55want
  905. 32:56and here instead of negative one I don't
  906. 32:58super love the use of negative one
  907. 33:00because I like to be very explicit so
  908. 33:02that you get error messages when things
  909. 33:03don't go according to your expectation
  910. 33:04so what do we expect here we expect this
  911. 33:07to become t
  912. 33:09divide n using integer division here
  913. 33:12so that's what I expect to happen
  914. 33:14and then one more thing I want to do
  915. 33:15here is remember previously all the way
  916. 33:18in the beginning n was three and uh
  917. 33:21basically we're concatenating
  918. 33:23um all the three characters that existed
  919. 33:25there
  920. 33:26so we basically are concatenated
  921. 33:28everything
  922. 33:29and so sometimes I can create a spurious
  923. 33:31dimension of one here so if it is the
  924. 33:34case that x dot shape at one is one then
  925. 33:37it's kind of like a spurious dimension
  926. 33:39um so we don't want to return a
  927. 33:41three-dimensional tensor with a one here
  928. 33:44we just want to return a two-dimensional
  929. 33:46tensor exactly as we did before
  930. 33:48so in this case basically we will just
  931. 33:50say x equals x dot squeeze that is a
  932. 33:54pytorch function
  933. 33:56and squeeze takes a dimension that it
  934. 34:01either squeezes out all the dimensions
  935. 34:02of a tensor that are one or you can
  936. 34:05specify the exact Dimension that you
  937. 34:08want to be squeezed and again I like to
  938. 34:10be as explicit as possible always so I
  939. 34:12expect to squeeze out the First
  940. 34:13Dimension only
  941. 34:15of this tensor
  942. 34:17this three-dimensional tensor and if
  943. 34:19this Dimension here is one then I just
  944. 34:21want to return B by c times n
  945. 34:24and so self dot out will be X and then
  946. 34:26we return salt dot out
  947. 34:28so that's the candidate implementation
  948. 34:30and of course this should be self.n
  949. 34:33instead of just n
  950. 34:34so let's run
  951. 34:36and let's come here now
  952. 34:39and take it for a spin so flatten
  953. 34:41consecutive
  954. 34:44and in the beginning let's just use
  955. 34:47eight so this should recover the
  956. 34:49previous Behavior so flagging
  957. 34:51consecutive of eight uh which is the
  958. 34:53current block size
  959. 34:55we can do this uh that should recover
  960. 34:57the previous Behavior
  961. 34:59so we should be able to run the model
  962. 35:02and here we can inspect I have a little
  963. 35:06code snippet here where I iterate over
  964. 35:08all the layers I print the name of this
  965. 35:11class and the shape
  966. 35:14and so we see the shapes as we expect
  967. 35:17them after every single layer in the top
  968. 35:19bit so now let's try to restructure it
  969. 35:22using our flattened consecutive and do
  970. 35:25it hierarchically so in particular
  971. 35:28we want to flatten consecutive not just
  972. 35:30not block size but just two
  973. 35:33and then we want to process this with
  974. 35:34linear now then the number of inputs to
  975. 35:37this linear will not be an embed times
  976. 35:38block size it will now only be n embed
  977. 35:41times two
  978. 35:4220.
  979. 35:44this goes through the first layer and
  980. 35:46now we can in principle just copy paste
  981. 35:48this
  982. 35:49now the next linear layer should expect
  983. 35:51and hidden times two
  984. 35:53and the last piece of it should expect
  985. 35:58and it enters 2 again
  986. 36:01so this is sort of like the naive
  987. 36:03version of it
  988. 36:04um
  989. 36:05so running this we now have a much much
  990. 36:07bigger model
  991. 36:09and we should be able to basically just
  992. 36:10forward the model
  993. 36:13and now we can inspect uh the numbers in
  994. 36:16between
  995. 36:17so four byte by 20
  996. 36:19was Platinum consecutively into four by
  997. 36:21four by Twenty
  998. 36:23this was projected into four by four by
  999. 36:24two hundred
  1000. 36:26and then bash storm just worked out of
  1001. 36:29the box we have to verify that bastron
  1002. 36:31does the correct thing even though it
  1003. 36:33takes a three-dimensional impedance that
  1004. 36:34are two dimensional input
  1005. 36:36then we have 10h which is element wise
  1006. 36:38then we crushed it again so if we
  1007. 36:41flatten consecutively and ended up with
  1008. 36:42a four by two by 400 now
  1009. 36:45then linear brought it back down to 200
  1010. 36:47batch room 10h and lastly we get a 4 by
  1011. 36:50400 and we see that the flattened
  1012. 36:52consecutive for the last flatten here uh
  1013. 36:54it squeezed out that dimension of one so
  1014. 36:57we only ended up with four by four
  1015. 36:58hundred and then linear Bachelor on 10h
  1016. 37:00and uh the last linear layer to get our
  1017. 37:04logents and so The Lodges end up in the
  1018. 37:06same shape as they were before but now
  1019. 37:08we actually have a nice three layer
  1020. 37:10neural nut and it basically corresponds
  1021. 37:12to whoops sorry it basically corresponds
  1022. 37:15exactly to this network now except only
  1023. 37:18this piece here because we only have
  1024. 37:20three layers whereas here in this
  1025. 37:22example there's uh four layers with the
  1026. 37:25total receptive field size of 16
  1027. 37:28characters instead of just eight
  1028. 37:29characters so the block size here is 16.
  1029. 37:32so this piece of it's basically
  1030. 37:34implemented here
  1031. 37:36um now we just have to kind of figure
  1032. 37:38out some good Channel numbers to use
  1033. 37:40here now in particular I changed the
  1034. 37:42number of hidden units to be 68 in this
  1035. 37:45architecture because when I use 68 the
  1036. 37:47number of parameters comes out to be 22
  1037. 37:49000 so that's exactly the same that we
  1038. 37:52had before and we have the same amount
  1039. 37:54of capacity at this neural net in terms
  1040. 37:56of the number of parameters but the
  1041. 37:57question is whether we are utilizing
  1042. 37:59those parameters in a more efficient
  1043. 38:00architecture so what I did then is I got
  1044. 38:03rid of a lot of the debugging cells here
  1045. 38:05and I rerun the optimization and
  1046. 38:07scrolling down to the result we see that
  1047. 38:09we get the identical performance roughly
  1048. 38:12so our validation loss now is 2.029 and
  1049. 38:15previously it was 2.027 so controlling
  1050. 38:18for the number of parameters changing
  1051. 38:20from the flat to hierarchical is not
  1052. 38:21giving us anything yet
  1053. 38:23that said there are two things
  1054. 38:25um to point out number one we didn't
  1055. 38:27really torture the um architecture here
  1056. 38:29very much this is just my first guess
  1057. 38:31and there's a bunch of hyper parameters
  1058. 38:33search that we could do in order in
  1059. 38:35terms of how we allocate uh our budget
  1060. 38:37of parameters to what layers number two
  1061. 38:39we still may have a bug inside the
  1062. 38:42bachelor 1D layer so let's take a look
  1063. 38:44at
  1064. 38:45um uh that because it runs but does it
  1065. 38:49do the right thing
  1066. 38:50so I pulled up the layer inspector sort
  1067. 38:53of that we have here and printed out the
  1068. 38:55shape along the way and currently it
  1069. 38:57looks like the batch form is receiving
  1070. 38:58an input that is 32 by 4 by 68 right and
  1071. 39:03here on the right I have the current
  1072. 39:04implementation of Bachelor that we have
  1073. 39:05right now
  1074. 39:06now this bachelor assumed in the way we
  1075. 39:09wrote it and at the time that X is
  1076. 39:11two-dimensional so it was n by D where n
  1077. 39:15was the batch size so that's why we only
  1078. 39:17reduced uh the mean and the variance
  1079. 39:19over the zeroth dimension but now X will
  1080. 39:21basically become three-dimensional so
  1081. 39:23what's happening inside the bachelor
  1082. 39:24right now and how come it's working at
  1083. 39:26all and not giving any errors the reason
  1084. 39:28for that is basically because everything
  1085. 39:30broadcasts properly but the bachelor is
  1086. 39:32not doing what we need what we wanted to
  1087. 39:34do
  1088. 39:35so in particular let's basically think
  1089. 39:37through what's happening inside the
  1090. 39:38bathroom uh looking at what's what's do
  1091. 39:41What's Happening Here
  1092. 39:43I have the code here
  1093. 39:45so we're receiving an input of 32 by 4
  1094. 39:47by 68 and then we are doing uh here x
  1095. 39:52dot mean here I have e instead of X but
  1096. 39:54we're doing the mean over zero and
  1097. 39:57that's actually giving us 1 by 4 by 68.
  1098. 39:59so we're doing the mean only over the
  1099. 40:01very first Dimension and it's giving us
  1100. 40:03a mean and a variance that still
  1101. 40:05maintain this Dimension here
  1102. 40:07so these means are only taking over 32
  1103. 40:10numbers in the First Dimension and then
  1104. 40:12when we perform this everything
  1105. 40:14broadcasts correctly still
  1106. 40:16but basically what ends up happening is
  1107. 40:20when we also look at the running mean
  1108. 40:26the shape of it so I'm looking at the
  1109. 40:27model that layers at three which is the
  1110. 40:28first bathroom layer and they're looking
  1111. 40:30at whatever the running mean became and
  1112. 40:32its shape
  1113. 40:34the shape of this running mean now is 1
  1114. 40:35by 4 by 68.
  1115. 40:38right instead of it being
  1116. 40:39um you know just a size of dimension
  1117. 40:43because we have 68 channels we expect to
  1118. 40:45have 68 means and variances that we're
  1119. 40:47maintaining but actually we have an
  1120. 40:49array of 4 by 68 and so basically what
  1121. 40:51this is telling us is this bash Norm is
  1122. 40:54only
  1123. 40:55this bachelor is currently working in
  1124. 40:57parallel
  1125. 40:58over
  1126. 41:014 times 68 instead of just 68 channels
  1127. 41:06so basically we are maintaining
  1128. 41:08statistics for every one of these four
  1129. 41:10positions individually and independently
  1130. 41:13and instead what we want to do is we
  1131. 41:15want to treat this four as a batch
  1132. 41:16Dimension just like the zeroth dimension
  1133. 41:19so as far as the bachelor is concerned
  1134. 41:22it doesn't want to average we don't want
  1135. 41:24to average over 32 numbers we want to
  1136. 41:26now average over 32 times four numbers
  1137. 41:29for every single one of these 68
  1138. 41:31channels
  1139. 41:32and uh so let me now
  1140. 41:34remove this
  1141. 41:36it turns out that when you look at the
  1142. 41:38documentation of torch.mean
  1143. 41:42so let's go to torch.me
  1144. 41:49in one of its signatures when we specify
  1145. 41:51the dimension
  1146. 41:53we see that the dimension here is not
  1147. 41:54just it can be in or it can also be a
  1148. 41:56tuple of ins so we can reduce over
  1149. 41:59multiple integers at the same time over
  1150. 42:02multiple Dimensions at the same time so
  1151. 42:04instead of just reducing over zero we
  1152. 42:05can pass in a tuple 0 1.
  1153. 42:08and here zero one as well and then
  1154. 42:10what's going to happen is the output of
  1155. 42:12course is going to be the same
  1156. 42:13but now what's going to happen is
  1157. 42:15because we reduce over 0 and 1 if we
  1158. 42:17look at immin.shape
  1159. 42:20we see that now we've reduced we took
  1160. 42:22the mean over both the zeroth and the
  1161. 42:25First Dimension
  1162. 42:26so we're just getting 68 numbers and a
  1163. 42:28bunch of spurious Dimensions here
  1164. 42:30so now this becomes 1 by 1 by 68 and the
  1165. 42:34running mean and the running variance
  1166. 42:35analogously will become one by one by
  1167. 42:3768. so even though there are the
  1168. 42:39spurious Dimensions uh the current the
  1169. 42:41current the correct thing will happen in
  1170. 42:43that we are only maintaining means and
  1171. 42:45variances for 64 sorry for 68 channels
  1172. 42:49and we're not calculating the mean
  1173. 42:50variance across 32 times 4 dimensions so
  1174. 42:54that's exactly what we want and let's
  1175. 42:56change the implementation of bash term
  1176. 42:581D that we have so that it can take in
  1177. 43:01two-dimensional or three-dimensional
  1178. 43:02inputs and perform accordingly so at the
  1179. 43:05end of the day the fix is relatively
  1180. 43:07straightforward basically the dimension
  1181. 43:09we want to reduce over is either 0 or
  1182. 43:12the Tuple zero and one depending on the
  1183. 43:14dimensionality of X so if x dot and dim
  1184. 43:16is two so it's a two dimensional tensor
  1185. 43:18then Dimension we want to reduce over is
  1186. 43:20just the integer zero
  1187. 43:22L if x dot ending is three so it's a
  1188. 43:24three-dimensional tensor then the dims
  1189. 43:26we're going to assume are zero and one
  1190. 43:29that we want to reduce over and then
  1191. 43:31here we just pass in dim
  1192. 43:33and if the dimensionality of X is
  1193. 43:35anything else we'll now get an error
  1194. 43:36which is good
  1195. 43:38um so that should be the fix now I want
  1196. 43:41to point out one more thing we're
  1197. 43:42actually departing from the API of Pi
  1198. 43:44torch here a little bit because when you
  1199. 43:46come to batch room 1D and pytorch you
  1200. 43:48can scroll down and you can see that the
  1201. 43:50input to this layer can either be n by C
  1202. 43:53where n is the batch size and C is the
  1203. 43:55number of features or channels or it
  1204. 43:57actually does accept three-dimensional
  1205. 43:59inputs but it expects it to be n by C by
  1206. 44:01L
  1207. 44:02where LSA like the sequence length or
  1208. 44:04something like that
  1209. 44:05so um
  1210. 44:07this is problem because you see how C is
  1211. 44:09nested here in the middle and so when it
  1212. 44:12gets three-dimensional inputs this bash
  1213. 44:14term layer will reduce over zero and two
  1214. 44:17instead of zero and one so it basically
  1215. 44:20Pi torch batch number one D layer
  1216. 44:22assumes that c will always be the First
  1217. 44:25Dimension whereas we'll we assume here
  1218. 44:28that c is the last Dimension and there
  1219. 44:30are some number of batch Dimensions
  1220. 44:32beforehand
  1221. 44:34um
  1222. 44:34and so
  1223. 44:36it expects n by C or M by C by all we
  1224. 44:39expect and by C or n by L by C
  1225. 44:42and so it's a deviation
  1226. 44:45um
  1227. 44:46I think it's okay I prefer it this way
  1228. 44:49honestly so this is the way that we will
  1229. 44:50keep it for our purposes
  1230. 44:52so I redefined the layers re-initialize
  1231. 44:54the neural net and did a single forward
  1232. 44:55pass with a break just for one step
  1233. 44:57looking at the shapes along the way
  1234. 44:59they're of course identical all the
  1235. 45:01shapes are the same but the way we see
  1236. 45:03that things are actually working as we
  1237. 45:05want them to now is that when we look at
  1238. 45:07the bathroom layer the running mean
  1239. 45:08shape is now one by one by 68. so we're
  1240. 45:11only maintaining 68 means for every one
  1241. 45:13of our channels and we're treating both
  1242. 45:15the zeroth and the First Dimension as a
  1243. 45:17batch Dimension which is exactly what we
  1244. 45:19want so let me retrain the neural lot
  1245. 45:21now okay so I retrained the neural net
  1246. 45:22with the bug fix we get a nice curve and
  1247. 45:25when we look at the validation
  1248. 45:25performance we do actually see a slight
  1249. 45:27Improvement so we went from 2.029 to
  1250. 45:302.022 so basically the bug inside the
  1251. 45:32bathroom was holding up us back like a
  1252. 45:35little bit it looks like and we are
  1253. 45:37getting a tiny Improvement now but it's
  1254. 45:39not clear if this is statistical
  1255. 45:40significant
  1256. 45:41um
  1257. 45:42and the reason we slightly expect an
  1258. 45:44improvement is because we're not
  1259. 45:46maintaining so many different means and
  1260. 45:47variances that are only estimated using
  1261. 45:49using 32 numbers effectively now we are
  1262. 45:52estimating them using 32 times 4 numbers
  1263. 45:54so you just have a lot more numbers that
  1264. 45:56go into any one estimate of the mean and
  1265. 45:58variance and it allows things to be a
  1266. 46:01bit more stable and less Wiggly inside
  1267. 46:03those estimates of those statistics so
  1268. 46:07pretty nice with this more General
  1269. 46:08architecture in place we are now set up
  1270. 46:10to push the performance further by
  1271. 46:12increasing the size of the network so
  1272. 46:14for example I bumped up the number of
  1273. 46:16embeddings to 24 instead of 10 and also
  1274. 46:19increased number of hidden units but
  1275. 46:21using the exact same architecture we now
  1276. 46:23have 76 000 parameters and the training
  1277. 46:25takes a lot longer but we do get a nice
  1278. 46:28curve and then when you actually
  1279. 46:29evaluate the performance we are now
  1280. 46:31getting validation performance of 1.993
  1281. 46:33so we've crossed over the 2.0 sort of
  1282. 46:36territory and right about 1.99 but we
  1283. 46:39are starting to have to wait quite a bit
  1284. 46:42longer and we're a little bit in the
  1285. 46:44dark with respect to the correct setting
  1286. 46:46of the hyper parameters here and the
  1287. 46:47learning rates and so on because the
  1288. 46:48experiments are starting to take longer
  1289. 46:50to train and so we are missing sort of
  1290. 46:52like an experimental harness on which we
  1291. 46:54could run a number of experiments and
  1292. 46:56really tune this architecture very well
  1293. 46:58so I'd like to conclude now with a few
  1294. 46:59notes we basically improved our
  1295. 47:02performance from a starting of 2.1 down
  1296. 47:04to 1.9 but I don't want that to be the
  1297. 47:06focus because honestly we're kind of in
  1298. 47:08the dark we have no experimental harness
  1299. 47:10we're just guessing and checking and
  1300. 47:12this whole thing is terrible we're just
  1301. 47:13looking at the training loss normally
  1302. 47:15you want to look at both the training
  1303. 47:17and the validation loss together and the
  1304. 47:19whole thing looks different if you're
  1305. 47:20actually trying to squeeze out numbers
  1306. 47:23that said we did implement this
  1307. 47:25architecture from the wavenet paper but
  1308. 47:28we did not implement this specific uh
  1309. 47:31forward pass of it where you have a more
  1310. 47:33complicated a linear layer sort of that
  1311. 47:35is this gated linear layer kind of and
  1312. 47:38there's residual connections and Skip
  1313. 47:40connections and so on so we did not
  1314. 47:42Implement that we just implemented this
  1315. 47:44structure I would like to briefly hint
  1316. 47:46or preview how what we've done here
  1317. 47:48relates to convolutional neural networks
  1318. 47:50as used in the wavenet paper and
  1319. 47:52basically the use of convolutions is
  1320. 47:54strictly for efficiency it doesn't
  1321. 47:56actually change the model we've
  1322. 47:57implemented
  1323. 47:58so here for example
  1324. 48:00let me look at a specific name to work
  1325. 48:02with an example so there's a name in our
  1326. 48:05training set and it's DeAndre and it has
  1327. 48:08seven letters so that is eight
  1328. 48:10independent examples in our model so all
  1329. 48:12these rows here are independent examples
  1330. 48:14of the Android
  1331. 48:16now you can forward of course any one of
  1332. 48:18these rows independently so I can take
  1333. 48:20my model and call call it on any
  1334. 48:24individual index notice by the way here
  1335. 48:26I'm being a little bit tricky
  1336. 48:28the reason for this is that extra at
  1337. 48:30seven that shape is just
  1338. 48:33um one dimensional array of eight so you
  1339. 48:36can't actually call the model on it
  1340. 48:37you're going to get an error because
  1341. 48:39there's no batch dimension
  1342. 48:41so when you do extra at
  1343. 48:45a list of seven then the shape of this
  1344. 48:47becomes one by eight so I get an extra
  1345. 48:49batch dimension of one and then we can
  1346. 48:52forward the model
  1347. 48:53so
  1348. 48:55that forwards a single example and you
  1349. 48:57might imagine that you actually may want
  1350. 48:59to forward all of these eight
  1351. 49:01um at the same time
  1352. 49:03so pre-allocating some memory and then
  1353. 49:05doing a for Loop eight times and
  1354. 49:07forwarding all of those eight here will
  1355. 49:10give us all the logits in all these
  1356. 49:11different cases
  1357. 49:13now for us with the model as we've
  1358. 49:14implemented it right now this is eight
  1359. 49:16independent calls to our model
  1360. 49:18but what convolutions allow you to do is
  1361. 49:20it allow you to basically slide this
  1362. 49:22model efficiently over the input
  1363. 49:24sequence and so this for Loop can be
  1364. 49:27done not outside in Python but inside of
  1365. 49:31kernels in Cuda and so this for Loop
  1366. 49:33gets hidden into the convolution
  1367. 49:35so the convolution basically you can
  1368. 49:37cover this it's a for Loop applying a
  1369. 49:40little linear filter over space of some
  1370. 49:43input sequence and in our case the space
  1371. 49:45we're interested in is one dimensional
  1372. 49:46and we're interested in sliding these
  1373. 49:48filters over the input data
  1374. 49:51so this diagram actually is fairly good
  1375. 49:54as well
  1376. 49:55basically what we've done is here they
  1377. 49:57are highlighting in Black one individ
  1378. 49:59one single sort of like tree of this
  1379. 50:01calculation so just calculating the
  1380. 50:03single output example here
  1381. 50:06um
  1382. 50:07and so this is basically what we've
  1383. 50:08implemented here we've implemented a
  1384. 50:10single this black structure we've
  1385. 50:13implemented that and calculated a single
  1386. 50:15output like a single example
  1387. 50:17but what collusions allow you to do is
  1388. 50:19it allows you to take this black
  1389. 50:20structure and kind of like slide it over
  1390. 50:23the input sequence here and calculate
  1391. 50:26all of these orange outputs at the same
  1392. 50:29time or here that corresponds to
  1393. 50:31calculating all of these outputs of
  1394. 50:34um at all the positions of DeAndre at
  1395. 50:37the same time
  1396. 50:38and the reason that this is much more
  1397. 50:41efficient is because number one as I
  1398. 50:43mentioned the for Loop is inside the
  1399. 50:45Cuda kernels in the sliding so that
  1400. 50:48makes it efficient but number two notice
  1401. 50:50the variable reuse here for example if
  1402. 50:52we look at this circle this node here
  1403. 50:54this node here is the right child of
  1404. 50:56this node but is also the left child of
  1405. 50:59the node here
  1406. 51:01and so basically this node and its value
  1407. 51:03is used twice
  1408. 51:05and so right now in this naive way we'd
  1409. 51:08have to recalculate it but here we are
  1410. 51:11allowed to reuse it
  1411. 51:12so in the convolutional neural network
  1412. 51:14you think of these linear layers that we
  1413. 51:16have up above as filters and we take
  1414. 51:19these filters and they're linear filters
  1415. 51:21and you slide them over input sequence
  1416. 51:23and we calculate the first layer and
  1417. 51:25then the second layer and then the third
  1418. 51:26layer and then the output layer of the
  1419. 51:28sandwich and it's all done very
  1420. 51:30efficiently using these convolutions
  1421. 51:32so we're going to cover that in a future
  1422. 51:34video the second thing I hope you took
  1423. 51:35away from this video is you've seen me
  1424. 51:37basically Implement all of these layer
  1425. 51:40Lego building blocks or module building
  1426. 51:42blocks and I'm implementing them over
  1427. 51:45here and we've implemented a number of
  1428. 51:46layers together and we've also
  1429. 51:48implemented these these containers and
  1430. 51:51we've overall pytorchified our code
  1431. 51:53quite a bit more
  1432. 51:54now basically what we're doing here is
  1433. 51:56we're re-implementing torch.nn which is
  1434. 51:59the neural networks library on top of
  1435. 52:02torch.tensor and it looks very much like
  1436. 52:04this except it is much better because
  1437. 52:07because it's in pi torch instead of
  1438. 52:08jingling my Jupiter notebook so I think
  1439. 52:11going forward I will probably have
  1440. 52:13considered us having unlocked
  1441. 52:15um torch.nn we understand roughly what's
  1442. 52:18in there how these modules work how
  1443. 52:19they're nested and what they're doing on
  1444. 52:21top of torture tensor so hopefully we'll
  1445. 52:24just uh we'll just switch over and
  1446. 52:25continue and start using torch.net
  1447. 52:27directly the next thing I hope you got a
  1448. 52:29bit of a sense of is what the
  1449. 52:31development process of building deep
  1450. 52:33neural networks looks like which I think
  1451. 52:35was relatively representative to some
  1452. 52:36extent so number one we are spending a
  1453. 52:39lot of time in the documentation page of
  1454. 52:41pytorch and we're reading through all
  1455. 52:44the layers looking at documentations
  1456. 52:45where the shapes of the inputs what can
  1457. 52:48they be what does the layer do and so on
  1458. 52:51unfortunately I have to say the
  1459. 52:53patreon's documentation is not are very
  1460. 52:55good they spend a ton of time on
  1461. 52:57Hardcore engineering of all kinds of
  1462. 52:59distributed Primitives Etc but as far as
  1463. 53:01I can tell no one is maintaining any
  1464. 53:03documentation it will lie to you it will
  1465. 53:06be wrong it will be incomplete it will
  1466. 53:08be unclear so unfortunately it is what
  1467. 53:12it is and you just kind of do your best
  1468. 53:14um with what they've given us
  1469. 53:18um number two
  1470. 53:20uh the other thing that I hope you got a
  1471. 53:22sense of is there's a ton of trying to
  1472. 53:24make the shapes work and there's a lot
  1473. 53:26of gymnastics around these
  1474. 53:27multi-dimensional arrays and are they
  1475. 53:29two-dimensional three-dimensional
  1476. 53:30four-dimensional uh what layers take
  1477. 53:32what shapes is it NCL or NLC and you're
  1478. 53:36promoting and viewing and it just can
  1479. 53:39get pretty messy and so that brings me
  1480. 53:40to number three I very often prototype
  1481. 53:43these layers and implementations in
  1482. 53:44jupyter notebooks and make sure that all
  1483. 53:46the shapes work out and I'm spending a
  1484. 53:48lot of time basically babysitting the
  1485. 53:50shapes and making sure everything is
  1486. 53:52correct and then once I'm satisfied with
  1487. 53:54the functionality in the Jupiter
  1488. 53:55notebook I will take that code and copy
  1489. 53:57paste it into my repository of actual
  1490. 53:59code that I'm training with and so then
  1491. 54:02I'm working with vs code on the side so
  1492. 54:04I usually have jupyter notebook and vs
  1493. 54:06code I develop in Jupiter notebook I
  1494. 54:07paste into vs code and then I kick off
  1495. 54:09experiments from from the reaper of
  1496. 54:11course from the code repository so
  1497. 54:14that's roughly some notes on the
  1498. 54:16development process of working with
  1499. 54:17neurons lastly I think this lecture
  1500. 54:19unlocks a lot of potential further
  1501. 54:21lectures because number one we have to
  1502. 54:23convert our neural network to actually
  1503. 54:25use these dilated causal convolutional
  1504. 54:27layers so implementing the comnet number
  1505. 54:30two potentially starting to get into
  1506. 54:32what this means whatever residual
  1507. 54:34connections and Skip connections and why
  1508. 54:36are they useful
  1509. 54:37number three we as I mentioned we don't
  1510. 54:40have any experimental harness so right
  1511. 54:42now I'm just guessing checking
  1512. 54:44everything this is not representative of
  1513. 54:45typical deep learning workflows you have
  1514. 54:47to set up your evaluation harness you
  1515. 54:49can kick off experiments you have lots
  1516. 54:51of arguments that your script can take
  1517. 54:53you're you're kicking off a lot of
  1518. 54:54experimentation you're looking at a lot
  1519. 54:56of plots of training and validation
  1520. 54:57losses and you're looking at what is
  1521. 54:59working and what is not working and
  1522. 55:01you're working on this like population
  1523. 55:02level and you're doing all these hyper
  1524. 55:04parameter searches and so we've done
  1525. 55:06none of that so far so how to set that
  1526. 55:09up and how to make it good I think as a
  1527. 55:11whole another topic number three we
  1528. 55:14should probably cover recurring neural
  1529. 55:16networks RNs lstm's grooves and of
  1530. 55:19course Transformers so many uh places to
  1531. 55:22go and we'll cover that in the future
  1532. 55:24for now bye sorry I forgot to say that
  1533. 55:27if you are interested I think it is kind
  1534. 55:30of interesting to try to beat this
  1535. 55:31number 1.993 because I really haven't
  1536. 55:34tried a lot of experimentation here and
  1537. 55:36there's quite a bit of fruit potentially
  1538. 55:37to still purchase further so I haven't
  1539. 55:40tried any other ways of allocating these
  1540. 55:42channels in this neural net maybe the
  1541. 55:44number of dimensions for the embedding
  1542. 55:47is all wrong maybe it's possible to
  1543. 55:49actually take the original network with
  1544. 55:50just one hidden layer and make it big
  1545. 55:53enough and actually beat my fancy
  1546. 55:54hierarchical Network it's not obvious
  1547. 55:56that would be kind of embarrassing if
  1548. 55:59this did not do better even once you
  1549. 56:01torture it a little bit maybe you can
  1550. 56:03read the weight net paper and try to
  1551. 56:04figure out how some of these layers work
  1552. 56:06and Implement them yourselves using what
  1553. 56:07we have
  1554. 56:08and of course you can always tune some
  1555. 56:10of the initialization or some of the
  1556. 56:12optimization and see if you can improve
  1557. 56:15it that way so I'd be curious if people
  1558. 56:16can come up with some ways to beat this
  1559. 56:18and yeah that's it for now bye

About this transcript

This page contains the full transcript of Building makemore Part 5: Building a WaveNet by Andrej Karpathy, generated from the public captions YouTube serves with the video. The transcript has 10,385 words across 1,559 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.