jupyter | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import numpy as np
Le concept central de numpy
est l'array
On peut créer un array
de plusieurs manières. Pour créer un array
à partir d'une liste, il suffit d'utiliser la méthode array
:
np.array([1,2,5])
np.array([["a","z","e"],["r","t"],["y"]])
Il existe aussi des méthodes pratiques pour créer des array:
- séquences logiques :
np.arange
(séquence linéaire) ounp.linspace
- séquences ordonnées: fonctions de génération de nombres aléatoires:
np.rand.uniform
,np.rand.normal
, etc. - array rempli de zéros, de 1 ou d'un nombre désiré :
np.zeros
,np.ones
ounp.full
- tableau sous forme de matrice identité:
np.eye
np.arange(0,10)
np.arange(0,10,3)
np.linspace(0, 1, 5)
np.zeros(10, dtype=int)
np.ones((3, 5), dtype=float)
np.full((3, 5), 3.14)
np.eye(3)
Exercice : Générer:
-
$X$ une variable aléatoire, 1000 répétitions d'une loi$U(0,1)$ -
$Y$ une variable aléatoire, 1000 répétitions d'une loi normale de moyenne nulle et de variance égale à 2 - Vérifier la variance de
$Y$ avecnp.var
X = np.random.uniform(0,1,1000)
Y = np.random.normal(0,np.sqrt(2),1000)
np.var(Y)
Il existe
np.linspace(0, 1, 5)
# Un tableau de longueur 10, rempli d'entiers qui valent 0
np.zeros(10, dtype=int)
# Un tableau de taille 3x5 rempli de nombres à virgule flottante de valeur 1
np.ones((3, 5), dtype=float)
# Un tableau 3x5 rempli de 3,14
np.full((3, 5), 3.14)
La logique générale de l'indexation d'un array unidimensionnel est la suivante:
x[start:stop:step]
Pour sélectionner uniquement un éléments, on fera ainsi:
x = np.arange(10)
x[2]
En l'occurrence, on sélectionne le K$^{eme}$ élément en utilisant
x[K-1]
Exercice
- Sélectionner les éléments 0,3,5
- Sélectionner les éléments pairs
- Sélectionner tous les éléments sauf le premier
- Sélectionner les 5 premiers éléments
Correction
x[[0,3,5]]
x[::2]
x[-0]
x[:5]
# x2[0,:] # La première ligne
On peut également sélectionner des données à partir de conditions logiques (opération qu'on appelle un boolean mask), ce qui sera pratique lorsqu'il sera nécessaire d'effectuer des opérations de filtre sur les données (pandas
reprend cette logique).
Pour des opérations de comparaison simples, les comparateurs logiques peuvent être suffisants:
x = np.arange(10)
x2 = np.array([[-1,1,-2],[-3,2,0]])
x==2
x2<0
Néanmoins, numpy
propose un certain nombre de fonctions logiques très pratiques:
- count_nonzero
- is_nan
- any ; all ; notamment avex
axis = 0
Exercice
Soit
x = np.random.normal(0, size=(3, 4))
un array multidimensionnel et
y = np.array([np.nan, 0, 1])
- Utiliser
count_nonzero
sury
- Utiliser
is_nan
sury
et compter le nombre de valeurs non NaN - Vérifier que
x
comporte au moins une valeur positive dans son ensemble, dans chaque array et en
x = np.random.normal(0, size=(3, 4))
y = np.array([np.nan, 0, 1])
x
y
np.count_nonzero(y)
np.isnan(y)
np.any(x>0)
np.any(x>0, axis = 0)
Pour sélectionner les observations relatives à la condition logique, il suffit d'utiliser la logique de slicing de numpy
qui fonctionne avec les conditions logiques
Exercice
Soit
x = np.random.normal(size=10000)
- Ne conserver que les valeurs dont la valeur absolue est supérieure à 1.96
- Compter le nombre de valeurs supérieures à 1.96 en valeur absolue et leur proportion dans l'ensemble
- Sommer les valeurs absolues de toutes les observations supérieures (en valeur absolue) à 1.96 et rapportez les à la somme des valeurs de
x
(en valeur absolue)
x = np.random.normal(size=10000)
x2 = x[np.abs(x)>=1.96]
x2.size
x2.size/x.size
np.sum(np.abs(x2))/np.sum(np.abs(x))
Pour ordonner un array, on utilise np.sort
x = np.array([7, 2, 3, 1, 6, 5, 4])
np.sort(x)
Si on désire faire un ré-ordonnement partiel pour trouver les k valeurs les plus petites d'un array
sans les ordonner, on utilise partition
:
np.partition(x, 3)
## Broadcasting
Le broadcasting désigne un ensemble de règles pour appliquer une opération qui normalement ne s'applique que sur une seule valeur à l'ensemble des membres d'un tableau Numpy.
Le broadcasting nous permet d'appliquer ces opérations sur des tableaux de dimensions différentes.
a = np.array([0, 1, 2])
b = np.array([5, 5, 5])
a + b
a + 5
L'idée de cet exercice vient de là
- Utiliser
import random as rand
X = np.random.random((10, 2))
%matplotlib inline
import matplotlib.pyplot as plt
plt.scatter(X[:, 0], X[:, 1], s=100)
dist_sq = np.sum((X[:, np.newaxis, :] - X[np.newaxis, :, :]) ** 2, axis=-1)
dist_sq
This operation has a lot packed into it, and it might be a bit confusing if you're unfamiliar with NumPy's broadcasting rules. When you come across code like this, it can be useful to break it down into its component steps:
# for each pair of points, compute differences in their coordinates
differences = X[:, np.newaxis, :] - X[np.newaxis, :, :]
differences.shape
# square the coordinate differences
sq_differences = differences ** 2
sq_differences.shape
# sum the coordinate differences to get the squared distance
dist_sq = sq_differences.sum(-1)
dist_sq.shape
Just to double-check what we are doing, we should see that the diagonal of this matrix (i.e., the set of distances between each point and itself) is all zero:
dist_sq.diagonal()
It checks out! With the pairwise square-distances converted, we can now use np.argsort to sort along each row. The leftmost columns will then give the indices of the nearest neighbors:
nearest = np.argsort(dist_sq, axis=1)
print(nearest)
Notice that the first column gives the numbers 0 through 9 in order: this is due to the fact that each point's closest neighbor is itself, as we would expect.
By using a full sort here, we've actually done more work than we need to in this case. If we're simply interested in the nearest k neighbors, all we need is to partition each row so that the smallest k+1
squared distances come first, with larger distances filling the remaining positions of the array. We can do this with the np.argpartition function:
K = 2 nearest_partition = np.argpartition(dist_sq, K + 1, axis=1)
Finally, I'll note that when doing very large nearest neighbor searches, there are tree-based and/or approximate algorithms that can scale as O[NlogN] or better rather than the O[N2] of the brute-force algorithm. One example of this is the KD-Tree, implemented in Scikit-learn.
Suite exercice: * faire une fonction dont argument est array et k * faire quelques tests unitaires: diag 0, premier element matrice est élément lui-même, dimension sortie
- Pour restructurer un
array
, c'est-à-dire changer ses dimensions, le plus simple est d'utiliser la méthodereshape
. Par exemple, pour
np.reshape np.concatenate np.split, np.hsplit, and np.vsplit