Please wait, while our marmots are preparing the hot chocolate…
# @chunk: chunks/title.md # @chunk: chunks/objectives.md ## Informatique {var-cours-n} : Plan {#plan overview} - Logistique : rappels {tp} - Bibliothèque Numpy : premier contact {numpyintro} - Numpy : type, *shape*, agrégations {nptypeshapeagg} - Numpy : opérations élément par élément {npsimpleop} - Listes Python : tranches {listslicing} - Numpy : indices et tranches {npslicing} - Bibliothèque Matplotlib : premier contact {matplotlibintro} # @copy:#plan: %+class:inred: .tp ## Rendus de TP {libyli} - Typiquement 2 rendus - premier rendu en fin de séance - second rendu libre, avant le lundi mardi suivant 5h00 (matin) - Comment rendre - créez un fichier .zip - aller sur claroline connect - aller dans ressource « Rendu TP... » - envoyez votre fichier zip - (ne pas supprimer l'ancien s'il y en a déjà un) - Que rendre ? - fichier zip avec le code python, le compte rendu, etc (voir énoncé de TP) - bien penser à vos noms (les 2 pour un binôme) dans le compte rendu - ⚠ fichiers absents, nom manquant, ... ⇒ comme si pas rendu - NB: si le « rendu TP... » n'existe pas encore, me le dire - RAPPEL: examen de TP personnel (pas de binôme) ## Points importants sur le TP3 {libyli} - Avoir compris le calcul flottant - python ne peux pas représenter tous les nombres réels - certains nombres sont donc arrondis (type float) - il est donc inadapté de comparer des nombres avec `==` - Avoir bien compris `assert`, par exemple `assert «expr»` - instruction python qui vérifie que `«expr»` est vraie - génère une erreur si `«expr»` est fausse - (NB: toute erreur interrompt le programme) - Avoir pris connaissance de `numpy.testing.assert_allclose` - (renommé `assert_egal` dans le TP3) - fonction qui reçoit 2 paramètres - vérifie que ces deux paramètres sont (à peu près) égaux - gère les nombres flottant presque égaux - gère les listes et tableau numpy - ⚠ L'examen pratique utilisera `assert` etc. # @copy:#plan: %+class:inred: .numpyintro ## Numpy {libyli} - Motivation - `les_carrés`, `les_logs`, ... - `liste_zeros2d`, `grille`, ... - simplifié grâce aux « listes en compréhension » ⇒ peut mieux faire - \+ performances (vitesse de calcul) - Bibliothèque Numpy (module `numpy`) - structure de données pour des tableaux à 1, 2, n dimensions - simplification des calculs - fonctions utilitaire pour les opérations classiques - bases de nombreuses autres bibliothèques ## Numpy, ex. : création de tableaux de 0 {libyli} - Exemple (atypique, préférer la version d'en bas) ```python import numpy a = numpy.zeros(6) # "vecteur" avec 6 zéros print(a) b = numpy.zeros([5, 10]) # tableau de 5 lignes et 10 colonnes print(b) {slide} ``` - Version typique (`np` et utilisation de « tuple » (n-uplet)) ```python import numpy as np a = np.zeros(6) print(a) b = np.zeros((5, 10)) print(b) {slide} ``` - NB: `(5, 10)` est un **n-uplet (ou *tuple*)** qui se comporte comme la liste `[5, 10]` mais n'est pas modifiable (erreur si on essaie de changer une valeur) ## Numpy : quelques fonctions de création - `np.zeros(n)` - `np.zeros(shape)` (*shape* ⇔ forme ⇔ dimensions du tableau) - et `np.one(...)` - `np.arange(n)` - `np.arange(a, b)` - `np.arange(a, b, s)` - `np.eye(n)` - `np.eye(n1, n2)` - `np.random.random(n)` - `np.random.random(shape)` - `np.random.uniform(a, b, shape)` - `np.random.normal(moyenne, ecart_type, shape)` - ... ## Numpy : opérations {libyli} - La plupart des opération (`+`, `-`, `*`, ...) sont effectuée élément par élément - entre deux tableaux numpy `a + b` - entre un tableaux et un nombre `a + 10` (ajoute 10 à chaque élément de `a`) - La plupart des fonctions de `math` ont un équivalent dans numpy - ex : `np.log(a)` - Numpy propose des fonction d'agrégation - ex : `np.sum(a)`, `np.mean(a)`, `np.median(a)`, etc. ```python import numpy as np a = np.random.uniform(0.5, 1, (7, 4)) b = np.random.uniform(10, 20, (7, 4)) print(a + b) print(a + 10) print(a**b) print(np.sum(a)) print(np.sum(a, axis=0)) # plus tard... {slide} ``` # @copy:#plan: %+class:inred: .nptypeshapeagg # @chunk: chunks/q/np-access-1.md # @chunk: chunks/q/np-access-2.md ## Numpy : création et *shape* (forme, dimensions) {libyli} ```python import numpy as np a = np.ones((3, 8)) b = np.arange(0, 100, 5) c = np.arange(0.5, 100, 5) d = np.array([10, 15, 3.14, 2.7, 9.81]) {slide} ``` - Tableau numpy : type `ndarray` et type des éléments - `ndarray` tableau à n dimensions - types numériques python : int64, float64, bool, ... ```python print( type(a), type(b), type(c) ) # numpy.ndarray (les trois) print( a.dtype, b.dtype, c.dtype ) # float64 int64 float64 {slide} ``` - *shape* ⇔ forme ⇔ dimensions de tableau numpy ```python print(a.shape) # (3,8) 2-uplet (paire) avec 3 et 8 print(b.shape) # (20,) 1-uplet contenant la valeur 20 print(c.shape) # (20,) {slide} ``` - Indice multiples (autant que de dimensions) ```python print(a[0, 0]) print(b[0]) a[1, 1] = a[2, 2] + 999 {slide} ``` # @chunk: chunks/q/np-shape-1.md # @chunk: chunks/q/np-shape-2.md ## Numpy : *reshape* et données partagées et *copy* {libyli} - Changement de forme avec `.reshape(shape)` ```python a = np.array([1, 2, 3, 10, 20, 30]) b = a.reshape((2, 3)) # réorganiser en 2 lignes de 3 el. # équivalent, calcul auto. de la dimension manquante b = a.reshape((2, -1)) b = a.reshape((-1, 3)) {dense slide} ``` - ⚠️ Les tableaux partagent leurs données (idem pour les listes) ```python print(a[0]) # 1 b[0,0] = 3.14 print(a[0]) # 3.14 l = [1, 2 ,3] # idem en numpy sans reshape ou avec listes # idem si : l = np.array([1, 2, 3]) v = l v[0] = 3.14 print(l[0]) # 3.14 {dense slide} ``` - Copier un tableau avec `.copy()` ```python a[0] = 1 c = a.copy() c[0] = 3.14 print(a[0]) # 1 {dense slide} ``` ## Numpy : fonctions d'agrégations {libyli} ```python a = np.random.uniform(0.95, 1.05, (20, 50)) print(a.shape) # (20, 50) print(a.size) # 1000 {slide} ``` ```python print(np.sum(a)) # ≈ 1000 {slide} ``` ```python print(np.mean(a)) # ≈ 1 print(np.var(a)) # ≈ 0.0008333 (0.1² / 12) print(np.std(a)) # = np.var(a) ** 0.5 {slide} ``` ```python print(np.min(a)) # ≳ 0.95 print(np.max(a)) # ≲ 1.05 {slide} ``` - Indice du min/max ```python b = np.array([[10, 20, 30], [60, 50, 40]]) print(np.argmin(b)) # 0 bligne = b.reshape((-1,)) print(np.argmax(bligne)) # 3 print(np.argmax(b)) # 3 (comme si en ligne) print(np.unravel_index(np.argmax(b), b.shape)) # (1, 0) {slide} ``` # @copy:#plan: %+class:inred: .npsimpleop ## Opérations élément par élément {libyli} - Créons deux tableaux de même dimensions ```python a = np.arange(0, 1000, 100).reshape((2, 5)) b = np.arange(0, 10).reshape((2, 5)) assert_allclose(a, np.array([[ 0, 100, 200, 300, 400], [500, 600, 700, 800, 900]])) assert_allclose(b, np.array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9]])) {slide} ``` - Opérations éléments par élément ```python c = a + b assert_allclose(c, np.array([[ 0, 101, 202, 303, 404], [505, 606, 707, 808, 909]])) d = a * b assert_allclose(d, np.array([[ 0, 100, 400, 900,1600], [2500,3600,4900,6400,8100]])) {slide} ``` ```python print(a / b) # [[ nan 100. 100. 100. 100.] # [ 100. 100. 100. 100. 100.]] # nan : « not a number » (valeur spéciale, « pas un nombre ») {slide} ``` ## Opérations entre un tableau et un nombre {libyli} - Créons un tableaux ```python a = np.arange(0, 1000, 100).reshape((2, 5)) assert_allclose(a, np.array([[ 0, 100, 200, 300, 400], [500, 600, 700, 800, 900]])) {slide dense} ``` - Opérations avec un nombre ```python print(a + 1) # ou 1 + a # [[ 1 101 201 301 401] # [501 601 701 801 901]] print(a / 100) # ou a*0.01 ou 0.01*a # [[ 0. 1. 2. 3. 4.] # [ 5. 6. 7. 8. 9.]] print(a**2) # [[ 0 10000 40000 90000 160000] # [250000 360000 490000 640000 810000]] print(100 / a) # [[ inf 1. 0.5 0.3333 0.25 ] # [ 0.2 0.1667 0.14285714 0.125 0.1111]] # # inf : « infinity » (infini) {slide} ``` ## Fonctions mathématiques sur chaque élément {libyli} - Créons un tableaux ```python a = np.arange(0, 600, 100).reshape((2, 3)) assert_allclose(a, np.array([[ 0, 100, 200], [300, 400, 500]])) {dense slide} ``` - Fonctions mathématiques du module `numpy` ```python print(np.sin(a)) # [[ 0. -0.50636564 -0.8732973 ] # [-0.99975584 -0.85091936 -0.46777181]] print(np.cos(np.radians(a))) # [[ 1. -0.17364818 -0.93969262] # [ 0.5 0.76604444 -0.76604444]] print(np.log(a)) # [[ -inf 4.60517019 5.29831737] # [ 5.70378247 5.99146455 6.2146081 ]] print(np.exp(a)) # [[ 1.00000000e+000 2.68811714e+043 7.22597377e+086] # [ 1.94242640e+130 5.22146969e+173 1.40359222e+217]] print(np.clip(a, 150, 350)) # [[150 150 200] # [300 350 350]] ... # https://docs.scipy.org/doc/numpy/reference/routines.math.html # (^ pas que des opération élément par élément) {dense slide} ``` # @copy:#plan: %+class:inred: .listslicing ## Tranches de listes Python {libyli} - Rappel : accès à un élément d'une liste `la_liste[l_indice]` ```python a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] print(a[3]) # 30 {slide} ``` - Extraction d'une sous partie de liste ```python b = a[3:6] print(b) # [30, 40, 50] # avec un pas de 2 c = a[3:6:2] print(c) # [30, 50] {slide} ``` - Équivalent à ```python b = [a[i] for i in range(3, 6)] c = [a[i] for i in range(3, 6, 2)] # rappel : équivalent à c = [] for in range(3, 6, 2): c.append(a[i]) {slide} ``` ## Tranches en Python : raccourcis {libyli} - Omission des indices {anim-continue} ```python a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] {slide} ``` - Début et fin automatique ```python print(a[:3]) # [0, 10, 20] print(a[5:]) # [50, 60, 70, 80, 90] {slide} ``` - Avec un pas ```python print(a[:5:2]) # [0, 20, 40] print(a[5::2]) # [50, 70, 90] # et que le pas print(a[::3]) # [0, 30, 60, 90] {slide} ``` - Astuces ```python print(a[:]) # une copie de a # pas négatif print(a[::-1]) # [90, 80, 70, 60, 50, 40, 30, 20, 10, 0] print(a[::-3]) # [90, 60, 30, 0] {slide} ``` ## Indices et tranches Python : indices négatifs {libyli} ```python a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] {slide} ``` - Indices à partir de la fin ```python print(a[-1]) # 90 print(a[len(a)-1]) # 90 print(a[-3]) # 70 print(a[len(a)-3]) # 70 {slide} ``` - Marche aussi en tranches ```python print(a[1:-1]) # 10 ... 80 print(a[1:len(a)-1]) # 10 ... 80 print(a[:-3]) # 0 ... 60 {slide} ``` # @copy:#plan: %+class:inred: .npslicing ## Numpy : indices et tranches - Autant d'indices que de dimensions - Pour chaque dimension, tout marche comme avec les liste - indices - indices négatif - tranches - valeurs par défaut - indices négatifs - pas - pas négatif # Re: Illustration de Numpy : $\pi$ # @copy:#plan: %+class:inred: .matplotlibintro ## Matplotlib {libyli} - Motivation - tracer des graphes (courbes, nuages de points, histogrammes, etc) - gérer automatiquement l'affichage des axes, titres, graduations, etc. - permettre éventuellement l'interaction l'utilisateur (zoom, etc.) - permettre éventuellement de sauver des fichiers (jpg, pdf, etc.) - Bibliothèque Matplotlib (module `matplotlib`) - généralement `from matplotlib import pyplot as plt` - tracé de différents types de graphes - gestion des sous graphes - http://matplotlib.org/ - http://matplotlib.org/gallery.html ## Matplotlib : exemple ```python from matplotlib import pyplot as plt x = [1, 2, 3, 9, 10] y = [ e**3 for e in x ] z = [ (10+e)**2 for e in x ] plt.plot(x, y, label="courbe 1") plt.plot(x, z, label="courbe 2") plt.legend() plt.savefig('courbes.pdf') plt.show() ``` # Illustration de Numpy + Matplotlib : affichage des pas (quand on marche) - {comment} - np.genfromtxt(..., separator=',') - cf prep/steps # OK {no-print}

/ will be replaced by the authorwill be replaced by the title