Académique Documents
Professionnel Documents
Culture Documents
P R É C É D E N T | S U I VA N T | I N D E X
T A B L E DE S M A T I È R E S
Travaux pratiques - Introduction à Scikit-learn
Préambule
(correspond à 1 séance de TP) Installation de scikit-learn
Références externes utiles :
Cours - Introduction
À partir des listes simples sont produits des tableaux unidimensionnels, à partir des listes de
listes (de même taille) des tableaux bidimensionnels, et ainsi de suite. Par exemple :
Le type du tableau peut être indiqué explicitement à la création, des conversions sont
effectuées pour les valeurs fournies :
Il est souvent nécessaire de créer des tableaux remplis de 0, de 1, ou dont le contenu n’est
pas initialisé. Par défaut, le type des tableaux ainsi créés est float64 .
Question :
Expliquez les deux derniers résultats obtenus.
Correction :
Le premier tableau id2d représente une matrice identité d’ordre 5, le second tableau tni2d
représente une matrice non initialisée à 3 lignes et 4 colonnes.
>>> id2d
array([[ 1., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 1.]])
Des tableaux peuvent être initialisés aussi par des séquences générées, par exemple :
Question :
Quel est le résultat de l’appel np.random.rand(3,5) ? Regardez la documentation NumPy (voir
lien au début du TP).
Correction :
Construction d’un tableau à trois lignes et 5 colonnes, dont les éléments sont initialisés par
tirage aléatoire suivant une loi normale uniforme avec des valeurs dans l’intervalle [0, 1] .
Question :
Générez le contenu d’un tableau de même taille (3, 5) à partir plutôt d’une loi normale (de
moyenne 0 et variance 1).
Correction :
C’est la fonction .randn() qui doit être employée à la place.
>>> tr = np.arange(20)
>>> tr
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
>>> tr.reshape(4,5)
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
>>> tr.reshape(2,10)
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
>>> tr.reshape(20)
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
Si un tableau est considéré trop grand pour être affiché en entier, NumPy affiche le début et la
fin, avec des ... au milieu :
>>> tr
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
>>> tr[:6]
array([0, 1, 2, 3, 4, 5])
>>> tr[:6:2] # la dernière valeur indique le pas de l'échantillonnage
array([0, 2, 4])
>>> a = tr[:2]
>>> a
array([0, 1])
>>> a[0] = 3
>>> tr
array([ 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
Les données ne sont pas copiées de tr vers un nouveau tableau a , la modification d’un
élément de a avec a[0] = 3 change aussi le contenu de tr[0] . Pour obtenir une copie il faut
utiliser copy() :
>>> a = tr[:2].copy()
>>> a
array([3, 1])
>>> a[0] = 0
>>> a
array([0, 1])
>>> tr
array([ 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
Question :
Faites l’extraction des colonnes impaires de ta2d .
Correction :
Toutes les lignes (donc :, ), la première colonne est 1 et on va jusqu’au bout avec un pas de
2 (donc 1::2 ) :
>>> ta2d[:,1::2]
array([[ 0.98760001, 0.65422127],
[ 0.09843615, 0.58226529],
[ 0.30371289, 0.30087438]])
Pour les tableaux multidimensionnels, lors des itérations c’est le dernier indice qui change le
plus vite, ensuite l’avant-dernier, et ainsi de suite. Par exemple, pour les tableaux
bidimensionels c’est l’indice de colonne qui change d’abord et ensuite celui de ligne (le tableau
est lu ligne après ligne) :
◾ fname : fichier ou chaîne de caractères ; si le fichier a une extension .gz ou .bz2 , il est
d’abord décompressé.
◾ dtype : type, optionnel, float par défaut.
◾ comments : chaîne de caractères, optionnel, indique une liste de caractères employée
dans le fichier pour précéder des commentaires (à ignorer lors de la lecture).
◾ delimiter : chaîne de caractères, optionnel, indique la chaîne de caractères employée
pour séparer des valeurs, par défaut “ “ (l’espace).
◾ converters : dictionnaire, optionnel, pour permettre des conversions.
◾ skiprows : entier, optionnel, pour le nombre de lignes à sauter en début de fichier
(par défaut 0).
◾ usecols : séquence, optionnel, indique les colonnes à lire ; par ex. usecols = [1,4,5]
extrait la 2ème, 5ème et 6ème colonne ; par défaut toutes les colonnes sont
extraites.
◾ unpack : booléen, optionnel, false par défaut ; si true , le tableau est transposé.
◾ ndmin : entier, optionnel, le tableau a au moins ndmin dimensions ; par défaut 0 .
(voir http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html)
Utilisation :
Une fonction plus flexible est genfromtxt , vous pouvez regarder son utilisation dans la
documentation.
La fonction numpy.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='',
comments='# ') permet d’écrire un tableau dans un fichier texte. Les paramètres sont :
(voir http://docs.scipy.org/doc/numpy/reference/generated/numpy.savetxt.html)
Utilisation :
Dans une autre fenêtre terminal, affichez les 10 premières lignes du fichier enregistré avec
head geyserv_nouveau.txt .
◾ fromfile(file[, dtype, count, sep]) : Construction d’un tableau à partir d’un fichier
texte ou binaire.
◾ fromregex(file, regexp, dtype) : Construction d’un tableau à partir d’un fichier texte,
avec un parseur d’expressions régulières.
◾ genfromtxt() : Fonction plus flexible pour la construction d’un tableau à partir d’un
fichier texte, avec une gestion des valeurs manquantes.
◾ load(file[, mmap_mode, allow_pickle, ...]) : Lecture de tableaux (ou autres objets) à
partir de fichiers .npy , .npz ou autres fichiers de données sérialisées.
◾ loadtxt(fname[, dtype, comments, delimiter, ...]) : Lecture de données à partir d’un
fichier texte.
◾ ndarray.tofile(fid[, sep, format]) : Ecriture d’un tableau dans un fichier texte ou
binaire (par défaut).
◾ save(file, arr[, allow_pickle, fix_imports]) : Ecriture d’un tableau dans un fichier
binaire de type .npy .
◾ savetxt(fname, X[, fmt, delimiter, newline, ...]) : Ecriture d’un tableau dans un fichier
texte.
◾ savez(file, *args, **kwds) : Ecriture de plusieurs tableaux dans un fichier de type .npz
sans compression.
◾ savez_compressed(file, *args, **kwds) : Ecriture de plusieurs tableaux dans un fichier de
type .npz avec compression.
Algèbre linéaire
>>> g0 = geyser[:2,:]
>>> g0
array([[ 3.6, 79. ],
[ 1.8, 54. ]])
>>> g0.transpose()
array([[ 3.6, 1.8],
[ 79. , 54. ]])
>>> np.linalg.inv(g0)
array([[ 1.03448276, -1.51340996],
[-0.03448276, 0.06896552]])
>>> g0.dot(tu2d) # ou np.dot(g0,tu2d)
array([[ 82.6, 82.6],
[ 55.8, 55.8]])
>>> tu2d
array([[ 1., 1.],
[ 1., 1.]])
>>> g0.dot(np.eye(2))
array([[ 3.6, 79. ],
[ 1.8, 54. ]])
>>> >>> g0.trace()
57.600000000000001
Cela permet d’obtenir les valeurs propres (chacune répétée suivant sa multiplicité) et les
vecteurs propres tels que la colonne vpvp[1][:,i] est le vecteur propre unitaire (de norme égale
à 1) correspondant à la valeur propre vpvp[0][i] .
Question :
Comment vérifier facilement ce calcul ?
Correction :
Simplement en vérifiant la relation de diagonalisation de la matrice symétrique initiale :
>>> md = np.diag(vpvp[0])
>>> vpvp[1].dot(md.dot(vpvp[1].transpose()))
Vectorisation de fonctions
Des fonctions Python qui travaillent sur des scalaires peuvent être vectorisées, c’est à dire
travailler sur des tableaux, élément par élément. Par exemple :
>>> addsubtract(2,3)
5
>>> vec_addsubtract = np.vectorize(addsubtract)
>>> tu2d
array([[ 1., 1.],
[ 1., 1.]])
>>> g0
array([[ 3.6, 79. ],
[ 1.8, 54. ]])
>>> vec_addsubtract(g0,tu2d)
array([[ 2.6, 78. ],
[ 0.8, 53. ]])
SciPy
SciPy ajoute de très nombreuses fonctions permettant de faire des calculs scientifiques. Il est
possible d’importer SciPy en entier avec import scipy mais il est préférable de se limiter aux
fonctionnalités utilisées, par exemple from scipy import linalg .
scipy.linalg contient toutes les fonctions de numpy.linalg plus quelques autres. Par ailleurs,
scipy.linalg est systématiquement compilée avec un support BLAS/LAPACK, alors que pour
numpy.linalg cela n’est pas obligatoire. Les calculs peuvent ainsi être plus rapide si c’est
scipy.linalg qui est utilisée.
Exemples :
>>> linalg.det(g0)
52.19999999999998
>>> linalg.norm(g0) # par défaut, norme de Frobenius
95.776823918941901
>>> linalg.norm(g0,'fro')
95.776823918941901
>>> linalg.norm(g0,1) # norme L1
133.0
>>> linalg.eig(g0)
(array([ 0.92097563+0.j, 56.67902437+0.j]), array([[-0.99942549, -0.83004523],
[ 0.03389222, -0.55769609]]))
Statistiques
De nombreuses fonctionnalités statistiques sont disponibles dans le module scipy.stats , comme
la génération de valeurs aléatoires suivant différentes distributions, des statistiques
descriptives et des tests statistiques.
Regardez les fonctionnalités de scipy.stats sur
http://docs.scipy.org/doc/scipy/reference/tutorial/stats.html.
Question :
Générez en utilisant scipy.stats une matrice 6 x 6 dont les valeurs sont issues d’une loi
normale de moyenne 1 et écart-type 3. Calculez les statistiques descriptives par ligne et par
colonne. Que constatez-vous ?
Correction :
Il faut utiliser norm.rvs() avec les valeurs appropriées pour la localisation et l’échelle :
Evidemment, les statistiques descriptives diffèrent de façon significative entre lignes et entre
colonnes.
Question :
Calculez les statistiques descriptives par ligne et par colonne pour le tableau geyser .
Correction :
◾ Documentation Matplotlib
>>> plt.plot(geyser)
>>> plt.title('Old Faithful Geyser Data') # intitulé du graphique
>>> plt.xlabel('numéro éruption') # signification axe des x
>>> plt.ylabel('durée éruption/pause (min)') # signification axe des y
>>> plt.legend(('Durée éruption', 'Durée pause'), loc='best')
>>> plt.show()
On observe que chaque colonne du tableau geyser a été représentée comme une série à part.
Question :
Les deux séries ont des moyennes et des écart-types très différents. Transformez le tableau
geyser pour obtenir une moyenne de 0 et un écart-type de 1 pour chacune de ces séries et
affichez-les de nouveau.
Lorsque les observations sont issues de tirages indépendants, il est d’usage de représenter le
vecteur correspondant à chaque observation comme un point, éventuellement identifié par son
indice. Il est possible de transmettre à la fonction plot deux tableaux unidimensionnels (de
même taille) représentant les coordonnées x et respectivement y des données :
Le résultat est illisible car par défaut les points d’indices successifs sont reliés entre eux. Il
faut modifier l’affichage, en précisant par ex. que l’on souhaite afficher chaque point comme
un + de couleur rouge :
Question :
Multipliez une des colonnes par 2.5 et affichez le résultat.
Le graphique peut être tourné en 3D à l’aide de la souris (bouton gauche maintenu appuyé).
Il est posible d’avoir plusieurs figures ouvertes en même temps si chacune a son propre
identifiant ( fig1 , fig2 , …) et si les appels à la fonction show() ne sont pas bloquants (utilisation
de plt.show(block=False) ).
Question :
En vous servant de la documentation, modifiez la couleur des points et ajoutez des
étiquettes sur les axes.
Question :
Complétez le tableau geyser d’une troisième colonne issue de tirages aléatoires et affichez le
résultat sous forme graphique.
Il est possible d’afficher les étiquettes textuelles associées aux observations. Pour cela, il faut
d’abord chercher des données adaptées en entrant dans une fenêtre terminal :
Vous pouvez regarder le contenu de ce fichier. Nous sélectionnons pour une visualisation les
colonnes suivantes :
La lecture des données sera faite dans deux tableaux différents, un pour les trois variables
numériques et l’autre pour les noms des espèces :
Pour l’affichage :
>>> plt.show()
Question :
Pour améliorer la lisibilité, affichez seulement une observation sur deux.
Correction :
Dans la boucle for ci dessus, remplacez range(len(noms)) par np.arange(0, len(noms), 2) .
Introduction à Scikit-learn
◾ Site scikit-learn