UNIVERSITE NORD-AMERICAINE PRIVEE
INSTITUT INTERNATIONAL DE TECHNOLOGIE
DEPARTEMENT INFORMATIQUE
© Guide pratique n°1 AU : 2021-2022
Matière Intelligence Artificielle Semestre : 2
Discipline 1ère année Génie Informatique
Enseignants Dr. Taoufik Ben Abdallah / Dr. Ali Ben Mrad
Nombre de pages : 9
Partie I : Calcul scientifique avec NumPy
Pour quelles raisons pourriez-vous vouloir vous intéresser à numpy (abréviation de numerical python) ?
D’abord, si vous désirez faire de la science des données ou de l’apprentissage automatique (Machine
Learning), numpy est d’une valeur inestimable. Elle fournit de multiples fonctions permettant notamment
de créer directement un tableau depuis un fichier ou au contraire de sauvegarder un tableau dans un fichier,
et manipuler des vecteurs, matrices et polynômes.
La bibliothèque numpy apporte la structure de données tableaux multidimensionnels (ndarray) à
Python. Ils sont comme les listes (et liste de listes) en Python, mais numpy permet de rendre les opérations
beaucoup plus efficaces, surtout sur les tableaux de large taille.
Contrairement aux listes en Python, les tableaux numpy ne peuvent contenir des éléments que d’un seul
type. Le type est automatiquement déduit au moment de la création du tableau, et a un impact sur les
opérations qui y seront appliquées. De plus, on peut spécifier le type des éléments d’un tableau
manuellement.
Dans cet atelier pratique, vous allez expérimenter quelques fonctions fournies par numpy utiles par la suite
par le traitement de données et le Machine Learning
Afin de lancer le notebook python, il suffit de se positionner dans le dossier de travail et de taper la
commande Jupyter Notebook. Par conséquent, une fenêtre se lancera dans le navigateur permettant ainsi
d’ouvrir l’application Jupyter. Créer un nouveau notebook Python et importer la bibliothèque numpy
dans une nouvelle cellule :
import numpy as np
Création des tableaux
a=[Link]([1, 2, 3]) # Créer un tableau ndarray de dimension 1 à partir d’une liste Python
print(type(a)) ; print("a=",a)
b=[Link]([[i for i in range(j,j+3)] for j in range(1,10,3)]) # Créer un tableau ndarray de dimension 2
(matrice) à partir d’une liste de liste Python
print("b=",b)
print([Link]) # [Link] représente un tuple indiquant la taille du tableau b pour chaque axe (ligne,
colonne)
c=[Link](0, 10, 2) # Créer un tableau ndarray de dimension 1 rempli d’une séquence linéaire
commençant à 0 et se terminant à 9 avec un pas de 2
print("c=",c)
d=[Link](0,2,5) # Créer un tableau ndarray de dimension 1 rempli d’une séquence de 5 valeurs,
espacées uniformément entre 0 et 2
print("d=",d)
print([Link], [Link], [Link], [Link]) # afficher le type d’éléments des tableaux a, b, c et d
1/9
# NB. Dans le module numpy, les entiers (long_scalars) sont normalement codés sur 4 octets (soit
32 bits) et les flottants sur 8 octets (soit 64 bits). Vous pouvez vérifier le type de données utilisé
dans un tableau avec l’attribut dtype
e=[Link](4) # Créer un tableau ndarray rempli d’une séquence de valeurs croissantes de 0 à 3
print("e=",e)
f=[Link](0, 10, 2) # Créer un tableau ndarray rempli d’une séquence linéaire commençant à 0
et se terminant à 9 avec un pas de 2
print("f=",f)
g=[Link](0, 2**63, 2**61)
print("g=",g)
print([Link])
# NB. Lorsque les entiers sont trop grands pour être représentés sur 4 octets, ils sont représentés
sur 8 octets (longlong_scalars), voire convertis en flottants (float64)
Propriétés des tableaux ndarray
a=[Link]([[1,5,7],[9,9,10]])
print("a=",a) ; print([Link]) ; print([Link])
print([Link]) # dimension
print([Link]) # Le nombre d’éléments du tableau
Conversion de type
a=[Link]([1,2,3,4.0]) # Comme les tableaux ne permettent pas le mélange de types, des
conversions automatiques se produisent. Les entiers sont convertis en float en raison de la
présence du float 4.0
print("a=",a)
b=[Link]([1,2,3.0, "hi"]) # Toutes les valeurs numériques sont converties en chaînes
print("b=",b)
c= [Link]([20, 12, 9])
print("c=",c, [Link])
d= [Link]([20, 12, 9], dtype="float32")
print("d=",d, [Link])
Modification de forme (shape)
a=[Link](10) ;
print("a=\n",a)
b= [Link](5,2) # ou bien [Link](a, (5,2)) Convertir un tableau unidimensionnel de taille 𝒏
(𝒏 = 𝒗𝟏 × 𝒗𝟐) en un tableau bidimensionnel de taille 𝒗𝟏 × 𝒗𝟐 ou de format 𝒗𝟐 × 𝒗𝟏
print("b=\n",b)
c= [Link](2,5) ; print("c=\n",c)
# d= [Link](2,3) # ?
#np. reshape(a,(2,6)) vs. [Link](a,(2,6)) #? # [Link]((2,6))
d=[Link]() # Déroule tous les axes et retourne un tableau avec ndim=1
print("d=\n",d, [Link], [Link])
Création des tableaux aléatoires
Le sous-module [Link] possède deux méthodes pour définir des tableaux de nombres au hasard :
random et randint
2/9
a=[Link]((3,4)) # Créer une matrice de taille 3 lignes × 4 colonnes de valeurs aléatoires
appartenant à [0,1]
print("a=",a)
b=[Link](2, 4, (3,3)) # [Link](2, 4,size=(3,3)) : Créer une matrice de taille 3
lignes × 3 colonnes de valeurs entières aléatoires appartenant à [2,4]
print("b=",b)
Création des tableaux constants
a=[Link]((2,2)) # Créer un tableau ndarray de taille 2 × 2 rempli par des zéros
print("a=\n",a, [Link])
b=[Link]((2,2)) # Créer un tableau ndarray de taille 2 × 2 rempli par des 1
print("b=\n",b, [Link])
c=[Link]((3,5), 5) # Créer un tableau ndarray de taille 3 × 5 contenant uniquement la valeur 5
print("c=\n",c)
d=[Link](3) # [Link](3) : Créer une matrice identité de taille 3 × 3
print("d=",d)
Indexation des tableaux (Slicing)
L’indexation des éléments d’un tableau T se fait par T[début:fin:pas]. Le début peut être omis si l’on veut
commencer au début de la liste (début=0). La fin peut être omise si l’on veut aller jusqu’au bout de la liste.
Le pas peut être aussi omis si le pas est de 1
a=[Link]([1,2,3,4])
print(a[2],a[:2],a[1:2],a[1:],a[1:4:2],a[::2],sep=" - ")
print(a[-1])# Accès au dernier élément
b=[Link]([[5,6,7,8], [9,10,11,12]]) ; print("b=\n",b)
print("b[:,0]=\n", b[:,0]) # Accès à la première colonne
print("b[1,:]=\n", b[1,:]) # Accès à la deuxième ligne
print("b[1,[0,2]]=\n", b[1,[0,2]]) # Accès à la ligne d’indice 1, et colonnes d’indices 0 et 2
print("b[:2, 1:3]=\n", b[:2,1:3]) # Accès aux lignes d’indices 0 et 1, et colonnes d’indices 1, 2
print("b[:2, :3]=\n", b[:2,:3])
print("b[::2, ::2]=\n",b[::2,::2])
print("Diagonale de b= \n",[Link](b)) # Renvoie un tableau unidimensionnel avec les éléments de
la diagonale de b
c=[Link]([[5,6,7], [9,10,11], [13,14,15]])
print("Diagonale de c= \n",[Link](c)) # Renvoie un tableau unidimensionnel avec les éléments de
la diagonale de c
Modification des éléments d’un tableau
Les tableaux numpy sont mutables
a=[Link]((3,3), dtype="int32") ; print("a=",a)
a[0,0] = 9 # Modifier la valeur de la ligne d’indice 0 et de la colonne d’indice 0 par 9
print("a=",a)
a[1,:] = [4,5,6] # Modifier les valeurs de chaque colonne de la ligne d’indice 1 respectivement par 4,
5 et 6
3/9
print("a=",a)
# a[1,:] = [2,2] ; print("a=",a) # ?
a[:,2] = [7,8,9] ; print("a=\n",a)
a[a%2==0]+= 1 ; print("a=\n",a)
Copie d’un tableau et de ses tranches
a = [Link](12).reshape(3,4)
print("a= \n",a,id(a),sep="\n")
b=[Link]() # Copie du tableau a
print("b= \n",b,id(b),sep="\n")
L1=b[1,:] # Référence
L2= b[1,:].copy() # Copie de la tranche b[1,:] du tableau b
print("L1={} - L2={}".format(L1,L2))
b[:,2] = [Link](3) ; print("b= \n",b)
print("L1={} - L2={}".format(L1,L2)) # Modification de b et de L1 mais pas de L2
NB. Pour supprimer le lien entre un tableau et l’une de ses tranches, il faut réaliser une
copie
Permutation de lignes et de colonnes
a=[Link](10,20).reshape(5,2) ; print("a= ",a)
a[1,:], a[2,:] = a[2,:], a[1,:] ; print("a=\n ",a)
a=[Link](10,20).reshape(5,2)
a[1,:], a[2,:] = a[2,:].copy(), a[1,:].copy() # Permutation de la ligne d’indice 1 avec celle d’indice 2
print("a=\n ",a)
a[:,0], a[:,1] = a[:,1].copy(),a[:,0].copy() # Permutation de la colonne d’indice 0 avec celle d’indice 1
print("a=\n ",a)
NB. La suppression de la référence par copie est nécessaire pour échanger deux lignes ou deux
colonnes d’un tableau bidimensionnel
# Autre méthode avec l’indexation avancé
# Indexation avancé : la ième ligne d’un tableau T correspond à T[[i],:]. NB. [i] est une copie de la ième
ligne de T et non plus référence sur T
b=[Link](10,20).reshape(5,2)
print("b=\n",b) ; print(b[[0],:])
b[[0],:], b[[2],:] = b[[2],:], b[[0],:] # Permutation de la ligne d’indice 0 avec celle d’indice 2
print("b=\n",b)
b[:,[0]], b[:,[1]] = b[:,[1]], b[:,[0]] # Permutation de la colonne d’indice 0 avec celle d’indice 1
print("b=\n",b)
Itérations des tableaux
a= [Link](1, 10,size=(3,4)) ; print("a=\n",a)
# Itération par ligne
print("Itération de a = ")
for l in a:
print(l) # l est un tableau contenant les éléments de la première ligne du tableau a
print(type(l))
print("Stop"); break
4/9
# Itération élément par élément
for i in [Link]:
print(i, end=" / ")
print(type(i))
Opérations sur les tableaux
Opérateurs arithmétiques
# Addition et multiplication par un scalaire
a=[Link](6) ; print("a=\n",a)
print("a+4=\n",a+4) # Chaque élément du tableau a est additionné par 4
print("a*2=\n",a*2) # Chaque élément du tableau a est multiplié par 2
b=[Link](6).reshape(2,3)
print("b=\n",b) ; print("b+4=\n",b+4)
# Addition et multiplication terme par terme
c=[Link](10,16).reshape(2,3)
print("c=\n",c) ; print("b+c=\n",b+c) ; print("a+a=\n",a+a)
# d=[Link](4); print("d+c=\n",d+c) # ?
print("b*c=\n",b*c) ; print("a*a=\n",a*a)
d=[Link](6).reshape(3,2)
# print("b*d=\n",b*d) # ?
# NB. L’addition ou la multiplication terme par terme est effectuée sur des tableaux de même
taille et de même format
Multiplication matricielle
a=[Link](2, 4,(3,2))
b=[Link](5, 10,(2,4))
print("a=\n",a)
print("[Link](a,b)=\n", [Link](a,b)) # Équivalent à [Link](b)
print("[Link](b)=\n", [Link](b))
# NB. Les formats de deux tableau T1 et T2 doivent être compatibles. Si T1 et T2 sont
bidimensionnels, leurs formats respectifs doivent être de la forme (n, p) et (p, q)
Transposition
a=[Link]([[1,3],[5,6]]) ; print("a=",a)
b=[Link]() # a.T : Transposer la matrice
print("b=",b) ; c=[Link]([1,3,8])
c=[Link]() ; print("c=",c)
# NB. Un tableau unidimensionnel est invariant par la méthode transpose, car ce genre de
tableau ne doit pas être considéré comme une ligne qui est changée en colonne par transposition
mais plutôt comme une liste
Quelques fonctions universelles de base
Les fonctions universelles (universal functions, ufunc) effectuent une opération élémentaire sur tous les
éléments d’un tableau
a=[Link](-3, 5,(3,3))
b=[Link](6, 10,(3,3))
print("a={}\n b={}\n".format(a,b))
print("[Link](a,b)=\n", [Link](a,b))
print("[Link](a,b)=\n", [Link](a,b))
print("[Link](a,b)=\n", [Link](a,b))
5/9
print("[Link](a,b)=", [Link](a,b), [Link](a,b).dtype, sep="\n")
c=[Link]([[2.5,-3],[4,4.8],[-2.2,1]])
print("[Link](c)=\n", [Link](c)) # Appliquer "valeur absolue" pour chaque élément du tableau
print("[Link](c)=\n", [Link](c)) # Arrondir respectivement à l’entier directement inférieur
print("[Link](c)=\n", [Link](c)) # Arrondir respectivement à l’entier directement supérieur
#[Link](c); [Link](c); [Link](c); np.log2(c); [Link](c); [Link](c); ...
Fonctions d’agrégation
a=[Link](1, 10,(4,4)) ; print("a=\n",a)
print("[Link](a)=\n", [Link](a)) # Calculer la somme de tous les éléments du tableau
print("[Link](a)=\n", [Link](a)) # Calculer la moyenne de tous les éléments du tableau
print("[Link](a)=\n", [Link](a)) # Calculer le maximum de tous les éléments du tableau
print("[Link](a)=\n", [Link](a)) # Calculer le minimum de tous les éléments du tableau
print("a[0,:]=\n",a[0,:])
print("[Link](a[0,:])=\n", [Link](a[0,:])) # Calculer le maximum de tous les éléments de la première
ligne du tableau
print("[Link](axis=0)=\n", [Link](axis=0)) # Tableau de maximum de chaque colonne (par ligne)
print("[Link](axis=1)=\n", [Link](axis=1)) # Tableau de maximum de chaque ligne (par colonne)
print("[Link](axis=0)=\n", [Link](axis=0))
print("[Link](axis=1)=\n", [Link](axis=1))
print("[Link](a)=\n", [Link](a)) # Équivalent à [Link]() # Déterminer la position du
plus grand élément du tableau
print("[Link](a)=\n", [Link](a)) # Équivalent à [Link]() # Déterminer la position du
plus petit élément du tableau
indC=[Link](axis=0).argmax(); # Déterminer l’indice de colonne qui contient le max du tableau
print("[Link](axis=0).argmax()=\n ",[Link](axis=0).argmax())
print("a[:,indC].argmax()=\n ",a[:,indC].argmax()) # Déterminer l’indice de ligne correspondant au
maximum de la colonne d’indice indC
print([Link](axis=1).argmax()) # Déterminer l’indice de ligne qui contient le max du tableau
# NB. Les fonctions d’agrégation de numpy sont plus performantes que celles de Python
lorsqu’elles s’appliquent à des tableaux de grande taille
Opérations sur des tableaux booléens
La création d’un tableau booléen peut être effectuer par la comparaison des éléments d’un tableau T à une
valeur scalaire v. Le tableau résultat est même format que T dont les éléments sont les booléens qui
résultent de la comparaison des éléments de T à v
a=[Link](6).reshape(3,2) ; print("a=\n",a)
b=a>3
print("b=\n", b)
c=~b # Tableau complémentaire de b obtenu en appliquant l’opérateur not à chaque élément de b
print("c=\n",c)
d=[Link]([[True,False],[True,True],[True,False]])
print("d=\n",d)
print("c+d=\n",c+d) # c+d=d+c est un tableau de même format que c ou d, obtenu en appliquant
l’opérateur "or" (disjonction inclusive) terme à terme
print("c*d=\n",c*d) # c*d=d*c est un tableau de même format que c ou d, obtenu en appliquant
l’opérateur "and" (conjonction) terme à terme
print("c^d=\n",c^d) # c^d=d^c est un tableau de même format que c ou d, obtenu en appliquant
l’opérateur "xor" (disjonction exclusive) terme à terme
6/9
Fusion des tableaux
a=[Link]([8,8,19]) ; a1=[Link]((1,3))
b=[Link](6).reshape(2,3)
c=[Link]((1,3))
d=[Link](6,10).reshape(2,2)
print("a=\n",a) ; print("b=\n",b) ; print("c=\n",c) ; print("d=\n",d)
print("a",type(a),[Link]) ; print("c",type(c),[Link]) ; print("a1",type(a1),[Link])
print("[Link]([a,[Link]([3,4,5])])=\n",[Link]([a,[Link]([3,4,5])])) # Joindre les
tableaux. NB. La jointure dépend des formes des tableaux
print("[Link]([a1,c])=\n",[Link]([a1,c]))
print("[Link]([a1,c])=\n",[Link]([a1,c])) # Effectue une pile verticale, c. à d. le tableau c est
ajouté en tant que nouvelles lignes du premier tableau a1
print("[Link]([a,c])=\n",[Link]([a,c]))
# print("[Link]([a,c])=\n",[Link]([a,c])) # ?
print("[Link]([b,d])=\n",[Link]([b,d])) # np.column_stack([b,d])) : Effectuer une pile
horizontale, c. à d. le tableau d est ajouté en tant que nouvelles colonnes du premier tableau b
NB. numpy utilise le concept d’empilement (stacking) pour fusionner les tableaux
Décomposition des tableaux
a=[Link](8).reshape(4,2)
print("a=\n",a)
decomp1=[Link](a,2) # Décompose le tableau a horizontalement en deux tableaux de même
largeur. Le résultat est une liste de tableaux ndarray
print("decomp1=\n",decomp1, type(decomp1))
# decomp2=[Link](a,3) # ?
decomp3=[Link](a,2)
print("decomp3=\n",decomp3, type(decomp3)) # Décompose le tableau a verticalement en deux
tableaux de même hauteur. Le résultat est une liste de tableaux ndarray
print("a[:2]=\n",a[:2])
print("a[2:3]=\n",a[2:3])
print("a[3:]=\n",a[3:])
decomp4= [Link](a,[2,3], axis=0) # Le tableau a est décomposé en trois tableaux : a[:2], a[2:3], et a[3:]
print("decomp4=\n",decomp4, type(decomp4))
b=a.T
print("b=\n",b)
print("b[:,:2]=\n",b[:,:2])
print("b[:,2:3]=\n",b[:,2:3])
print("b[:,3:]=\n",b[:,3:])
decomp5= [Link](b,[2,3], axis=1) # Le tableau b est décomposé en trois tableaux : b[:,:2], b[:,2:3],
et b[:,3:]
print("decomp5=\n",decomp5, type(decomp5))
Insertion des lignes et des colonnes
a=[Link]([[1,2],[3,1],[8,11]]) ; print("a=\n",a, [Link])
b=[Link]([[17,19]]) ; print("b=\n",b,[Link])
c=[Link](a,b) # Joindre les tableaux a et b en un tableau ndarray de dimension 1
7/9
print("c=\n",c,[Link])
d=[Link](a,b,axis=0) # Accoler le vecteur a en tant que nouvelle ligne de la matrice a
print("d=\n",d,[Link])
e=[Link](b,[Link]([[45]]),axis=1) # Accoler le vecteur [Link]([[45]]) en tant que nouvelle
colonne de la matrice b
print("e=\n",e,[Link])
f=[Link](a,e.T,axis=1) # Accoler le transposé du vecteur e en tant que nouvelle colonne de la
matrice a
print("f=\n",f,[Link])
g=[Link](a,1,b,axis=0) #Insertion de b en tant que nouvelle ligne (axis = 0) à la 1ère position
print("g=\n",g,[Link])
m= [Link](10).reshape(2,5)
p=m[:, :,[Link]]
k=[Link](11,21).reshape(2,5)
p=[Link](p,0,k,axis=2)
print("p=\n",p[:,:,1],[Link], [Link])
Suppression des lignes et des colonnes
a=[Link]([[1,2,4,9,10],[3,1,2,4,12],[8,11,17,22,1]]) ; print("a=\n",a, [Link])
b=[Link](a,1,axis=0) # Supprimer la ligne (axis=0) d’indice 1 de la matrice b
print("b=\n",b, [Link])
a=[Link]([[1,2,4,9,10],[3,1,2,4,12],[8,11,17,22,1]])
b=[Link](a,2,axis=1) # Supprimer la colonne (axis=1) d’indice 2 de la matrice b
print("b=\n",b, [Link])
a=[Link]([[1,2,4,9,10],[3,1,2,4,12],[8,11,17,22,1]])
b=[Link](a,[2,3],axis=1) # Supprimer la colonne (axis=1) d’indice 2 et 3 de la matrice b
print("b=\n",b, [Link])
Diffusion (Broadcasting)
Le Broadcasting permet à un opérateur ou à une fonction d’agir sur deux ou plusieurs tableaux même si
ces tableaux n’ont pas le même format. Il définit des règles selon lesquelles deux tableaux de
formats différents peuvent éventuellement s’apparier.
a. Deux tableaux de même dimesion (ndim) sont compatibles si, pour chaque axe, soit les tailles sont
égales, soit l’une d’elles est exactement égale à 1. (5, 3) et (1, 3) sont des formats broadcastable, (5, 3)
et (5, 1) également, mais (5, 3) et (3, 1) ne le sont pas
a=[Link](6).reshape(2,3) ; b=[Link](6,12).reshape(2,3)
print("a=\n",a,[Link],[Link])
print("b=\n",b,[Link],[Link])
c=a+b ; print("c=\n",c, [Link],[Link])
d=[Link](20,23).reshape(1,3)
print("d=\n",d,[Link],[Link])
e=a+d ; print("e=\n",e,[Link],[Link]) # d sera copier 2 fois (par ligne)
f=d.T ; print("f=\n",f,[Link],[Link])
# k=a+f; print("k=\n",k,[Link],[Link]) # ?
g=d+f; print("g=\n",g,[Link],[Link]) # f sera copier 3 fois (par colonne)
8/9
k= [Link](15).reshape(5,3,1)
print("[Link] [Link]=\n",[Link],[Link])
print("k[:,:,0]=\n",k[:,:,0])
m=[Link](50,62).reshape(1,3,4)
print("[Link] [Link]=\n",[Link],[Link])
print("m[:,:,0]=\n",m[:,:,0])
print("m[:,:,1]=\n",m[:,:,1])
n=k+m
print("[Link] [Link]=\n",[Link],[Link])
print("n[:,:,0]=\n",n[:,:,0])
print("n[:,:,1]=\n",n[:,:,1])
# NB. La taille selon chaque axe après broadcast est égale au maximum de toutes les tailles
d’entrée. [Exemples : (5, 3) + (5, 1) → (5,3) ; (5, 3, 1) + (1, 3, 4) → (5, 3, 4)]
b. Si un tableau a une dimension (ndim) inférieure à une autre, alors sa taille (shape) est précédée d’autant
de 1 que nécessaire pour atteindre la même dimension. (5, 3) × (3,) = (5, 3) [ (3,) est transformé à (1,3) , et
(1,3) sera copier 5 fois]
a=[Link](6).reshape(2,3) ; b=[Link]([10, 20, 30])
print("a=\n",a, [Link],[Link])
print("b=\n",b, [Link],[Link])
c=a+b ; print("c=\n",c, [Link],[Link])
d=a*b ; print("d=\n",d, [Link],[Link])
e=[Link]([10, 20]);
print("e=\n",e, [Link],[Link])
# f=a+e # ?
9/9