Numpy (Numerical Python): Les bases de la constriction

Si vous avez déjà des notions en Python, vous connaissez certainement les objets tels que les listes, les tuples, les dictionnaires …Toutefois, ces objets sont d’usage général et manquent de maturité scientifiques et par dessus tout font trop recours aux boucles qui, comme nous le savons, sont synonymes de lourdeur d’exécution. C’est pour cette raison que pour les calculs numériques, l’analyses des données, …Python dispose de la librairie numpy qui permet la création et la manipulation des matrices.

Les matrices sont les objets mathématiques centraux de l’algèbre linéaire mais aussi, la structures de données la plus efficace pour effectuer des calculs scientifiques sur ordinateur. Par ce que, pour tout data Scientiste ou Analyste quant qui se respecte, numpy (et plus encore Scipy, matplotlib) et plus spécifiquement son objet ndarray est très indispensable, nous consacrerons ce tutoriel, à la manipulation de cet objet.

Importation de la librairie numpy et efficience d’un objet ndarray

Il existe différente manière d’importer une librairie, nous pour cet article nous chargerons numpy de la façon suivante : import numpy as np . En suite, nous allons faire une petite comparaison entre une liste créer avec la fonction arange() de numpy et une liste range() standards de python. Pourquoi spécialement ces deux fonctions ? Par ce qu’elles sont sensées générer des séquences/séries de chiffres. Nous allons comparer leur performance avec la librairie timeit.

Comme nous pouvons l’observer,  sommer une liste standard de 1000 éléments ( obtenu avec range()), nécessite 8 fois plus de temps qu’avec un objet ndarray (obtenu avec arange()). Ces performances sont à relativiser en fonction du système utilisé.

Création et caractéristiques d’objets ndarray

Un objet de type  ndarray est un tableau multidimensionnel (d’où le nd = n-dimension) prenant en charge des données de type homogène, c’est à dire que les données doivent être de même type integer, float, …etc. Structurellement, c’est un objet constitué des données et de métadonnées (informations sur les données). Ces derrières portent sur les dimensions, la taille et le type de données notamment. Pour créer un objet de type ndarray, on utilise la fonction array(), qui grâce à l’argument dtype permet de spécifier le type des données :

Nous venons de créer une matrice donc un tableau à deux dimensions de type implicite float,donc les caractéristiques essentielles restent les dimensions des lignes et colonnes qui nous sont renvoyées sous forme de tuple (lignes, colonnes).

Quelques matrices remarquables

Nous avons vu qu’on pouvais créer des matrices ou de façon plus général, des tableaux multidimensionnels avec la fonction array(). Mais en algèbre linéaire, nous aurons besoins de quelques matrices très pratiques pour opérer des calculs comme des matrices unitaires, diagonales, des séquences ou encore des matrices aléatoires qui s’avèrent très utiles en simulation numérique :

Nous avons jusqu’ici créé des tableaux de dimension inférieure ou égale à 2 car très communs. Noter qu’avec la fonction array(), nous pouvons créer des tableaux de N dimension d’où le nom de l’objet ndarray. Par exemple, l’objet x ci-dessous est un tableau de 4 dimensions :

Manipulation des ndarray

  • Indexation et extraction d’éléments ou de sous-ensembles

L’indexation d’élément d’une matrice ou d’un ndarray en général, se fait entre les crochets []. Et selon que l’on veut sélectionner des éléments du début à la fin ou de la fin au début, on utilise un chiffre positif ou négatif, dans le cas où l’indexation est faite avec les chiffres(on peut faire une indexation booléenne). Aussi, l’indexation inter-dimension est séparée par une virgule en plus clair,  si x est une matrice alors pour indexer l’élément situé à l’intersection de la 2ème ligne et de la 3ème colonne, on écrira : x[2,3]. Ici nous ne travaillerons que l’indexation d’objet de 1D et 2D. Si besoin la logique peut être généralisée aux dimensions supérieurs.

  • Opération de transformation

La fonction copy() : on pourrait s’interroger sur le bien fondé d’une telle fonction sachant qu’il suffirait peut être d’affecter un objet à un nouvel objet qui en contiendrait une réplique exacte. Il faut savoir en effet que la simple affectation d’un objet existant à un nouvel objet, crée seulement une nouvelle référence vers le même objet, et non un nouvel objet.  Par exemple, observons de plus près le résultat des instructions ci-dessous :

On voit bien que les deux variables pointent vers un même objet( ils ont la même adresse mémoire) et le résultat obtenu ou la dépendance entre ces deux variables n’est pas vraiment ce que nous recherchons. Ainsi, pour faire une vraie copie, indépendante, on utilise copy().

La fonction reshape() : cette fonction permet notamment de modifier l’attribut shape, que nous avons vu plus haut et donc de changer la dimension d’un objet.

Nous pourrions aboutir aux mêmes transformations en agissant sur l’attribut shape, comme-ceci : X.shape = (4,5)

Les fonctions ravel() et flatten() : Ces fonctions transforment tous les objets de dimensions supérieurs à 1 en des objets de 1D. Mais alors pourquoi 2 fonctions ? Par ce que l’une c’est-à-dire ravel() renvoie seulement une référence à l’objet de départ alors que l’autre c’est-à-dire flatten() crée un objet indépendant (comme avec la fonction copy() ce que l’on a vu ci-dessus) :

La fonction transpose() : La transposition est une opération courante en algèbre linaire, très pratique sur les matrices notamment. structurellement parlant, il s’agit de faire une rotation de la matrice par rapport à sa diagonale.

Opérations mathématiques et statistiques :

  • Les opérations et fonctions mathématiques générales

Avec les objets ndarray, les opérations basiques telles que l’addition, la soustractions, la multiplication et la division sont possibles et mieux encore numpy propose des fonctions pour ces opérations. Par ailleurs, numpy offre également la possibilité d’utiliser des fonctions mathématiques habituelles telles que , sin(), cos(), exp(), log()…Ces fonctions ont été baptisées “universal functions” ( ufunc). Voici quelques utilisations de ces fonctions :

  • Quelques fonctions statistiques

Nous pouvons opérer de simples calculs statistiques tels que la somme, la moyenne, la médiane, la variance, l’écart-type…. Il faut savoir que pour toutes ces fonctions énumérées ci-dessous, sum(), mean(), max(),…, on a la l’argument axis, qui lorsqu’il est égal à 0, effectue l’opération pour chaque ligne et pour chaque colonne, si axis = 1 .

Si l’on s’y connaît un peu en R, on aurait remarqué la fameuse fonction summary(), qui permet de faire d’afficher pour chaque colonne d’un objet, le minimum et le maximum, les trois quartiles et la moyenne. Pour ceux qui ont un faible pour cette fameuse fonction en voici une réplique :

Toutefois, l’on peut faire appel à la fonction describe(), de la célébrissime librairie pandas. Il faudrait toutefois, penser à convertir l’objet ndarray en DataFrame ou autres types d’objets de cette librairie.

  • Quelques fonctions pratiques de l’Algèbre linéaire

Nous pouvons réaliser des opérations d’algèbre linéaire, comme le produit matriciel, la détermination du déterminant et le calcul de l’inverse d’une matrice et la décomposition de matrice. numpy pour se faire, dispose d’un sous-module linalg(linear algeber, en toutes lettres). Voyons ce que ce module nous propose comme fonctions :

On peut maintenant être tentée d’appliquer quelques fonctions à un vieux type d’exercice qui consiste à résoudre des systèmes d’équations à plusieurs inconnues celui ci-dessous :

    \[ \begin{cases}-2x+y-z+5w-2v=11\\ x+3y+2z-3w+2v=31\\-x+4y+8z-7w+5v=64\\4x-2y+5z+3w+v =76\\5x+7y-3z+3w+2v=88 \end{cases} \]

le système donné, nous devons le réécrire sous forme matricielle tel que  Ax=b où :

 

Like