Classification automatique de fromages

Page 1 sur 17Lecteur de document UniversityLib

Classification automatique de fromages

Data Analysis and Machine Learning · notes

Voir tous les documents en intelligence artificielle et données

1

Importation des données, description

DONNÉES

2

Objectif de l’étude

Classification automatique de fromages

Traitements réalisés

  • Chargement et description des données

  • Classification automatique

  • Pistes pour la détection du nombre adéquat de classes

  • Description – interprétation des groupes

CarredelEst 314 353.5 72.6 26.3 51.6 30.3 21 70 20
Babybel 314 238 209.8 25.1 63.7 6.4 22.6 70 27
Beaufort 401 112 259.4 33.3 54.9 1.2 26.6 120 41
Bleu 342 336 211.1 28.9 37.1 27.5 20.2 90 27
Camembert 264 314 215.9 19.5 103 36.4 23.4 60 20
Cantal 367 256 264 28.8 48.8 5.7 23 90 30
Chabichou 344 192 87.2 27.9 90.1 36.3 19.5 80 36
Chaource 292 276 132.9 25.4 116.4 32.5 17.8 70 25
Cheddar 406 172 182.3 32.5 76.4 4.9 26 110 28
Comte 399 92 220.5 32.4 55.9 1.3 29.2 120 51
Coulomniers 308 222 79.2 25.6 63.6 21.1 20.5 80 13
Edam 327 148 272.2 24.7 65.7 5.5 24.7 80 44
Emmental 378 60 308.2 29.4 56.3 2.4 29.4 110 45
Fr.chevrepatemolle 206 160 72.8 18.5 150.5 31 11.1 50 16
Fr.fondu.45 292 390 168.5 24 77.4 5.5 16.8 70 20
Fr.frais20nat. 80 41 146.3 3.5 50 20 8.3 10 11
Fr.frais40nat. 115 25 94.8 7.8 64.3 22.6 7 30 10
Maroilles 338 311 236.7 29.1 46.7 3.6 20.4 90 40
Morbier 347 285 219 29.5 57.6 5.8 23.6 80 30
Parmesan 381 240 334.6 27.5 90 5.2 35.7 80 46
Petitsuisse40 142 22 78.2 10.4 63.4 20.4 9.4 20 10
PontlEveque 300 223 156.7 23.4 53 4 21.1 70 22
Pyrenees 355 232 178.9 28 51.5 6.8 22.4 90 25
Reblochon 309 272 202.3 24.6 73.1 8.1 19.7 80 30
Rocquefort 370 432 162 31.2 83.5 13.3 18.7 100 25
SaintPaulin 298 205 261 23.3 60.4 6.7 23.3 70 26
Tome 321 252 125.5 27.3 62.3 6.2 21.8 80 20
Vacherin 321 140 218 29.3 49.2 3.7 17.6 80 30
Yaourtlaitent.nat. 70 91 215.7 3.4 42.9 2.9 4.1 13 14

3

Données disponibles

Publicité

Fromages calories sodium calcium lipides retinol folates proteines cholesterol magnesium

Fichier de données

Importation, statistiques descriptives et graphiques
 #modification du dossier par défaut
 import os
 os.chdir("…")

 #importation des données
 import pandas
 fromage = pandas.read_table("fromage.txt",sep="\t",header=0,index_col=0)

 #dimension des données
 print(fromage.shape)

 #statistiques descriptives
 print(fromage.describe())

 #graphique - croisement deux à deux des variables
 from pandas.tools.plotting import scatter_matrix
 scatter_matrix(fromage,figsize=(9,9))

Ce type de graphique n’est jamais anodin. Nous constatons par exemple que (1) « lipides » est fortement corrélé avec « calories » et « cholestérol » (sans trop de surprises) (remarque : la même information va peser 3 fois dans l’analyse) ; (2) dans certaines configurations, des groupes semblent apparaître naturellement (ex. croisement de « protéines » et « cholestérol », avec une corrélation inter-groupes assez marquée).

4

Classification ascendante hiérarchique

CAH

5

Classification ascendante hiérarchique

Utilisation du package « scipy »
 #librairies pour la CAH
 from matplotlib import pyplot as plt
 from scipy.cluster.hierarchy import dendrogram, linkage

 #générer la matrice des liens
 Z = linkage(fromage_cr,method='ward',metric='euclidean')

 #affichage du dendrogramme
 plt.title("CAH")
 dendrogram(Z,labels=fromage.index,orientation='left',color_threshold=0)
 plt.show()

##### Le dendrogramme « suggère » un découpage en 4 groupes. On note qu’une classe de fromages, les « fromages frais » (tout à gauche), se démarque fortement des autres au point qu’on aurait pu envisager aussi un découpage en 2 groupes seulement. Nous y reviendrons plus longuement lorsque nous mixerons l’analyse avec une analyse en composantes principales (ACP).

6

Classification ascendante hiérarchique

Découpage en classes – Matérialisation des groupes

Publicité

 #matérialisation des 4 classes (hauteur t = 7)
 plt.title('CAH avec matérialisation des 4 classes')
 dendrogram(Z,labels=fromage.index,orientation='left',color_threshold=7)
 plt.show()

 #découpage à la hauteur t = 7 ==> identifiants de 4 groupes obtenus
 groupes_cah = fcluster(Z,t=7,criterion='distance')
 print(groupes_cah)

 #index triés des groupes
 import numpy as np
 idg = np.argsort(groupes_cah)

 #affichage des observations et leurs groupes
 print(pandas.DataFrame(fromage.index ,groupes_cah ))

Le 1 groupe est constitué de fromages frais. Le 2 de fromages à pâte molle. Le 3 [ème] de fromages « durs ». Le 4 [ème] est un peu fourre-tout (de mon point de vue).

Mes compétences en fromage s’arrêtent là (merci à Wikipédia). Pour une caractérisation à l’aide des variables de l’étude, il faut passer par des techniques statistiques univariées (simples à lire) ou multivariées (tenant compte des relations entre les variables).

Groupe Fromage
1 Yaourtlaitent.nat.
1 Fr.frais20nat.
1 Petitsuisse40
1 Fr.frais40nat.
2 Fr.chevrepatemolle
2 Camembert
2 Chabichou
2 Chaource
3 Emmental
3 Parmesan
3 Beaufort
3 Comte
4 Pyrenees
4 PontlEveque
4 Rocquefort
4 SaintPaulin
4 Tome
4 Reblochon
4 CarredelEst
4 Maroilles
4 Vacherin
4 Edam
4 Coulomniers
4 Cheddar
4 Cantal
4 Bleu
4 Babybel
4 Morbier
R.R. – Université Lyon
4

Fr.fondu.45

Méthode des centres mobiles

K-MEANS

8

Classe Fromages
0 CarredelEst
0 Camembert
0 Fr.chevrepatemolle
0 Chabichou
0 Chaource
0 Coulomniers
1 Petitsuisse40
1 Fr.frais40nat.
1 Fr.frais20nat.
1 Yaourtlaitent.nat.
2 Parmesan
2 Edam
2 Emmental
2 Beaufort
2 Comte
3 Tome
3 SaintPaulin
3 Rocquefort
3 Reblochon
3 Pyrenees
3 PontlEveque
3 Cheddar
3 Morbier
3 Maroilles
3 Bleu
3 Vacherin
3 Cantal
3 Babybel
3 Fr.fondu.45
Méthode des centres mobiles
Groupes issus du clustering
Utilisation du package « scikit-learn »
Classe Fromages
0 CarredelEst
#k-means sur les données centrées et réduites
from sklearn import cluster 0 Camembert
kmeans = cluster.KMeans(nclusters=4) 0 Fr.chevrepatemolle
kmeans.fit(fromage
cr)
0 Chabichou
0 Chaource
#index triés des groupes
0 Coulomniers
idk = np.argsort(kmeans.labels)
1 Petitsuisse40
#affichage des observations et leurs groupes 1 Fr.frais40nat.
print(pandas.DataFrame(fromage.index ,kmeans.labels
)) 1 Fr.frais20nat.
1 Yaourtlaitent.nat.
#distances aux centres de classes des observations
2 Parmesan
print(kmeans.transform(fromagecr))
2 Edam
#correspondance avec les groupes de la CAH 2 Emmental
pandas.crosstab(groupes
cah,kmeans.labels_) 2 Beaufort
2 Comte
Groupe 0 1 2 3
3 Tome
CarredelEst 2.22 5.53 5.22 2.92
3 SaintPaulin
Babybel 3.02 5.19 2.79 0.74
3 Rocquefort
Beaufort 5.16 7.51 1.15 2.86
3 Reblochon
Bleu 3.24 6.12 3.90 2.11
3 Pyrenees
Camembert 1.93 5.40 5.10 3.54
Cantal 4.02 6.30 2.20 1.19 3 PontlEveque
Chabichou 1.78 5.93 4.53 3.39 3 Cheddar
Chaource 1.03 5.55 5.09 3.46 3 Morbier
Cheddar 3.75 6.82 2.29 1.95 3 Maroilles
Comte 5.44 7.84 1.35 3.42 3 Bleu
Coulomniers 1.96 4.84 4.75 2.49 3 Vacherin
Edam 4.23 6.13 1.34 2.25
3 Cantal
Emmental 5.53 7.48 0.90 3.40
3 Babybel
Fr.chevrepatemolle 3.10 5.01 7.09 5.54
3 Fr.fondu.45
Fr.fondu.45 2.84 5.28 4.45 1.89
Fr.frais20nat. 5.33 0.68 7.61 6.00
Fr.frais40nat. 4.55 1.01 7.32 5.61
Maroilles 4.20 6.46 2.45 1.53
Morbier 3.47 6.06 2.50 0.65
Parmesan 5.23 7.94 2.11 3.60
Petitsuisse40 4.38 1.21 7.13 5.40
PontlEveque 3.08 4.69 3.52 1.26
Pyrenees 3.28 5.71 2.81 0.71
Correspondance CAH – K-Means
Reblochon 2.74 5.31 2.94 0.81
Le groupe 1 de la CAH coïncide avec
Rocquefort 3.02 6.81 4.22 2.18
le groupe 1 des K-Means. Après, il y a
SaintPaulin 3.47 5.12 2.67 1.37
certes des correspondances, mais
Tome 2.73 5.25 3.67 1.26
elles ne sont pas exactes.
Vacherin 3.79 5.27 2.63 1.50
Yaourtlaitent.nat. 6.09 1.93 7.46 5.94
Distances aux centres de classes pour chaque individu
Col2 Col3 Col4 Col5 Col6 Groupes issus du clustering
Groupe 0 1 2 3 3 3
CarredelEst 2.22 5.53 5.22 2.92 2.92 2.92
Babybel 3.02 5.19 2.79 0.74 0.74 0.74
Beaufort 5.16 7.51 1.15 2.86 2.86 2.86
Bleu 3.24 6.12 3.90 2.11 2.11 2.11
Camembert 1.93 5.40 5.10 3.54 3.54 3.54
Cantal 4.02 6.30 2.20 1.19 1.19 1.19
Chabichou 1.78 5.93 4.53 3.39 3.39 3.39
Chaource 1.03 5.55 5.09 3.46 3.46 3.46
Cheddar 3.75 6.82 2.29 1.95 1.95 1.95
Comte 5.44 7.84 1.35 3.42 3.42 3.42
Coulomniers 1.96 4.84 4.75 2.49 2.49 2.49
Edam 4.23 6.13 1.34 2.25 2.25 2.25
Emmental 5.53 7.48 0.90 3.40 3.40 3.40
Fr.chevrepatemolle 3.10 5.01 7.09 5.54 5.54 5.54
Fr.fondu.45 2.84 5.28 4.45 1.89 1.89 1.89
Fr.frais20nat. 5.33 0.68 7.61 6.00 6.00 6.00
Fr.frais40nat. 4.55 1.01 7.32 5.61 5.61 5.61
Maroilles 4.20 6.46 2.45 1.53 1.53 1.53
Morbier 3.47 6.06 2.50 0.65 0.65 0.65
Parmesan 5.23 7.94 2.11 3.60 3.60 3.60
Petitsuisse40 4.38 1.21 7.13 5.40 5.40 5.40
PontlEveque 3.08 4.69 3.52 1.26 1.26 1.26
Pyrenees 3.28 5.71 2.81 0.71 0.71 0.71
Reblochon 2.74 5.31 2.94 0.81 0.81 0.81
Rocquefort 3.02 6.81 4.22 2.18 2.18 2.18
SaintPaulin 3.47 5.12 2.67 1.37 1.37 1.37
Tome 2.73 5.25 3.67 1.26 1.26 1.26
Vacherin 3.79 5.27 2.63 1.50 1.50 1.50
Yaourtlaitent.nat. 6.09 1.93 7.46 5.94 5.94 5.94
~~Distances aux centres de classes pour chaque individu~~ ~~Distances aux centres de classes pour chaque individu~~ ~~Distances aux centres de classes pour chaque individu~~ ~~Distances aux centres de classes pour chaque individu~~ ~~Distances aux centres de classes pour chaque individu~~ ~~Distances aux centres de classes pour chaque individu~~ ~~Distances aux centres de classes pour chaque individu~~
R.R. – Université Lyon 2

(avec en couleur les min. respectifs)
R.R. – Université Lyon 2

(avec en couleur les min. respectifs)
R.R. – Université Lyon 2

(avec en couleur les min. respectifs)
R.R. – Université Lyon 2

(avec en couleur les min. respectifs)
R.R. – Université Lyon 2

(avec en couleur les min. respectifs)
9 9

Méthode des centres mobiles

Aide à la détection du nombre adéquat de groupes

K-MEANS, à la différence de la CAH, ne fournit pas d’outils d’aide à la détection du nombre de classes. Nous devons les programmer sous Python ou utiliser des procédures proposées par des packages dédiés. Le schéma est souvent le même : on fait varier le nombre de groupes et on surveille l’évolution d’un indicateur de qualité de la solution c.-à-d. l’aptitude des individus à être plus proches de ses congénères du même groupe que des individus des autres groupes.

Dans ce qui suit, on calcule la métrique « silhouette » pour différents nombres de groupes issus de la méthode des centres mobiles.

 #librairie pour évaluation des partitions
 from sklearn import metrics

 #utilisation de la métrique "silhouette"
 #faire varier le nombre de clusters de 2 à 10
 res = np.arange(9,dtype="double")
 for k in np.arange(9):
 km = cluster.KMeans(n_clusters=k+2)
 km.fit(fromage_cr)
 res = metrics.silhouette_score(fromage_cr,km.labels_)

 print(res)

 #graphique
 import matplotlib.pyplot as plt
 plt.title("Silhouette")
 plt.xlabel("# of clusters")
 plt.plot(np.arange(2,11,1),res)
 plt.show()

10

Publicité

Analyses univariées et multivariées

INTERPRÉTATION DES CLASSES

11

Interprétation des classes

Statistiques comparatives

L’idée est de comparer les moyennes des variables actives conditionnellement aux groupes. Il est possible de quantifier globalement l’amplitude des écarts avec la proportion de variance expliquée (carré du rapport de corrélation). La démarche peut être étendue aux variables illustratives. Pour les catégorielles, nous confronterions les distributions conditionnelles.

L’approche est simple et les résultats faciles à lire. Rappelons cependant que nous ne tenons pas compte des liaisons entre les variables dans ce cas.

#moyenne par variable 0
m = fromage.mean() 1
#TSS 2
TSS = fromage.shape[0]fromage.var(ddof=0) 3
print(TSS)
#data.frame conditionnellement aux groupes
gb = fromage.groupby(kmeans.labels_)
#effectifs conditionnels
nk = gb.size()
print(nk)
#moyennes conditionnelles
mk = gb.mean()
print(mk)
#pour chaque groupe écart à la moyenne par
variable
EMk = (mk-m)
*2
#pondéré par les effectifs du groupe
EM = EMk.multiply(nk,axis=0)
#somme des valeurs => BSS
BSS = np.sum(EM,axis=0)
print(BSS)
#carré du rapport de corrélation
#variance expliquée par l'appartenance aux groupes
#pour chaque variable
R2 = BSS/TSS
print(R2)
Col2 4
5
6
14
Carré Rapport de corr.
calories 0.863799
sodium 0.599117
calcium 0.620108
lipides 0.851983
retinol 0.382815
folates 0.760722
proteines 0.810316
cholesterol 0.797596
magnesium 0.796207
#moyenne par variable
m = fromage.mean()
#TSS
TSS = fromage.shape[0]*fromage.var(ddof=0)
print(TSS)
#data.frame conditionnellement aux groupes
gb = fromage.groupby(kmeans.labels_)
#effectifs conditionnels
nk = gb.size()
print(nk)
#moyennes conditionnelles
mk = gb.mean()
print(mk)
#pour chaque groupe écart à la moyenne par
variable
EMk = (mk-m)**2
#pondéré par les effectifs du groupe
EM = EMk.multiply(nk,axis=0)
#somme des valeurs => BSS
BSS = np.sum(EM,axis=0)
print(BSS)
#carré du rapport de corrélation
#variance expliquée par l'appartenance aux groupes
#pour chaque variable
R2 = BSS/TSS
print(R2)

0
1
2
3|
Moyennes conditionnelles
 calories sodium calcium lipides retinol folates
0 101.750000 44.750000 133.75 6.275000 55.150000 16.475000
1 377.200000 130.400000 278.98 29.460000 64.560000 3.120000
2 288.000000 252.916667 110.10 23.866667 95.866667 31.266667
3 334.285714 267.428571 199.70 27.500000 60.050000 7.728571

 proteines cholesterol magnesium
0 7.200000 18.250000 11.250000
1 29.120000 102.000000 45.400000
2 18.883333 68.333333 21.666667
3 21.228571 83.571429 27.142857

12

Interprétation des classes

Analyse en composantes principales (ACP) Avec l’ACP, nous tenons compte des liaisons entre les variables. L’analyse est plus riche. Mais il faut savoir lire correctement les sorties de l’ACP.
 #ACP
 from sklearn.decomposition import PCA
 acp = PCA(n_components=2).fit_transform(fromage_cr)

 #projeter dans le plan factoriel
 #avec un code couleur différent selon le groupe
 #remarquer le rôle de zip() dans la boucle
 for couleur,k in zip(['red','blue','lawngreen','aqua'],[0,1,2,3]):
 plt.scatter(acp ,acp ,c=couleur)
 plt.show()

##### Il y a un problème. Le groupe des fromages frais (n° de groupe = 0) écrase l’information disponible et tasse les autres fromages dans un bloc qui s’oriente différemment. De fait, si l’on comprend bien la nature du groupe n°0 des fromages frais, les autres sont plus compliqués à comprendre lorsqu’ils sont replacés dans le premier plan factoriel.

13

A la lumière des résultats de l’ACP

Publicité

COMPLÉTER L’ANALYSE

14

Approfondir l’analyse

Retirer les fromages frais du jeu de données

Les fromages frais sont tellement particuliers – éloignés de l’ensemble des autres observations

  • qu’ils masquent des relations intéressantes qui peuvent exister entre ces produits. Nous reprenons l’analyse en les excluant des traitements.
 #retirer des observations le groupe n°0 du k-means précédent
 fromage_subset = fromage.iloc 
 print(fromage_subset.shape)

 #centrer et réduire
 fromage_subset_cr = preprocessing.scale(fromage_subset)

 #générer la matrice des liens
 Z_subset = linkage(fromage_subset_cr,method='ward',metric='euclidean')

 #cah et affichage du dendrogramme
 plt.title("CAH")
 dendrogram(Z_subset,labels=fromage_subset.index,orientation='left',color_threshold=7)
 plt.show()

 #groupes
 groupes_subset_cah = fcluster(Z_subset,t=7,criterion='distance')
 print(groupes_subset_cah)

##### 3 groupes se distinguent. On a moins le phénomène d’écrasement constaté dans l’analyse précédente.

15

Approfondir l’analyse

Retirer les fromages frais du jeu de données (2/2)
 #ACP
 acp_subset = PCA(n_components=2).fit_transform(fromage_subset_cr)

 #projeter dans le plan factoriel
 #avec un code couleur selon le groupe
 #remarquer le rôle de zip()
 plt.figure(figsize=(10,10))
 for couleur,k in zip(['blue','lawngreen','aqua'],[1,2,3]):

plt.scatter(acpsubset ,acpsubset ,c=couleur)

 #mettre les labels des points
 #remarquer le rôle de enumerate()
 for i,label in enumerate(fromage_subset.index):
 plt.annotate(label,(acp_subset ,acp_subset ))

 plt.show()

##### Les groupes sont constitués essentiellement sur le 1 facteur. Quelques fromages ont changé de camp par rapport à l’analyse précédente.

16

17