← Tous les corrigés

Q1passé le

Le sujet

Sujet du quiz (PDF)

Les questions à revoir sont listées sur votre page personnelle (lien reçu par mail), à côté de votre note.

Bilan de la classe

Copies
16
Moyenne
15
Médiane
16.5
Min – max
8 – 19
  • 8–101
  • 10–122
  • 12–142
  • 14–162
  • 16–184
  • 18–205

Séance 1 : NumPy, le tableau (ndarray, dtype, mémoire, reshape, indexation et slicing, vues vs copies, images). Clé de correction avec explications synthétiques. La lettre correspond à l’ordre des choix sur le sujet (A = 1er choix).

Clé de correction

Q Réponse Rappel Référence
1 B np.array(...) renvoie un numpy.ndarray S1 slide 8 « Pourquoi NumPy ? Le ndarray » · nb 1-02 § création d’un tableau multi-dimensionnel
2 A ndim = nombre de dimensions (3), size = nombre d’éléments (24) S1 slide 8 « Pourquoi NumPy ? » · nb 1-02 § taille, forme, dimension
3 C np.linspace(0, 1, 5) : bornes incluses, arange exclut la borne sup. S1 slides 10 « Les fabriques », 16 « 3 pièges » · nb 1-02 § valeurs régulièrement espacées
4 D np.arange(2, 20, 3) → 2, 5, 8, 11, 14, 17 : 6 éléments S1 slide 10 « Les fabriques » · nb 1-02 § valeurs régulièrement espacées
5 C nbytes = size × itemsize S1 slide 11 « Un buffer contigu » · nb 1-02 § type et taille mémoire
6 A image (H, W, 3) : shape[0] est la hauteur S1 slide 17 « TP images » · nb 1-06 § lecture d’une image en couleur
7 B canaux dans la 3e dimension : im[:, :, 1] est le vert S1 slides 14, 17 · nb 1-06 § canaux RGB de l’image
8 D tab[1::2] : départ 1, pas 2 S1 slide 13 « Indexer » · nb 1-05 § slicing en dimension 1
9 C vectorisation : la boucle est faite en C par numpy S1 slide 2 « Le cours en une phrase » · nb 1-04 § qu’est-ce que la vectorisation ?
10 A np.zeros((H, W, 3), dtype=np.uint8) S1 slide 10 « Les fabriques » · nb 1-02 § numpy.zeros / numpy.empty ; nb 1-06 § création d’une image
11 B canal alpha ; 255 = opaque, 0 = transparent S1 slide 17 « TP images » · nb 1-06 § transparence des images
12 D randint(0, 10) : borne sup. exclue ; size=(3, 4) S1 slide 10 « Les fabriques » · nb 1-02 § générateur de valeurs aléatoires entières
13 B dépassement int8 : 200 → 200 − 256 = −56 S1 slide 9 « Un type homogène » · nb 1-02 § numpy calcule à taille constante
14 C reshape renvoie une vue : a est modifié S1 slide 12 « reshape » · nb 1-03 § mémoire partagée
15 A -1 = dimension calculée : 24 / 4 = 6 S1 slide 12 « reshape » · nb : absent (1-03 ne montre pas -1)
16 D slice = vue (99), .copy() = copie indépendante (2) S1 slides 14–15 « Slicing / Vue ou copie » · nb 1-05 § les sous-tableaux sont des vues
17 A t[1, -1] = 7, t[-1][0] = 8 S1 slide 13 « Indexer » · nb 1-05 § accès à un tableau de dimension > 1
18 B astype renvoie une copie convertie ; t garde son dtype S1 slide 9 « Un type homogène » (inférence, astype) · nb 1-02 § modifier le type des éléments
19 C sous-bloc 2×2 mis à 7 : 4 × 7 = 28 S1 slide 14 « Slicing » · nb 1-05 § modification des sous-tableaux
20 D ::-1 sur l’axe des colonnes : miroir gauche-droite S1 slide 13 « Indexer » (pas) · nb 1-05 § rappel du slicing Python (l[::-1] sur liste)

Q1

Bonne réponse : B — numpy.ndarray
Pourquoi : np.array est une fonction qui construit un objet de type numpy.ndarray (n-dimensional array). numpy.array n’est pas un type, numpy.matrix est un vieux type à éviter, et le résultat n’est pas une liste Python.
Où dans le cours : slide 8 « Pourquoi NumPy ? Le ndarray » · 1-02-numpy-array § création d’un tableau multi-dimensionnel

Q2

Bonne réponse : A — 3 et 24
Pourquoi : ndim est le nombre de dimensions (len(tab.shape) = 3) et size le nombre total d’éléments (2 × 3 × 4 = 24). (2, 3, 4) est la valeur de shape, pas de ndim.
Où dans le cours : slide 8 « Pourquoi NumPy ? Le ndarray » · 1-02-numpy-array § taille, forme, dimension du tableau

Q3

Bonne réponse : C — np.linspace(0, 1, 5)
Pourquoi : linspace(a, b, n) donne n valeurs régulièrement espacées, bornes incluses : 0, 0.25, 0.5, 0.75, 1.

  • np.arange(0, 1, 5) : le 3e argument est le pas, d’où un seul élément [0].
  • np.arange(0, 1, 0.2) : 5 valeurs mais la borne 1 est exclue (0 … 0.8).
  • np.zeros(5) + 1/5 : cinq fois 0.2.
    Où dans le cours : slide 10 « Les fabriques » + slide 16 « Les 3 pièges du jour » (piège 3) · 1-02-numpy-array § tableau de valeurs régulièrement espacées

Q4

Bonne réponse : D — 6
Pourquoi : comme range, la borne 20 est exclue : 2, 5, 8, 11, 14, 17.
Où dans le cours : slide 10 « Les fabriques » · 1-02-numpy-array § tableau de valeurs régulièrement espacées (arange, borne exclue)

Q5

Bonne réponse : C — tab.nbytes
Pourquoi : nbytes = nombre d’octets total des données = size × itemsize. itemsize est la taille d’un élément, size le nombre d’éléments, memory n’existe pas.
Où dans le cours : slide 11 « Un buffer contigu, lu à travers une forme » · 1-02-numpy-array § type et taille mémoire des éléments du tableau (aussi 1-03-numpy-memory § organisation en mémoire)

Q6

Bonne réponse : A — im.shape[0]
Pourquoi : une image couleur est un tableau (hauteur, largeur, 3) ; la hauteur est donc shape[0] (533 pour les-mines.jpg), la largeur shape[1] (800). size donne le nombre total de valeurs, ndim vaut 3.
Où dans le cours : slide 17 « TP du jour : images (1/2) » · 1-06-imported-images1 § lecture d’une image en couleur (q. 6 : hauteur/largeur)

Q7

Bonne réponse : B — im[:, :, 1]
Pourquoi : les canaux R, G, B sont dans la dernière dimension ; on prend toutes les lignes, toutes les colonnes, et l’indice 1 du canal. im[1] ou im[1, :, :] est la 2e ligne de pixels, im[:, 1] la 2e colonne.
Où dans le cours : slide 14 « Slicing : on obtient une vue » (img[:, :, 0]) + slide 17 · 1-06-imported-images1 § canaux RGB de l’image

Q8

Bonne réponse : D — tab[1::2]
Pourquoi : start:stop:step avec start=1 et step=2. tab[::2] donne les indices pairs (0, 2, 4…), tab[2::1] tout à partir de 2, tab[1:2] un seul élément.
Où dans le cours : slide 13 « Indexer : une coordonnée par dimension » · 1-05-numpy-indexing-slicing § slicing en dimension 1

Q9

Bonne réponse : C — la boucle est faite par numpy, en C
Pourquoi : c’est la vectorisation (les ufunc) : code plus court, plus lisible et 10 à 100 fois plus rapide. Une boucle for fonctionne sur un ndarray mais elle est très lente ; la précision n’est pas en cause.
Où dans le cours : slide 2 « Le cours en une phrase » (pas de slide dédié) · 1-04-numpy-vectorization § qu’est-ce que la vectorisation ? + § les ufunc (partie planifiée en S1)

Q10

Bonne réponse : A — np.zeros((100, 200, 3), dtype=np.uint8)
Pourquoi : forme (hauteur, largeur, 3) + dtype=np.uint8 + zéros = noir.

  • (3, 100, 200) : les canaux ne sont pas dans la bonne dimension pour imshow.
  • np.empty ne garantit pas des zéros (mémoire non initialisée).
  • np.zeros(100, 200, 3) : la forme doit être un tuple, d’où un TypeError (200 est pris pour un dtype).
    Où dans le cours : slide 10 « Les fabriques » · 1-02-numpy-array § tableau de zéros numpy.zeros et § tableau non-initialisé numpy.empty ; 1-06-imported-images1 § création d’une image de couleur

Q11

Bonne réponse : B — la transparence (canal alpha) ; 255
Pourquoi : en RGBA le 4e canal est l’alpha : 0 = totalement transparent, 255 = opaque (en uint8). Ce n’est ni la luminosité ni un niveau de gris.
Où dans le cours : slide 17 « TP du jour : images (1/2) » (point 4) · 1-06-imported-images1 § transparence des images (rappel : 0 transparent → 255 opaque)

Q12

Bonne réponse : D — un tableau 3×4 d’entiers entre 0 et 9 inclus
Pourquoi : randint(low, high) exclut high ; size=(3, 4) donne la forme (c’est size et non shape pour les fonctions aléatoires). Les valeurs sont des entiers, pas des flottants.
Où dans le cours : slide 10 « Les fabriques » · 1-02-numpy-array § générateur de valeurs aléatoires entières

Q13

Bonne réponse : B — [-56 100]
Pourquoi : numpy calcule à taille constante : la somme de deux int8 reste un int8 (−128 … 127). 100 + 100 = 200 dépasse 127 et « fait le tour » : 200 − 256 = −56. Il n’y a ni promotion vers int64 ni erreur. 50 + 50 = 100 tient.
Où dans le cours : slide 9 « Un type homogène et de taille fixe » + slide 16 (piège 2) · 1-02-numpy-array § numpy calcule à taille constante (point d’arrêt 1)

Q14

Bonne réponse : C — 100, car b est une vue
Pourquoi : reshape ne copie pas les données : a et b partagent le même segment mémoire (seule l’indexation change). Modifier b[0, 0] modifie a[0]. Pour une copie indépendante il faudrait a.reshape(2, 3).copy().
Où dans le cours : slide 12 « reshape : une autre grille, le même buffer » · 1-03-numpy-memory § fonctions resize et reshape + § mémoire partagée

Q15

Bonne réponse : A — (4, 6)
Pourquoi : -1 demande à numpy de calculer la dimension manquante à partir du nombre d’éléments : 24 / 4 = 6. La forme obtenue ne contient jamais -1.
Où dans le cours : slide 12 « reshape : une autre grille, le même buffer » (reshape(3, -1)) · 1-03-numpy-memory § fonctions resize et reshape ; le -1 n’y figure pas, seulement dans le slide et le point d’arrêt 2

Q16

Bonne réponse : D — 99 2
Pourquoi : b = a[1:4] est une vue : quand a[2] passe à 99, b[1] (même case) vaut 99. c a été créé avec .copy() : c’est un tableau indépendant, c[1] vaut toujours 2.
Où dans le cours : slide 14 « Slicing : on obtient une vue » + slide 15 « Vue ou copie ? La règle » · 1-05-numpy-indexing-slicing § les sous-tableaux sont des vues, et non des copies (point d’arrêt 3)

Q17

Bonne réponse : A — (7, 8)
Pourquoi : t vaut [[0 1 2 3] [4 5 6 7] [8 9 10 11]]. t[1, -1] = ligne 1, dernière colonne = 7. t[-1] est la dernière ligne [8 9 10 11], son élément 0 vaut 8.
Où dans le cours : slide 13 « Indexer : une coordonnée par dimension » (indices négatifs, tab[i][j]) · 1-05-numpy-indexing-slicing § accès à un tableau de dimension 1 (indices négatifs) et § accès à un tableau de dimension > à 1

Q18

Bonne réponse : B — int64 float64
Pourquoi : np.array([1, 2, 3]) est inféré en entiers (int64). astype ne convertit pas sur place : il renvoie une copie indépendante au type demandé (float64), et t garde son dtype d’origine. float64 float64 supposerait une conversion en place, int64 int64 que astype n’a aucun effet sur des entiers « ronds », float64 int64 inverse les deux tableaux.
Où dans le cours : slide 9 « Un type homogène et de taille fixe » (inférence int64 ; « changer de type se demande explicitement : a.astype(np.float64) → une copie ») + slide 15 « Vue ou copie ? La règle » (a.astype(...) = copie) · 1-02-numpy-array § création d’un tableau avec le type des éléments et § modifier le type des éléments d’un tableau existant

Q19

Bonne réponse : C — 28
Pourquoi : t[1:, 1:] désigne les lignes 1 à 2 et les colonnes 1 à 2 : un bloc 2×2 (4 cases). L’affectation à travers la slice modifie t en place : somme = 4 × 7 = 28. (63 serait 9 cases, 21 3 cases, 14 2 cases.)
Où dans le cours : slide 14 « Slicing : on obtient une vue » (vec[::2] = 100) · 1-05-numpy-indexing-slicing § slicing en dimension > à 1 + § modification des sous-tableaux

Q20

Bonne réponse : D — l’image retournée gauche-droite (miroir horizontal)
Pourquoi : le premier : garde toutes les lignes, le ::-1 inverse l’ordre des colonnes (2e dimension) ; les canaux sont inchangés. Le miroir vertical serait im[::-1], le négatif 255 - im, la transposée im.transpose(1, 0, 2).
Où dans le cours : slide 13 « Indexer : une coordonnée par dimension » (tranche début:fin:pas) · 1-05-numpy-indexing-slicing § rappel du slicing Python (l[::-1], sur une liste) + § slicing en dimension > à 1 ; pas d’exemple ::-1 sur un ndarray/image en S1