|
14 | 14 | "\n",
|
15 | 15 | "------------------------------\n",
|
16 | 16 | "\n",
|
17 |
| - "Writing clean vectorized `numpy` code is in many cases essential, because good knowlage of this tool will help you write code that is both elegant and efficient and thus leads into faster and more effective experiemnts. Much more importantly, however, it will become easier for you to rewrite matematical equations because your code **will read like equations**. So lets start with some basics." |
| 17 | + "Writing clean vectorized `numpy` code is in many cases essential. Familiarity with this tool will help you write code that is both elegant and efficient and thus leads into faster and more effective experiemnts. Much more importantly, however, it will become easier for you to rewrite matematical equations because your code **will read like equations**. So lets start with some basics." |
18 | 18 | ]
|
19 | 19 | },
|
20 | 20 | {
|
|
80 | 80 | "Through this tutorial, we will try to keep the names of vectors (which will be lower-case) and matricies (which will\n",
|
81 | 81 | "be keep upper-case) constant. Now, when we know how to create basic numpy objects, lets talk about them a bit.\n",
|
82 | 82 | "\n",
|
83 |
| - "All objects like these (vector, matrix...) have attribute **shape** which describes, as the name suggests, their shape. Or in other words what do the dimensions of a particular object look like. This attribute can be accesed by writing `.shape` after the name of the object as follows:" |
| 83 | + "All objects like these (vector, matrix...) have **shape** attribute which describes, as the name suggests, their shape. Or in other words, what do the dimensions of a particular object look like. This attribute can be accesed by writing `.shape` after the name of the object as follows:" |
84 | 84 | ]
|
85 | 85 | },
|
86 | 86 | {
|
|
101 | 101 | " [1, 2, 3, 4]])\n",
|
102 | 102 | "print(\"{}\\n\".format(A))\n",
|
103 | 103 | "\n",
|
104 |
| - "# create 3D matrix\n", |
| 104 | + "# create 3D matrix (literally a 3D Python array wrapped in np.array)\n", |
105 | 105 | "B = np.array([[[1, 2], [1, 2],\n",
|
106 | 106 | " [3, 4], [3, 4]],\n",
|
107 | 107 | " [[4, 5], [5, 6],\n",
|
|
118 | 118 | "cell_type": "markdown",
|
119 | 119 | "metadata": {},
|
120 | 120 | "source": [
|
121 |
| - "We will mostly be working with high dimensional objects. \n", |
| 121 | + "Throughout this course we will mostly work with high dimensional objects. \n", |
122 | 122 | "\n",
|
123 |
| - "In scinetific computation practice, it is often needed to create a multidimensional object with certain values, such as an array with all elements equal to zero or a matrix initialized with values from the normal distribution. Luckilly, `numpy` is awesome in this regard, as it provides functions that allow us to quickly create these objects.\n", |
| 123 | + "In scientific computation practice, it is often needed to create a multidimensional object with certain values, such as an array with all elements equal to zero or a matrix initialized with values sampled from the normal distribution.\n", |
| 124 | + "\n", |
| 125 | + "Luckilly, `numpy` is awesome in this regard, as it provides functions that allow us to quickly create objects like this.\n", |
124 | 126 | "\n",
|
125 | 127 | "Here are some examples of usage of functions for matrix and array creation that you may find useful:"
|
126 | 128 | ]
|
|
139 | 141 | "print(\"a = {}\".format(a))\n",
|
140 | 142 | "\n",
|
141 | 143 | "# we can also set its starting point. So to create vector [10, 11, 12, 13, 14]\n",
|
| 144 | + "# we would do\n", |
142 | 145 | "v = np.arange(10, 15)\n",
|
143 | 146 | "print(\"v = {}\".format(v))\n",
|
144 | 147 | "\n",
|
145 | 148 | "# and also we can set step size. So to create a vector with elements spaced by 10\n",
|
146 |
| - "# and starts at 10 and ends at 40, that is [10, 20, 30, 40]\n", |
| 149 | + "# with start at 10 and end at 40, that is [10, 20, 30, 40] we would do\n", |
147 | 150 | "u = np.arange(10, 50, 10)\n",
|
148 | 151 | "print(\"u = {}\".format(u))\n",
|
149 | 152 | "\n",
|
|
172 | 175 | "print(\"X with shape {}\".format(X.shape))\n",
|
173 | 176 | "print(X)\n",
|
174 | 177 | "\n",
|
175 |
| - "# Create 3D matrix with random values from normal distribution of shape (2, 3, 2)\n", |
| 178 | + "# Create 3D matrix with values sampled from normal distribution of shape (2, 3, 2)\n", |
176 | 179 | "Y = np.random.randn(2, 3, 2)\n",
|
177 | 180 | "print(\"\\nY with shape {}\".format(Y.shape))\n",
|
178 | 181 | "print(Y)"
|
|
182 | 185 | "cell_type": "markdown",
|
183 | 186 | "metadata": {},
|
184 | 187 | "source": [
|
185 |
| - "Once you have these objects initalized, you can do artithmetic operations with them:" |
| 188 | + "Once we have these objects initalized, there are a ton of aritmetic operations we can do with them:" |
186 | 189 | ]
|
187 | 190 | },
|
188 | 191 | {
|
|
197 | 200 | "a = np.array([1, 2, 3, 4, 5])\n",
|
198 | 201 | "print(\"a = {}\".format(a))\n",
|
199 | 202 | "\n",
|
200 |
| - "# add constant value to each element of a vector\n", |
| 203 | + "# add a constant value to each element of a vector\n", |
201 | 204 | "print(\"a + 5 = {}\".format(a + 5))\n",
|
202 | 205 | "\n",
|
203 |
| - "# multiply each element of a vector by constant value\n", |
| 206 | + "# multiply each element of a vector by a constant value\n", |
204 | 207 | "print(\"a * 5 = {}\".format(a * 5))\n",
|
205 | 208 | "\n",
|
206 |
| - "# square vector a\n", |
| 209 | + "# square the vector a\n", |
207 | 210 | "print(\"a^2 = {}\".format(a ** 2))\n",
|
208 | 211 | "\n",
|
209 | 212 | "v = np.array([2, 2, 3, 2, 3])\n",
|
210 | 213 | "print(\"v = {}\".format(v))\n",
|
211 | 214 | "\n",
|
212 |
| - "# multiply 'a' by 'v'\n", |
| 215 | + "# multiply vector a by vector v\n", |
213 | 216 | "print(\"a * v = {}\".format(a * v))"
|
214 | 217 | ]
|
215 | 218 | },
|
216 | 219 | {
|
217 | 220 | "cell_type": "markdown",
|
218 | 221 | "metadata": {},
|
219 | 222 | "source": [
|
220 |
| - "To mutliple matrices together (to get their **scalar product**, not the **dot product**), we do not need to do anything special:" |
| 223 | + "To multiply matrices together (to get their **scalar product**, not the **dot product**), we do not need to do anything special:" |
221 | 224 | ]
|
222 | 225 | },
|
223 | 226 | {
|
|
271 | 274 | "cell_type": "markdown",
|
272 | 275 | "metadata": {},
|
273 | 276 | "source": [
|
274 |
| - "Oftentimes your vectors/matricies will have wrong shape. For instance, your data can be (and often times will be) stored in common data storing formats like CSV. This formats are easily loadable to Python but not very usefull, since our models will require vectors or matricies of certain shape. To reshape our vectors/matricies numpy provides a `.reshape` function.\n", |
| 277 | + "Oftentimes your vectors/matricies will have a shape that is just not what you would want. \n", |
| 278 | + "\n", |
| 279 | + "For instance, your data can be (and often times will be) stored in common data storing formats like CSV. This formats are easily loadable to Python but not very usefull, since our models will require vectors or matricies of certain shape. To reshape our vectors/matricies numpy provides a `.reshape` function.\n", |
275 | 280 | "\n",
|
276 |
| - "For example, if we would find interesting data that consits out of 100 images each having `36x36`px and loaded it into our python code. Our matrix would have shape (100, 36, 36). Now, we would like to use this to train some model. But our model takes a vector not a matrics. We can easily fix it with numpy." |
| 281 | + "For example, if we would find interesting data that consits of 100 gray scale images each having `36 x 36`px and loaded it into our python code. Note that since these are grayscale images, each pixel is represented as a single scalar value.\n", |
| 282 | + "\n", |
| 283 | + "Long story short, our matrix would have shape `(100, 36, 36)`. Now, we would like to use this to train some model. But our model takes a vector, not a matrix. We can easily preprocess this data accordingly with `numpy`." |
277 | 284 | ]
|
278 | 285 | },
|
279 | 286 | {
|
|
343 | 350 | "source": [
|
344 | 351 | "You may also often times need to find the `sum` or `mean` of a vector or a matrix. \n",
|
345 | 352 | "\n",
|
346 |
| - "For all operations like this `numpy` already provides a function (`mean`, `sum`, ...). These functions can also take an optional `axis` argument, which specifies in which axis should an operation be taken. For instance, if we would like to take sum of a first axis of vector `x` we would do something like `np.sum(x, axis=0)` (dimension are indexed from zero). " |
| 353 | + "For all operations like this `numpy` already provides an implemented function (`mean`, `sum`, ...). These functions can also take an optional `axis` argument, which specifies in which axis should an operation be taken. \n", |
| 354 | + "\n", |
| 355 | + "For instance, if we would like to take sum of a first axis of vector `x` we would do something like `np.sum(x, axis=0)` (dimension are indexed from zero). " |
347 | 356 | ]
|
348 | 357 | },
|
349 | 358 | {
|
350 | 359 | "cell_type": "code",
|
351 | 360 | "execution_count": null,
|
352 | 361 | "metadata": {
|
353 |
| - "collapsed": true, |
354 | 362 | "scrolled": false
|
355 | 363 | },
|
356 | 364 | "outputs": [],
|
357 | 365 | "source": [
|
358 |
| - "# create random vector x\n", |
359 |
| - "x = np.array([[1, 3, 5, 7],\n", |
| 366 | + "# create some matrix x\n", |
| 367 | + "X = np.array([[1, 3, 5, 7],\n", |
360 | 368 | " [6, 7, 3, 1],\n",
|
361 | 369 | " [1, 4, 5, 1],\n",
|
362 | 370 | " [7, 8, 4, 3],\n",
|
363 | 371 | " [1, 2, 3, 4],\n",
|
364 | 372 | " [9, 5, 4, 3],\n",
|
365 | 373 | " [9, 8, 7, 6]])\n",
|
366 |
| - "print(\"Shape of x: {}\\n\".format(x.shape))\n", |
| 374 | + "print(\"Shape of X: {}\\n\".format(X.shape))\n", |
367 | 375 | "\n",
|
368 | 376 | "# take sum of first axis\n",
|
369 |
| - "s = np.sum(x, axis=0)\n", |
370 |
| - "print(\"sum of first dimension of a vector x: \\ns={}\\n\".format(s))\n", |
| 377 | + "s = np.sum(X, axis=0)\n", |
| 378 | + "print(\"sum of first dimension of matrix x: \\ns={}\\n\".format(s))\n", |
371 | 379 | "\n",
|
372 | 380 | "print(\"Shape of s: {}\".format(s.shape))"
|
373 | 381 | ]
|
|
432 | 440 | "metadata": {},
|
433 | 441 | "source": [
|
434 | 442 | "`numpy` also supports an operation called **broadcasting**. This can be better explained on some example.\n",
|
435 |
| - "Let us assume we have a 2D matrix with 10 training examples, each of them having 3 features (matrix `X` of shape (10, 3)).\n", |
| 443 | + "Let us assume we have a 2D matrix with 10 training examples, each of them having 3 features (matrix `X` of shape (10, 3)). Further suppose we also have a vector `w` of weights for each feature of size `(3, )`. \n", |
436 | 444 | "\n",
|
437 |
| - "Further suppose we also have a vector `w` of weights for each feature of size (3, ). Now, we would like to weigh each one of our traning examples with our wieght vector `w`. In plain Python we would probably have to write 2 `for` loops. In `numpy` it seems that that since we can multiply vectors we would have to write just one.\n", |
| 445 | + "Now, we would like to weigh each one of our traning examples with our wieght vector `w`. In plain Python we would probably have to write 2 `for` loops. In `numpy` it seems that that since we can multiply vectors we would have to write just one.\n", |
438 | 446 | "\n",
|
439 |
| - "But this has been all taken care of for us by **broadcasting**. In the end, we can just use simple multiplication:" |
| 447 | + "Thankfully, all of this has been taken care of for us by **broadcasting**. In the end, we can just use simple multiplication:" |
440 | 448 | ]
|
441 | 449 | },
|
442 | 450 | {
|
443 | 451 | "cell_type": "code",
|
444 | 452 | "execution_count": null,
|
445 | 453 | "metadata": {
|
446 |
| - "collapsed": true, |
447 | 454 | "scrolled": false
|
448 | 455 | },
|
449 | 456 | "outputs": [],
|
|
461 | 468 | "\n",
|
462 | 469 | "# multiply each vector of shape (3,) in a second \n",
|
463 | 470 | "# dimension of matrix X by weight vector w\n",
|
| 471 | + "print(\"Multiplication result:\")\n", |
464 | 472 | "print(X * w)"
|
465 | 473 | ]
|
466 | 474 | },
|
467 | 475 | {
|
468 | 476 | "cell_type": "markdown",
|
469 | 477 | "metadata": {},
|
470 | 478 | "source": [
|
471 |
| - "If we would want to set all elements in second dimension of the first element of some matrix to zero, we can also do this with `numpy`s broadcasting by simply typing **:** instead of a number in a specific dimension." |
| 479 | + "If we would want to set all elements in second dimension of the first element of some matrix to zero, we can also do this with `numpy`s broadcasting by simply typing **:** instead of a number in a specific dimension.\n", |
| 480 | + "\n", |
| 481 | + "*Note*: the magical colon **:** here is actually the delimeter of syntax for \"slicing\" Python sequences (of any kind, really). For instance,\n", |
| 482 | + "\n", |
| 483 | + "- `[1:5]` is equivalent to saying \"from 1 to 5\"\n", |
| 484 | + "- `[:5]` is equivalent to saying \"from beginning to 5\"\n", |
| 485 | + "- `[1:]` is equivalent to saying \"from 1 to end\"\n", |
| 486 | + "\n", |
| 487 | + "Taking all of this into consideration, in the end we get `[:]` which can be equivalently described as \"from beginning to end\"" |
472 | 488 | ]
|
473 | 489 | },
|
474 | 490 | {
|
|
502 | 518 | "cell_type": "code",
|
503 | 519 | "execution_count": null,
|
504 | 520 | "metadata": {
|
505 |
| - "collapsed": true, |
506 | 521 | "scrolled": false
|
507 | 522 | },
|
508 | 523 | "outputs": [],
|
|
549 | 564 | "cell_type": "code",
|
550 | 565 | "execution_count": null,
|
551 | 566 | "metadata": {
|
552 |
| - "collapsed": true, |
553 | 567 | "scrolled": false
|
554 | 568 | },
|
555 | 569 | "outputs": [],
|
|
575 | 589 | "cell_type": "code",
|
576 | 590 | "execution_count": null,
|
577 | 591 | "metadata": {
|
578 |
| - "collapsed": true, |
579 | 592 | "scrolled": false
|
580 | 593 | },
|
581 | 594 | "outputs": [],
|
|
623 | 636 | "source": [
|
624 | 637 | "<h5 style=\"color: #1B1BFF\">Your input required:</h5>\n",
|
625 | 638 | "\n",
|
626 |
| - "Create a function that will set all the elements of a given array/matrix under a specified threshold to a specific value (we prepared the header for you)." |
| 639 | + "Create a function that will set all the elements of a given array/matrix under a specified threshold to a specific value (we prepared the function header for you)." |
627 | 640 | ]
|
628 | 641 | },
|
629 | 642 | {
|
|
674 | 687 | "source": [
|
675 | 688 | "Rewrite this matematical equation first with the use of loops and then as functional vectorized numpy code: \n",
|
676 | 689 | "\n",
|
677 |
| - "$$y = \\frac{1}{n}\\sum^n{X_i}$$" |
| 690 | + "$$y = \\frac{1}{n}\\sum_i^n{X_i}$$" |
678 | 691 | ]
|
679 | 692 | },
|
680 | 693 | {
|
|
785 | 798 | "metadata": {},
|
786 | 799 | "source": [
|
787 | 800 | "------------------------------------------------------------------------------------------------------------------\n",
|
788 |
| - "### Bonus question for 5 points:\n", |
789 | 801 | "\n",
|
790 |
| - "We loaded a picture for you. With just reshape and function `rollaxis()` (check out the offical docs) split the image into equal chunks. In other words, simulate sliding window cutter that will cutout window of size `80x80` each **80 pixels**. Your final array should have shape `108x80x80x3`. This should not take more than few lines of code. You can also pass the final array to `show_cut_image(<your array here>)` function to see some of your cutouts." |
| 802 | + "### Bonus question for 3 points:\n", |
| 803 | + "\n", |
| 804 | + "We loaded a picture for you. With just reshape and function `rollaxis()` (check out the offical docs) split the image into equal chunks. In other words, simulate sliding window cutter that will cutout window of size `80 x 80` each **80 pixels**. Your final array should have shape `108 x 80 x 80 x 3`. This should not take more than few lines of code. You can also pass the final array to `show_cut_image(<your array here>)` function to see some of your cutouts." |
791 | 805 | ]
|
792 | 806 | },
|
793 | 807 | {
|
794 | 808 | "cell_type": "code",
|
795 | 809 | "execution_count": null,
|
796 | 810 | "metadata": {
|
797 |
| - "collapsed": true, |
798 | 811 | "scrolled": false
|
799 | 812 | },
|
800 | 813 | "outputs": [],
|
|
829 | 842 | "source": [
|
830 | 843 | "### Submission details\n",
|
831 | 844 | "\n",
|
832 |
| - "Please submit the filled in `.ipynb` file to [Moodle](https://moodle.uniba.sk/moodle/inf11/course/view.php?id=601). Should that be a problem in any way, please feel free to contact the course TAs.\n", |
| 845 | + "Please save your solutions to file called in `<firstname>_<lastname>.ipynb` Once you have done that, please submit it to [Moodle](https://moodle.uniba.sk/moodle/inf11/course/view.php?id=710). Should that be a problem in any way, please feel free to contact the course TAs.\n", |
833 | 846 | "\n",
|
834 |
| - "The deadline for this assignment is the **7th of October, 23:55 CEST**.\n", |
| 847 | + "The deadline for this assignment is the **6th of October, 23:55 CEST**.\n", |
835 | 848 | "\n",
|
836 | 849 | "*If you need any help with this assignment, please feel free to ask the course TAs during their office hours, which can be found at the [course website](http://compbio.fmph.uniba.sk/vyuka/ml/).*\n",
|
837 | 850 | "\n",
|
|
849 | 862 | "language_info": {
|
850 | 863 | "codemirror_mode": {
|
851 | 864 | "name": "ipython",
|
852 |
| - "version": 2 |
| 865 | + "version": 3 |
853 | 866 | },
|
854 | 867 | "file_extension": ".py",
|
855 | 868 | "mimetype": "text/x-python",
|
856 | 869 | "name": "python",
|
857 | 870 | "nbconvert_exporter": "python",
|
858 |
| - "pygments_lexer": "ipython2", |
859 |
| - "version": "2.7.13" |
| 871 | + "pygments_lexer": "ipython3", |
| 872 | + "version": "3.6.3" |
860 | 873 | }
|
861 | 874 | },
|
862 | 875 | "nbformat": 4,
|
|
0 commit comments