{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "TyD2gu6xTg3B" }, "source": [ "# 1. Introduction to Python 🐍\n", "\n", "\"Open" ] }, { "cell_type": "markdown", "metadata": { "id": "zbJ2fw29OHAX" }, "source": [ "This Notebook was originally prepared by [Mathieu Blondel](https://mblondel.org/) and few modifications have been made by us." ] }, { "cell_type": "markdown", "metadata": { "id": "JbVT11Y8CbAu" }, "source": [ "## Goals of this exercise 🌟" ] }, { "cell_type": "markdown", "metadata": { "id": "kw1B2R_WCU7X" }, "source": [ "\n", "\n", "* We will learn about the programming language Python as well as [NumPy](https://numpy.org/) and [Matplotlib](https://matplotlib.org/), two fundamental tools for data science and machine learning in Python.\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "YV4sYCn8EPwb" }, "source": [ "## What are Jupyter Notebooks and Google Colab? 🤔" ] }, { "cell_type": "markdown", "metadata": { "id": "2HuuwOcQEYQI" }, "source": [ "Notebooks are a great way to mix executable code with rich contents (HTML, images, equations written in LaTeX). Google Colab allows to run notebooks on the cloud for free without any prior installation, while leveraging the power of [GPUs](https://en.wikipedia.org/wiki/Graphics_processing_unit)." ] }, { "cell_type": "markdown", "metadata": { "id": "t0XmMkPuGGOs" }, "source": [ "This document that you are reading is not a static web page, but an interactive environment called a notebook, that lets you write and execute code. Notebooks consist of so-called code cells, blocks of one or more Python instructions. For example, here is a code cell that stores the result of a computation (the number of seconds in a day) in a variable and prints its value:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "qeGAvLq1ALJ4", "outputId": "98125183-7dbb-434d-d37f-636f211e9908" }, "outputs": [ { "data": { "text/plain": [ "86400" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "seconds_in_a_day = 24 * 60 * 60\n", "seconds_in_a_day" ] }, { "cell_type": "markdown", "metadata": { "id": "njoPs3q1G75-" }, "source": [ "Click on the \"play\" button to execute the cell. You should be able to see the result. Alternatively, you can also execute the cell by pressing `Ctrl + Enter` if you are on Windows/Linux or `Command + Enter` if you are on a Mac." ] }, { "cell_type": "markdown", "metadata": { "id": "NvdYaBgHHdbw" }, "source": [ "Variables that you defined in one cell can later be used in other cells:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "s1kp5Zv0JBSx", "outputId": "bb15ad08-0397-4662-f9b8-b0985b898976" }, "outputs": [ { "data": { "text/plain": [ "604800" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "seconds_in_a_week = 7 * seconds_in_a_day\n", "seconds_in_a_week" ] }, { "cell_type": "markdown", "metadata": { "id": "uALfY4q1JFQ0" }, "source": [ "Note that the order of execution is important. For instance, if we do not run the cell storing `seconds_in_a_day` beforehand, the above cell will raise an error, as it depends on this variable. To make sure that you run all the cells in the correct order, you can also click on `Runtime` in the top-level menu, then `Run all`." ] }, { "cell_type": "markdown", "metadata": { "id": "HvXs_KaoRWQ9" }, "source": [ "### Exercise - code cells ❗❗\n", "\n", "Add a code cell below this cell: \n", "\n", "1. Click on this cell\n", "2. Click on `+ Code`\n", "3. In the new cell, compute the number of seconds in a year by reusing the variable `seconds_in_a_day`. Run the new cell.\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "qyLSwlxnJqXX" }, "source": [ "## Python 🐍" ] }, { "cell_type": "markdown", "metadata": { "id": "3ltwm91eJyQM" }, "source": [ "Python is one of the most popular programming languages for machine learning, both in academia and in industry. As such, it is essential to learn this language for anyone interested in machine learning. In this section, we will review Python basics." ] }, { "cell_type": "markdown", "metadata": { "id": "3EKvP6jiMZ9H" }, "source": [ "### Arithmetic operations" ] }, { "cell_type": "markdown", "metadata": { "id": "DDjs0-7YQ80h" }, "source": [ "Python supports the usual arithmetic operators: + (addition), * (multiplication), / (division), ** (power), // (integer division)." ] }, { "cell_type": "markdown", "metadata": { "id": "UhcbBQUiStHG" }, "source": [ "### Lists" ] }, { "cell_type": "markdown", "metadata": { "id": "RkPn1IjNTCxA" }, "source": [ "Lists are a container type for ordered sequences of elements. Lists can be initialized empty" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "OrnV1ySAPtHp" }, "outputs": [], "source": [ "my_list = []" ] }, { "cell_type": "markdown", "metadata": { "id": "OwRqyYI9XnPK" }, "source": [ "or with some initial elements" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "Uq5YTJ1JXpOX" }, "outputs": [], "source": [ "my_list = [1, 2, 3]" ] }, { "cell_type": "markdown", "metadata": { "id": "Hk2WmojJXyyz" }, "source": [ "Lists have a dynamic size and elements can be added (appended) to them" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "QFTNqiYiXxAh", "outputId": "aeef5f18-37ba-43af-d79c-7aa769323268" }, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_list.append(4)\n", "my_list" ] }, { "cell_type": "markdown", "metadata": { "id": "IUnJuqQ2Yhzw" }, "source": [ "We can access individual elements of a list (indexing starts from 0)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "pyFxyZPVYpG_", "outputId": "e09e13f7-a3a3-4097-d89b-89801b15953b" }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_list[2]" ] }, { "cell_type": "markdown", "metadata": { "id": "hPMrIDYsdgMP" }, "source": [ "We can access \"slices\" of a list using `my_list[i:j]` where `i` is the start of the slice (again, indexing starts from 0) and `j` the end of the slice. For instance:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Ichf9p0gd7tJ", "outputId": "68bec7a4-0bd6-455e-abb6-e281053468de" }, "outputs": [ { "data": { "text/plain": [ "[2, 3]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_list[1:3]" ] }, { "cell_type": "markdown", "metadata": { "id": "KMbzH4tzQ9rI" }, "source": [ "Omitting the second index means that the slice shoud run until the end of the list" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "O7wCthKnREKV", "outputId": "29eacc7f-de0c-4bc5-cda6-ac675b7147a6" }, "outputs": [ { "data": { "text/plain": [ "[2, 3, 4]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_list[1:]" ] }, { "cell_type": "markdown", "metadata": { "id": "C5Aeu7PUebrK" }, "source": [ "We can check if an element is in the list using `in`" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "a_P5NCi-efvb", "outputId": "4198bcfe-839b-4a73-a755-1f15208aaddc" }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "5 in my_list" ] }, { "cell_type": "markdown", "metadata": { "id": "LypIsP5gkl10" }, "source": [ "The length of a list can be obtained using the `len` function" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "ac0FMsaKkrWc", "outputId": "2bdbfe60-79c9-47f6-8678-f19c9100db91" }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(my_list)" ] }, { "cell_type": "markdown", "metadata": { "id": "1c3RLStf7G2I" }, "source": [ "### Strings" ] }, { "cell_type": "markdown", "metadata": { "id": "Jm6hZhgz7KhI" }, "source": [ "Strings are used to store text. They can be defined using either single quotes or double quotes" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "id": "cCma6Oj_7T8n" }, "outputs": [], "source": [ "string1 = \"some text\"\n", "string2 = 'some other text'" ] }, { "cell_type": "markdown", "metadata": { "id": "Irr4xuWu7Znu" }, "source": [ "Strings behave similarly to lists. As such we can access individual elements in exactly the same way" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "id": "26_POhLO7iM3", "outputId": "564919bc-3368-4853-ad19-e0e435383e21" }, "outputs": [ { "data": { "text/plain": [ "'e'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "string1[3]" ] }, { "cell_type": "markdown", "metadata": { "id": "oA_UD0JV7oPw" }, "source": [ "and similarly for slices" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "id": "dcZFcLqQ7qCe", "outputId": "c5ea492e-ed98-4b55-f0fe-e7970bfa36b0" }, "outputs": [ { "data": { "text/plain": [ "'text'" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "string1[5:]" ] }, { "cell_type": "markdown", "metadata": { "id": "hOQ_CIiu76YG" }, "source": [ "String concatenation is performed using the `+` operator" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "id": "mxqNMKCY79_W", "outputId": "5d66117b-1bab-4f90-a4c7-a895f50f3aaa" }, "outputs": [ { "data": { "text/plain": [ "'some text some other text'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "string1 + \" \" + string2" ] }, { "cell_type": "markdown", "metadata": { "id": "7Lox2GZCMdIB" }, "source": [ "### Conditionals" ] }, { "cell_type": "markdown", "metadata": { "id": "-gXEAWFZfDTT" }, "source": [ "As their name indicates, conditionals are a way to execute code depending on whether a condition is True or False. As in other languages, Python supports `if` and `else` but `else if` is contracted into `elif`, as the example below demonstrates. " ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "xC_DMZjofoYZ", "outputId": "0144d338-2824-41ea-a377-672a7fccc163" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "positive\n" ] } ], "source": [ "my_variable = 5\n", "if my_variable < 0:\n", " print(\"negative\")\n", "elif my_variable == 0:\n", " print(\"null\")\n", "else: # my_variable > 0\n", " print(\"positive\")" ] }, { "cell_type": "markdown", "metadata": { "id": "Ag0SUokSf9jl" }, "source": [ "Here `<` and `>` are the strict `less` and `greater than` operators, while `==` is the equality operator (not to be confused with `=`, the variable assignment operator). The operators `<=` and `>=` can be used for less (resp. greater) than or equal comparisons." ] }, { "cell_type": "markdown", "metadata": { "id": "qTkQ2F_jy8wz" }, "source": [ "Contrary to other languages, blocks of code are delimited using indentation. Here, we use 2-space indentation but many programmers also use 4-space indentation. Any one is fine as long as you are consistent throughout your code." ] }, { "cell_type": "markdown", "metadata": { "id": "clWaFCzBMfkv" }, "source": [ "### Loops" ] }, { "cell_type": "markdown", "metadata": { "id": "_A5doqhTivWe" }, "source": [ "Loops are a way to execute a block of code multiple times. There are two main types of loops: **while** loops and **for** loops." ] }, { "cell_type": "markdown", "metadata": { "id": "YN8lwTxQkGEa" }, "source": [ "While loop" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7-QXGqgOjsr_", "outputId": "df68f7da-f690-4237-f79a-40e55e413719" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "i = 0\n", "while i < len(my_list):\n", " print(my_list[i])\n", " i += 1 # equivalent to i = i + 1" ] }, { "cell_type": "markdown", "metadata": { "id": "8mEI_ocfkSvZ" }, "source": [ "For loop" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "2QObx5mckMcI", "outputId": "8e898b21-c4cd-41d5-a5e7-a2b3b1c64bf5" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "for i in range(len(my_list)):\n", " print(my_list[i])" ] }, { "cell_type": "markdown", "metadata": { "id": "XO6qqppikZvm" }, "source": [ "If the goal is simply to iterate over a list, we can do so directly as follows" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "PjFKzN6zkeJ7", "outputId": "4215706a-61a9-4d12-f4ff-1fa6724c077c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "for element in my_list:\n", " print(element)" ] }, { "cell_type": "markdown", "metadata": { "id": "Cck4zwYrex02" }, "source": [ "### Functions" ] }, { "cell_type": "markdown", "metadata": { "id": "n1PbIf_ohxFO" }, "source": [ "To improve code readability, it is common to separate the code into different blocks, responsible for performing precise actions: functions! 😃 A function takes some inputs and process them to return some outputs." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "cImA09gOhRmx", "outputId": "71b08a6b-6a00-4078-b4dd-f0b095297a30" }, "outputs": [ { "data": { "text/plain": [ "36" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def square(x):\n", " return x ** 2\n", "\n", "def multiply(a, b):\n", " return a * b\n", "\n", "# Functions can be composed.\n", "square(multiply(3, 2))" ] }, { "cell_type": "markdown", "metadata": { "id": "75-5SOk9iYSt" }, "source": [ "To improve code readability, it is sometimes useful to explicitly name the arguments" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "wkIUuZHhidI0", "outputId": "48c2d1c2-bd45-4a86-d6aa-0b630561b3ba" }, "outputs": [ { "data": { "text/plain": [ "36" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "square(multiply(a=3, b=2))" ] }, { "cell_type": "markdown", "metadata": { "id": "LkpwbQEVMys2" }, "source": [ "### Exercise - conditionals, loops and function ❗❗" ] }, { "cell_type": "markdown", "metadata": { "id": "ASpVhol9ZXI0" }, "source": [ "**Exercise 1.** Using a conditional, write the [relu](https://en.wikipedia.org/wiki/Rectifier_(neural_networks)) function defined as follows\n", "\n", "$\\text{relu}(x) = \\left\\{\n", " \\begin{array}{rl}\n", " x, & \\text{if } x \\ge 0 \\\\\n", " 0, & \\text{otherwise }.\n", " \\end{array}\\right.$" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "id": "jlgyu65SaUvr" }, "outputs": [], "source": [ "def relu(x):\n", " # Write your function here\n", " return\n", "\n", "relu(-3)" ] }, { "cell_type": "markdown", "metadata": { "id": "Y3so0ceoakIw" }, "source": [ "**Exercise 2.** Using a foor loop, write a function that computes the [Euclidean norm](https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm) of a vector, represented as a list." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "id": "-IH-BD41bI1u" }, "outputs": [], "source": [ "def euclidean_norm(vector):\n", " # Write your function here\n", " return\n", "\n", "my_vector = [0.5, -1.2, 3.3, 4.5]\n", "# The result should be roughly 5.729746940310715\n", "euclidean_norm(my_vector)" ] }, { "cell_type": "markdown", "metadata": { "id": "SEXIh_e9cW3S" }, "source": [ "**Exercise 3.** Using a for loop and a conditional, write a function that returns the maximum value in a vector." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "id": "zd9ntMq0cb2e" }, "outputs": [], "source": [ "def vector_maximum(vector):\n", " # Write your function here\n", " return" ] }, { "cell_type": "markdown", "metadata": { "id": "qPAZA4OMc6sT" }, "source": [ "**Bonus exercise.** if time permits, write a function that sorts a list in ascending order (from smaller to bigger) using the [bubble sort](https://en.wikipedia.org/wiki/Bubble_sort) algorithm." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "id": "sBokdJO4dGyf" }, "outputs": [], "source": [ "def bubble_sort(my_list):\n", " # Write your function here\n", " return\n", "\n", "my_list = [1, -3, 3, 2]\n", "# Should return [-3, 1, 2, 3]\n", "bubble_sort(my_list)" ] }, { "cell_type": "markdown", "metadata": { "id": "jDxjvtEEM1vg" }, "source": [ "### Going further 💯" ] }, { "cell_type": "markdown", "metadata": { "id": "wRkmvzf-PdEp" }, "source": [ "Clearly, it is impossible to cover all the language features in this short introduction. To go further, we recommend the following resources:" ] }, { "cell_type": "markdown", "metadata": { "id": "n8nbPoWclRlH" }, "source": [ "\n", "\n", "\n", "* Python for for computations in science and engineering [booklets](https://pointbreezepubs.gumroad.com/).\n", "* List of Python [tutorials](https://wiki.python.org/moin/BeginnersGuide/Programmers)\n", "* Four-hour [course](https://www.youtube.com/watch?v=rfscVS0vtbw) on Youtube\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "6X4WJo3iM6m9" }, "source": [ "## NumPy 💻" ] }, { "cell_type": "markdown", "metadata": { "id": "_H3bNbLloXCY" }, "source": [ "[NumPy](https://numpy.org/) is a popular library for storing arrays of numbers and performing computations on them. Not only this enables to write often more succint code, this also makes the code faster, since most NumPy routines are implemented in C for speed." ] }, { "cell_type": "markdown", "metadata": { "id": "M7tI3XLhqwSX" }, "source": [ "To use NumPy in your program, you need to import it as follows" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "id": "phSPPyfyq2gX" }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": { "id": "9secCfFLNHEE" }, "source": [ "### Array creation\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "LSS2wEnkq97n" }, "source": [ "NumPy arrays can be created from Python lists" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Hfeg286yrLvJ", "outputId": "c42f5ee7-a0f8-4dfb-b534-a62708bbf156" }, "outputs": [ { "data": { "text/plain": [ "array([1, 2, 3])" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_array = np.array([1, 2, 3])\n", "my_array" ] }, { "cell_type": "markdown", "metadata": { "id": "Sy2EvrxFriAG" }, "source": [ "NumPy supports array of arbitrary dimension. For example, we can create two-dimensional arrays (e.g. to store a matrix) as follows" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "wM-GYVMsrzNs", "outputId": "128f54ec-65df-45fb-ee5e-a825c25c6634" }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 3],\n", " [4, 5, 6]])" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_2d_array = np.array([[1, 2, 3], [4, 5, 6]])\n", "my_2d_array" ] }, { "cell_type": "markdown", "metadata": { "id": "-kZMzYsAsVAc" }, "source": [ "We can access individual elements of a 2d-array using two indices" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "4q8X86BbscPd", "outputId": "73a0b46d-3d90-4cfd-dbfe-307dd23b50f4" }, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_2d_array[1, 2]" ] }, { "cell_type": "markdown", "metadata": { "id": "OfVIKyxkTh0p" }, "source": [ "We can also access rows" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "CrKnDAtyTlYe", "outputId": "6b364949-e1ad-4285-8821-d7990c0e8865" }, "outputs": [ { "data": { "text/plain": [ "array([4, 5, 6])" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_2d_array[1]" ] }, { "cell_type": "markdown", "metadata": { "id": "hskLBCp9ToCG" }, "source": [ "and columns" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "MOOFsLHhTozX", "outputId": "23d6d993-5b91-4450-e492-6aa7de1986ed" }, "outputs": [ { "data": { "text/plain": [ "array([3, 6])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_2d_array[:, 2]" ] }, { "cell_type": "markdown", "metadata": { "id": "keWK_5PHr9Q2" }, "source": [ "Arrays have a `shape` attribute" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "5QIo7l1Yr8m7", "outputId": "6613e4e3-351c-4e00-c22c-753c48ba842a" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(3,)\n", "(2, 3)\n" ] } ], "source": [ "print(my_array.shape)\n", "print(my_2d_array.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "LmX0EDWVsoDY" }, "source": [ "Contrary to Python lists, NumPy arrays must have a type and all elements of the array must have the same type." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "FZjOowkls57o", "outputId": "60d9d76d-c601-4ad3-963f-663df00ce536" }, "outputs": [ { "data": { "text/plain": [ "dtype('int32')" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_array.dtype" ] }, { "cell_type": "markdown", "metadata": { "id": "i5AvLdf7tGnZ" }, "source": [ "The main types are `int32` (32-bit integers), `int64` (64-bit integers), `float32` (32-bit real values) and `float64` (64-bit real values)." ] }, { "cell_type": "markdown", "metadata": { "id": "w8ym2qZCt9Nm" }, "source": [ "The `dtype` can be specified when creating the array" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "gXpM_FqruCVv", "outputId": "88d2cc90-e73f-4554-b09b-fd19dd9b3f35" }, "outputs": [ { "data": { "text/plain": [ "dtype('float64')" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_array = np.array([1, 2, 3], dtype=np.float64)\n", "my_array.dtype" ] }, { "cell_type": "markdown", "metadata": { "id": "WueaRIONuTdS" }, "source": [ "We can create arrays of all zeros using" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "jbD8N1UauK8r", "outputId": "775fe73a-316f-4605-d747-2c1431f1b013" }, "outputs": [ { "data": { "text/plain": [ "array([[0., 0., 0.],\n", " [0., 0., 0.]])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "zero_array = np.zeros((2, 3))\n", "zero_array" ] }, { "cell_type": "markdown", "metadata": { "id": "vn5go6qoudo4" }, "source": [ "and similarly for all ones using `ones` instead of `zeros`." ] }, { "cell_type": "markdown", "metadata": { "id": "1kCRlhLJuvZ6" }, "source": [ "We can create a range of values using" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "EcQXDeEmuxpO", "outputId": "9142690f-f66d-425a-9792-435f458d3742" }, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 2, 3, 4])" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.arange(5)" ] }, { "cell_type": "markdown", "metadata": { "id": "ZvJECk6Iu3uF" }, "source": [ "or specifying the starting point" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Pk3UzL3du_f8", "outputId": "2a9a07f4-907b-4553-d339-a4834d543544" }, "outputs": [ { "data": { "text/plain": [ "array([3, 4])" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.arange(3, 5)" ] }, { "cell_type": "markdown", "metadata": { "id": "f1JtqFSivJKG" }, "source": [ "Another useful routine is `linspace` for creating linearly spaced values in an interval. For instance, to create 10 values in `[0, 1]`, we can use" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "udHHjGAHvOQM", "outputId": "4be5895d-975a-40e8-a54f-b269e454e94b" }, "outputs": [ { "data": { "text/plain": [ "array([0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,\n", " 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.linspace(0, 1, 10)" ] }, { "cell_type": "markdown", "metadata": { "id": "WbcxAKobvgUT" }, "source": [ "Another important operation is `reshape`, for changing the shape of an array" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "4FPzTuDlvlLO", "outputId": "9697290e-0b71-4891-f45a-27da056f05f2" }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2],\n", " [3, 4],\n", " [5, 6]])" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_array = np.array([1, 2, 3, 4, 5, 6])\n", "my_array.reshape(3, 2)" ] }, { "cell_type": "markdown", "metadata": { "id": "G-QR80_g3N9Y" }, "source": [ "Play with these operations and make sure you understand them well." ] }, { "cell_type": "markdown", "metadata": { "id": "f9B0iCBlmfeY" }, "source": [ "### Basic operations" ] }, { "cell_type": "markdown", "metadata": { "id": "elQGgkqDxKLV" }, "source": [ "In NumPy, we express computations directly over arrays. This makes the code much more succint." ] }, { "cell_type": "markdown", "metadata": { "id": "hkCU1T8ixghX" }, "source": [ "Arithmetic operations can be performed directly over arrays. For instance, assuming two arrays have a compatible shape, we can add them as follows" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "4AoiRq42x5mI", "outputId": "bc259f8a-b32b-47d2-81a7-bbacce4c12ae" }, "outputs": [ { "data": { "text/plain": [ "array([5, 7, 9])" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "array_a = np.array([1, 2, 3])\n", "array_b = np.array([4, 5, 6])\n", "array_a + array_b" ] }, { "cell_type": "markdown", "metadata": { "id": "SyPqME2EyD4x" }, "source": [ "Compare this with the equivalent computation using a for loop" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "HxRFA_U2yfI-", "outputId": "050bc7fd-2872-41aa-f141-5cb098534d11" }, "outputs": [ { "data": { "text/plain": [ "array([5, 7, 9])" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "array_out = np.zeros_like(array_a)\n", "for i in range(len(array_a)):\n", " array_out[i] = array_a[i] + array_b[i]\n", "array_out" ] }, { "cell_type": "markdown", "metadata": { "id": "i2a-apX-zlPN" }, "source": [ "Not only this code is more verbose, it will also run much more slowly." ] }, { "cell_type": "markdown", "metadata": { "id": "Qdn8MwpR0wX_" }, "source": [ "In NumPy, functions that operates on arrays in an element-wise fashion are called [universal functions](https://numpy.org/doc/stable/reference/ufuncs.html). For instance, this is the case of `np.sin`" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "JoanjiMu1BH5", "outputId": "9ffbb222-89fc-438d-9e2c-46794d3689b8" }, "outputs": [ { "data": { "text/plain": [ "array([0.84147098, 0.90929743, 0.14112001])" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.sin(array_a)" ] }, { "cell_type": "markdown", "metadata": { "id": "jHljrPXg5h8W" }, "source": [ "Vector inner product can be performed using `np.dot`" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "TphR8oIx5ob9", "outputId": "ed943559-ad23-4d3f-8b8c-9188763fb07f" }, "outputs": [ { "data": { "text/plain": [ "32" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.dot(array_a, array_b)" ] }, { "cell_type": "markdown", "metadata": { "id": "lHInOiSW50OR" }, "source": [ "When the two arguments to `np.dot` are both 2d arrays, `np.dot` becomes matrix multiplication" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "QRbpbhPP6Up0", "outputId": "08fa7a5b-8e69-41ae-8e2c-30d309ea8213" }, "outputs": [ { "data": { "text/plain": [ "array([[-0.78372786, -0.849849 , -0.80062414, -0.17832529],\n", " [-0.95976823, -1.81073509, -0.58237139, -1.02972195],\n", " [-1.00018451, -1.01810406, -1.04100908, -0.2526472 ],\n", " [-0.73005882, -1.58872211, -0.40764567, -0.54033096],\n", " [-0.46429466, -1.14327928, -0.12796835, -0.87775792]])" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "array_A = np.random.rand(5, 3)\n", "array_B = np.random.randn(3, 4)\n", "np.dot(array_A, array_B)" ] }, { "cell_type": "markdown", "metadata": { "id": "odVawD9m6gwv" }, "source": [ "Matrix transpose can be done using `.transpose()` or `.T` for short" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "gvPe_JAO6mvF", "outputId": "87775836-ce5e-40f5-80a1-33c9613fe5c5" }, "outputs": [ { "data": { "text/plain": [ "array([[0.53487215, 0.9167603 , 0.61587894, 0.98524764, 0.48891708],\n", " [0.55500459, 0.73120862, 0.72928845, 0.44575498, 0.39782748],\n", " [0.05074806, 0.68669673, 0.14052154, 0.05889541, 0.68256372]])" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "array_A.T" ] }, { "cell_type": "markdown", "metadata": { "id": "JlWt3oFnE_E-" }, "source": [ "### Slicing and masking" ] }, { "cell_type": "markdown", "metadata": { "id": "e4aKKe7bFA65" }, "source": [ "Like Python lists, NumPy arrays support slicing" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "0kPhv2xcF1TP", "outputId": "fc04e16e-62b1-4237-aa99-249525314029" }, "outputs": [ { "data": { "text/plain": [ "array([5, 6, 7, 8, 9])" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.arange(10)[5:]" ] }, { "cell_type": "markdown", "metadata": { "id": "ITu2Wy4-GB2G" }, "source": [ "We can also select only certain elements from the array" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "8tlZzTB6GEyw", "outputId": "eee6c6cb-e7fb-479b-9ad4-26c45f1253e7" }, "outputs": [ { "data": { "text/plain": [ "array([5, 6, 7, 8, 9])" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.arange(10)\n", "mask = x >= 5\n", "x[mask]" ] }, { "cell_type": "markdown", "metadata": { "id": "NlGForCimjBL" }, "source": [ "### Exercise - arrays and linear algebra ❗❗" ] }, { "cell_type": "markdown", "metadata": { "id": "Ur1UlSFPTu6O" }, "source": [ "**Exercise 1.** Create a 3d array of shape (2, 2, 2), containing 8 values. Access individual elements and slices." ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "id": "v1ed4-vLUWXQ" }, "outputs": [], "source": [ "# Your code here" ] }, { "cell_type": "markdown", "metadata": { "id": "s_ksfCDJzyxI" }, "source": [ "**Exercise 2.** Rewrite the relu function (see Python section) using [np.maximum](https://numpy.org/doc/stable/reference/generated/numpy.maximum.html). Check that it works on both a single value and on an array of values." ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "id": "QtSTxH5Dz6f8" }, "outputs": [], "source": [ "def relu_numpy(x):\n", " return\n", "\n", "relu_numpy(np.array([1, -3, 2.5]))" ] }, { "cell_type": "markdown", "metadata": { "id": "wggUjpyRz7fb" }, "source": [ "**Exercise 3.** Rewrite the Euclidean norm of a vector (1d array) using NumPy (without for loop)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "id": "p5BLcHOD0Bhy" }, "outputs": [], "source": [ "def euclidean_norm_numpy(x):\n", " return\n", "\n", "my_vector = np.array([0.5, -1.2, 3.3, 4.5])\n", "euclidean_norm_numpy(my_vector)" ] }, { "cell_type": "markdown", "metadata": { "id": "01IteVJ60Il2" }, "source": [ "**Exercise 4.** Write a function that computes the Euclidean norms of a matrix (2d array) in a row-wise fashion. Hint: use the `axis` argument of [np.sum](https://numpy.org/doc/stable/reference/generated/numpy.sum.html)." ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "id": "at5lWRNM0SVG" }, "outputs": [], "source": [ "def euclidean_norm_2d(X):\n", " return\n", "\n", "my_matrix = np.array([[0.5, -1.2, 4.5],\n", " [-3.2, 1.9, 2.7]])\n", "# Should return an array of size 2.\n", "euclidean_norm_2d(my_matrix)" ] }, { "cell_type": "markdown", "metadata": { "id": "yd1ZoByo436x" }, "source": [ "**Exercise 5.** Compute the mean value of the features in the [iris dataset](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_iris.html). Hint: use the `axis` argument on [np.mean](https://numpy.org/doc/stable/reference/generated/numpy.mean.html)." ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "id": "fYFVobkP5JK6" }, "outputs": [], "source": [ "from sklearn.datasets import load_iris\n", "X, y = load_iris(return_X_y=True)\n", "\n", "# Result should be an array of size 4." ] }, { "cell_type": "markdown", "metadata": { "id": "1FDs9zX6mpoX" }, "source": [ "### Going further 💯" ] }, { "cell_type": "markdown", "metadata": { "id": "hFP61Iztmr9Q" }, "source": [ "* NumPy [reference](https://numpy.org/doc/stable/reference/)\n", "* SciPy [lectures](https://scipy-lectures.org/)\n", "* One-hour [tutorial](https://www.youtube.com/watch?v=QUT1VHiLmmI) on Youtube \n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "7Jt6T3kJ8I2T" }, "source": [ "## Matplotlib 📈" ] }, { "cell_type": "markdown", "metadata": { "id": "kQX8TiEOALkQ" }, "source": [ "### Basic plots" ] }, { "cell_type": "markdown", "metadata": { "id": "REYwc9Va8UTg" }, "source": [ "Matplotlib is a plotting library for Python." ] }, { "cell_type": "markdown", "metadata": { "id": "Eom7t-m6-Uzb" }, "source": [ "We start with a rudimentary plotting example." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 295 }, "id": "g21e5Ncm927z", "outputId": "2e95dff3-0bb0-4759-f675-d32c05eaaade" }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib import pyplot as plt\n", "\n", "x_values = np.linspace(-3, 3, 100)\n", "\n", "plt.figure()\n", "plt.plot(x_values, np.sin(x_values), label=\"Sinusoid\")\n", "plt.xlabel(\"x\")\n", "plt.ylabel(\"sin(x)\")\n", "plt.title(\"Matplotlib example\")\n", "plt.legend(loc=\"upper left\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "ltvlLwXF-eAH" }, "source": [ "We continue with a rudimentary scatter plot example. This example displays samples from the [iris dataset](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_iris.html) using the first two features. Colors indicate class membership (there are 3 classes)." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 268 }, "id": "sEzcJAmy-hbK", "outputId": "e71652fa-add5-40e9-ee69-46eaf36b7d5e" }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from sklearn.datasets import load_iris\n", "X, y = load_iris(return_X_y=True)\n", "\n", "X_class0 = X[y == 0]\n", "X_class1 = X[y == 1]\n", "X_class2 = X[y == 2]\n", "\n", "plt.figure()\n", "plt.scatter(X_class0[:, 0], X_class0[:, 1], label=\"Class 0\", color=\"C0\")\n", "plt.scatter(X_class1[:, 0], X_class1[:, 1], label=\"Class 1\", color=\"C1\")\n", "plt.scatter(X_class2[:, 0], X_class2[:, 1], label=\"Class 2\", color=\"C2\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "5vjln9qwAc3M" }, "source": [ "We see that samples belonging to class 0 can be linearly separated from the rest using only the first two features." ] }, { "cell_type": "markdown", "metadata": { "id": "uVWuIUs2AQ5a" }, "source": [ "### Exercise - plots ❗❗\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "1X6-g6zgCwJd" }, "source": [ "**Exercise 1.** Plot the relu and the [softplus](https://en.wikipedia.org/wiki/Rectifier_(neural_networks)#Softplus) functions on the same graph." ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "id": "Ob6HZUX0DJ8y" }, "outputs": [], "source": [ "# Your code here" ] }, { "cell_type": "markdown", "metadata": { "id": "vpRGfz0aDW3l" }, "source": [ "What is the main difference between the two functions?" ] }, { "cell_type": "markdown", "metadata": { "id": "JjDeIufRAYVL" }, "source": [ "**Exercise 2.** Repeat the same scatter plot but using the [digits dataset](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_digits.html) instead." ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "id": "-JU3TXCBBB0c" }, "outputs": [], "source": [ "from sklearn.datasets import load_digits\n", "X, y = load_digits(return_X_y=True)" ] }, { "cell_type": "markdown", "metadata": { "id": "w7wPWdmXBQA2" }, "source": [ "Are pixel values good features for classifying samples?" ] }, { "cell_type": "markdown", "metadata": { "id": "dYM-oV1jD3RV" }, "source": [ "### Going further 💯\n", "\n", "* Official [tutorial](https://matplotlib.org/tutorials/introductory/pyplot.html)\n", "* [Tutorial](https://www.youtube.com/watch?v=qErBw-R2Ybk) on Youtube" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.15" } }, "nbformat": 4, "nbformat_minor": 1 }