{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "TyD2gu6xTg3B"
},
"source": [
"# 1. Introduction to Python 🐍\n",
"\n",
"
"
]
},
{
"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
}