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 pourimshow.np.emptyne garantit pas des zéros (mémoire non initialisée).np.zeros(100, 200, 3): la forme doit être un tuple, d’où unTypeError(200 est pris pour undtype).
Où dans le cours : slide 10 « Les fabriques » · 1-02-numpy-array § tableau de zérosnumpy.zeroset § 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
