Accueil

Traduction

Tutoriel Python - sommaire

Tutoriel Python - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Apprentissage automatique ou "machine learning"

L'apprentissage automatique permet à un ordinateur d'apprendre à partir de l'étude statistiques de données.
L'apprentissage automatique constitue une étape vers l'intelligence artificielle (IA).

Rôle de l'apprentissage automatique : analyser des données pour prédire des résultats.
En apprentissage automatique, il est préférable de travailler avec de très grands ensembles de données.

Tendances centrales et de dispersion

Commençons par faire des statistiques descriptives.
Pour résumer une série statistique on précise les tendances centrales et les indicateurs de dispersion et les centiles.

Tendances centrales

Indicateurs de dispersion

L'écart type est un nombre qui décrit la dispersion des valeurs.
Un écart type faible signifie que la plupart des valeurs sont proches de la moyenne.
Un écart type élevé signifie que les valeurs sont dispersées sur une plus grande plage.
La variance est un autre nombre qui indique la dispersion des valeurs.
En fait la racine carrée de la variance donne l'écart type ! Réciproquement, multiplier l'écart type par lui-même donne la variance !

Les centiles

Les centiles (ou fréquences cumulées relatives) sont aussi fort utiles.
Quant les bornes sont 25%,50% & 75% on parle de "quartiles".

Commandes dans la console

La vitesse moyenne de 13 véhicules a été enregistrée dans une liste.

>>> vitesses =[99,86,87,88,111,86,103,87,94,78,77,85,86]
>>> import numpy
>>> moy = numpy.mean(vitesses)
>>> print(moy)
89.76923076923077
>>> mediane = numpy.median(vitesses)
>>> print(mediane)
87.0
>>> from scipy import stats
>>> mode = stats.mode(vitesses)
>>> print(mode)
ModeResult(mode=np.int64(86), count=np.int64(3))
>>> sorted(vitesses)
[77, 78, 85, 86, 86, 86, 87, 87, 88, 94, 99, 103, 111]
>>> x = numpy.std(vitesses)
>>> print(x)
9.258292301032677
>>> x = numpy.var(vitesses)
>>> print(x)
85.71597633136093
>>> ages_immeuble =[5,31,43,48,50,41,7,11,15,39,80,82,32,2,8,6,25,36,27,61,31]
>>> x = numpy.percentile(ages_immeuble,75)
>>> print(x)
43.0
>>> sorted(ages_immeuble)
[2, 5, 6, 7, 8, 11, 15, 25, 27, 31, 31, 32, 36, 39, 41, 43, 48, 50, 61, 80, 82]
>>> print(numpy.percentile(ages_immeuble,50))
31.0
>>> ages_ephad = [80,82,85,78,79,81,90,92,70,95]
>>> sorted(ages_epad)
[70, 78, 79, 80, 81, 82, 85, 90, 92, 95]
>>> print(numpy.percentile(ages_ephad,75))
88.75
>>> print(numpy.percentile(ages_ephad,50))
81.5
>>>

Commentaires

La bibliothèque numpy ne propose pas de fonction pour calculer le mode. Aussi dois-je utiliser le module stats de la bibliothèque scipy. Pensez à installer via pip les bibliothèque numpy & scipy si nécessaire.
La fonction mode() du module stats explique le résultat (86) ; cette valeur est le mode car elle est présente 3 fois.
En triant par valeurs croissantes les vitesses on voit bien que la valeur centrale est 87 (divise bien la série de 13 valeurs).

Pour calculer l'écart type d'une série il faut utiliser la méthode std() de numpy.
Pour calculer la variance d'une série il faut utiliser la méthode var() de numpy.

La liste "ages_immeubles" contient l'âge de tous les habitants d'un immeuble.

Le tri croissant des âges nous explique ces résultats.

Bien évidemment si on effectue les mêmes calculs pour les résidents d'un EPHAD on obtient des résultats très différents ; 50% ont 81,5 ans ou moins ; 75% ont 88,75 ans ou moins.

Générer de gros volumes de données

Jusquà présent nous avons travaillé sur des petites séries.
Or dans le cadre du machin learning il est préférable de travailler sur de gros volumes de données.

Mais il peut être difficile de collecter des données réelles, surtout en début de projet.
En attendant d'avoir des données réelles on peut faire appel à numpy pour générer de gros volumes de données de façon aléatoire.

Générer un gros volume de données de façon aléatoire

Commandes dans la console

x = numpy.random.uniform(0.0, 5.0,300)
>>> print(x)
[4.99558831 8.71919516 1.6507823  4.83382777 3.48532315 6.79265608
 5.9110596  5.5154024  8.16825112 1.23528455 9.64783342 5.33245858
 ...
 8.74580542 7.47918954 8.99244468 3.67724478 9.76528993 7.67749263
 8.67758733 6.18789059 1.75184577 1.01863659 3.56650118 0.17371824
 7.61495578 4.76198228 2.16602183 1.83469036 4.84905152 7.56727853
 8.23893248 1.20047409 9.34390281 2.11673471 9.80474226 4.90770023]
 
>>> import matplotlib.pyplot as plt
>>> plt.hist(x,10)
>>> plt.show()

x = numpy.random.uniform(0.0, 5.0,300) : je crée une liste nommée "x" de 300 flottants compris entre 0 et 10.
plt.hist(x,10) : la méthod hist()
J'importe ensuite le module pyplot de matplotlib pour les représentations graphiques (histogramme,camemberts,etc.)

Le diagramme en bâtons (ou histogramme)

Distribution normale des données

Nous allons maintenant créer une série de données selon une distribution normale ou distribution gaussienne.
La distribution gaussienne, ou distribution normale, est une courbe en forme de cloche décrivant la répartition des données autour d'une moyenne, avec une variabilité mesurée par l'écart type, couramment observée dans les phénomènes naturels.

Commandes dans la console

>>> import numpy
>>> import matplotlib.pyplot as plt
>>> x = numpy.random.normal(10,2,5000)
>>> plt.hist(x,100)
>>>plt.show()

x = numpy.random.normal(10,2,5000) : génère un tableau de 5000 nombres aléatoires suivant une distribution gaussiennet avec une moyenne de 10 et un écart-type de 2.

Représentation graphique

Les valeurs sont concentrées autour de 10 et rarement s'en éloigner de plus de 2.
Comme vous pouvez le constater sur la courbe, la plupart des valeurs se situent entre 8 et 12 avec un maximum aux alentours de 10.

Nuage de points

La méthode scatter() du module pyplot permet de définir un nuage de points.
Il faut en données deux séries de même longueur, l’un pour les valeurs de l’axe des x et l’autre pour les valeurs de l’axe des y.

Commandes

>>> import matplotlib.pyplot as plt
>>> x = [5,7,8,7,2,17,2,9,4,11,12,9,6]
>>> y = [99,86,87,88,111,86,103,87,94,78,77,85,86]
>>> plt.scatter(x,y)
>>> plt.show()

La liste x contient les âges des véhicules et la liste y contient leur vitesse respective.

Représentation graphique

Plus la voiture est âgeé et plus sa vitesse est faible.
Il y a une corrélation entre l'âge d'un véhicule et sa vitesse.

Régressions

Régression linéaire

Le programme

#regression_lineaire.py
import matplotlib.pyplot as plt
from scipy import stats

x = [5,7,8,7,2,17,2,9,4,11,12,9,6]
y = [99,86,87,88,111,86,103,87,94,78,77,85,86]

slope, intercept, r, p, std_err = stats.linregress(x, y)

def calcul_y(x):
  return slope * x + intercept

regression_y= list(map(calcul_y, x))

plt.scatter(x, y)
plt.plot(x,regression_y)
plt.show()

Analyse de ce script

Il y a beaucoup à dire ...
SciPy est une bibliothèque de calcul scientifique basée sur Numpy. SciPy signifie "Scientific Python".

slope, intercept, r, p, std_err = stats.linregress(x, y) ? Cette instruction effectue une régression linéaire et retourne 5 valeurs :

Nous avons besoin que de 3 valeures : slope, x & intercept.
La fonction "calcul_y()" détermine les ordonnées de la droite de régression
regression_y= list(map(calcul_y, x)) : via la fonction générique map() j'applique la fonction "calcul_y()" à tous les termes de la liste x afin d'obtenir toutes les ordonnées des points de la droite de régression.
plt.scatter(x, y) : je trace le nuage de points
plt.plot(x,regression_y) : je trace la droite de régression
plt.show() : j'affiche le graphique correspondant

Le graphique

On observe bien que la vitesse est inversement proportionnelle à l'âge du véhicule.

Régression multiple

La régression multiple est similaire à la régression linéaire, mais elle prend en compte plusieurs variables. Elle permet de prédire une valeur à partir de deux variables ou plus.

Le fichier "voitures.csv"

Marque,Modèle,Cylindrée,Poids,CO2
Toyoty,Aygo,1000,790,99
Mitsubishi,Space Star,1200,1160,95
Skoda,Citigo,1000,929,95
Fiat,500,900,865,90
Mini,Cooper,1500,1140,105
VW,Up!,1000,929,105
Skoda,Fabia,1400,1109,90
Mercedes,A-Class,1500,1365,92
Ford,Fiesta,1500,1112,98
Audi,A1,1600,1150,99
Hyundai,I20,1100,980,99
Suzuki,Swift,1300,990,101
Ford,Fiesta,1000,1112,99
Honda,Civic,1600,1252,94
Hundai,I30,1600,1326,97
Opel,Astra,1600,1330,97
BMW,1,1600,1365,99
Mazda,3,2200,1280,104
Skoda,Rapid,1600,1119,104
Ford,Focus,2000,1328,105
Ford,Mondeo,1600,1584,94
Opel,Insignia,2000,1428,99
Mercedes,C-Class,2100,1365,99
Skoda,Octavia,1600,1415,99
Volvo,S60,2000,1415,99
Mercedes,CLA,1500,1465,102
Audi,A4,2000,1490,104
Audi,A6,2000,1725,114
Volvo,V70,1600,1523,109
BMW,5,2000,1705,114
Mercedes,E-Class,2100,1605,115
Volvo,XC70,2000,1746,117
Ford,B-Max,1600,1235,104
BMW,216,1600,1390,108
Opel,Zafira,1600,1405,109
Mercedes,SLK,2500,1395,120

Le programme

# regression_multiple.py
import pandas
from sklearn import linear_model
df = pandas.read_csv("voitures.csv")
print ("Dateframe: ")
print(df)
print("-------------")
X = df[['Poids', 'Cylindrée']]
y = df['CO2']

regr = linear_model.LinearRegression()
regr.fit(X, y)

# coefficients 
print("coefficients de poids et cylindrée : " , regr.coef_)

# prédire l'émission de C02 d'une voiture de 2,3 T et d'une cylindrée de 1300cm3:
prediction1 = regr.predict([[2300, 1300]])
print("Bilan carbone d'une voiture de 2,3 T et cylindrée de 1300 cm2 :" , prediction1)

# prédire l'émission de C02 d'une voiture de 3,3 T et d'une cylindrée de 1300cm3:
prediction2 = regr.predict([[3300, 1300]])
print("Bilan carbone d'une voiture de 3,3 T et cylindrée de 1300 cm2 :" , prediction2)

Analyse du script

Dès qu'il faut manipuler un fichier CSV pensez à pandas !

Scikit-learn (sklearn) est une bibliothèque pour le "machine learning" en Python donc pour l'analyse prédictive et la modélisation.
Nous avons besoin du module linear_model de cette bibliothèque pour gérer une régression multiple.

Le rendu (sauf affichage du dateframe)

...
coefficients de poids et cylindrée :  [0.00755095 0.00780526]
Bilan carbone d'une voiture de 2,3 T et cylindrée de 1300 cm2 : [107.2087328]
Bilan carbone d'une voiture de 3,3 T et cylindrée de 1300 cm2 : [114.75968007]

reg.coef_ contient les coefficients du poids et de Cylindrée, respectivement : 0,00755095 et 0,00780526
Ces coefficients indiquent que si le poids augmente de 1 kg, les émissions de CO₂ augmentent de 0,00755095 gr. Et si la cylindrée augmente de 1 cm³, les émissions de CO₂ augmentent de 0,00780526 gr.