Skip to content

Commit

Permalink
Eléments complémentaires clustering (#107)
Browse files Browse the repository at this point in the history
* add elements clustering

* add elements clustering

* Apply suggestions from code review

Co-authored-by: Lino Galiana <33896139+linogaliana@users.noreply.github.com>
  • Loading branch information
raphaeleadjerad and linogaliana committed May 12, 2021
1 parent 0fd0e55 commit c6fa115
Showing 1 changed file with 129 additions and 31 deletions.
160 changes: 129 additions & 31 deletions content/course/modelisation/5_clustering.Rmd
Expand Up @@ -29,16 +29,16 @@ summary: |
généralement non observés,
en fonction de caractéristiques observables. Il s'agit d'une
application classique des méthodes non supervisées. Les applications
au monde réel sont nombreuses, notamment dans le domaine de la
segmentation tarifaire.
au monde réel sont nombreuses, notamment dans le domaine de la
segmentation tarifaire.
---


```{r setup, include=FALSE}
dir_path <- gsub(here::here(), "..", here::here("course","modelisation"))
library(knitr)
library(reticulate)
library(knitr)
library(reticulate)
knitr::knit_engines$set(python = reticulate::eng_python)
knitr::opts_chunk$set(fig.path = "")
knitr::opts_chunk$set(eval = TRUE, echo = FALSE, warning = FALSE, message = FALSE)
Expand Down Expand Up @@ -75,23 +75,37 @@ Le *clustering* est un champ d'application de l'apprentissage non-supervisé.
Il s'agit d'exploiter l'information disponible pour regrouper des observations
à la structure commune ensemble.

L'objectif est de créer des classes d'observations pour lesquelles:
L'objectif est de créer des clusters d'observations pour lesquelles:

* au sein de chaque classe, les observations sont homogènes (variance infra-classe minimale)
* les classes ont des profils hétérogènes, c'est-à-dire qu'elles se distinguent l'une de l'autre (variance inter-classes maximale)
* au sein de chaque cluster, les observations sont homogènes (variance intra-cluster minimale)
* les clusters ont des profils hétérogènes, c'est-à-dire qu'ils se distinguent l'une de l'autre (variance inter-clusters maximale)

En Machine Learning, les méthodes de clustering sont très utilisées pour
faire de la recommandation. En faisant, par exemple, des classes homogènes de
consommateur, il est plus facile d'identifier et cibler des comportements
propres à chaque classe de consommateurs.

En Machine Learning, les méthodes de classification sont très utilisées pour
faire de la recommandation. En faisant, par exemple, des classes homogènes de
consommateur, il est plus facile d'identifier et cibler des comportements
propres à chaque classe.
Ces méthodes ont également un intérêt en économie et sciences sociales parce qu'elles permettent
de regrouper des observations sans *a priori* et ainsi interpréter une variable
d'intérêt à l'aune de ces résultats. Ce [travail (très) récent](https://www.insee.fr/fr/statistiques/4925200)
utilise par exemple cette approche.

Les méthodes clustering peuvent aussi intervenir en amont d'un problème de classification (dans des
problèmes d'apprentissage semi-supervisés).
Par exemple, le manuel *Hands-on machine learning with scikit-learn, Keras et TensorFlow* présente dans le
chapitre dédié à l'apprentissage non supervisé quelques exemples.
Dans certaines bases de données, on peut se retrouver avec quelques exemples labellisés mais la plupart
non labellisés. Les labels ont par exemple été faits manuellement par des experts.
Par exemple, supposons que dans la [base MNIST des chiffres manuscrits](https://fr.wikipedia.org/wiki/Base_de_donn%C3%A9es_MNIST), les chiffres ne soient pas labellisés
et que l'on se demande quelle est la meilleure stratégie pour labelliser cette base.
On pourrait regarder des images de chiffres manuscrits au hasard de la base et les labelliser.
Les auteurs du livre montrent qu'il existe toutefois une meilleure stratégie.
Il vaut mieux appliquer un algorithme de clustering en amont pour regrouper les images ensemble et avoir une
image représentative par groupe, et labelliser ces images représentatives au lieu de labelliser au hasard.


Les méthodes de *clustering* sont nombreuses.
Nous allons exclusivement nous pencher sur la plus intuitive: les k-means.
Premièrement, nous pencher sur la plus intuitive: les k-means.

# Données

Expand All @@ -101,12 +115,15 @@ exec(open('./get_data.py').read())

## Principe

L'objectif des kmeans est de partitioner l'espace d'observations en trouvant des points (*centroids*) qui permettent de créer des centres de gravité autour pour lesquels les observations proches peuvent être regroupés dans une classe homogène
L'objectif des kmeans est de partitioner l'espace d'observations en trouvant des points (*centroids*) qui permettent de
créer des centres de gravité pour lesquels les observations proches peuvent être regroupées dans une classe homogène.
L'algorithme Kmeans fonctionne par itération, en initialisant les centroids puis en les mettant à jour à chaque
itération, jusqu'à ce que les centroids se stabilisent :

![](https://scikit-learn.org/stable/_images/sphx_glr_plot_kmeans_assumptions_001.png)

{{% panel status="hint" title="Hint" icon="fa fa-lightbulb" %}}
L'objectif des *kmeans* est de trouver un ensemble une partition des données $S=\{S_1,...,S_K\}$ telle que
L'objectif des *kmeans* est de trouver une partition des données $S=\{S_1,...,S_K\}$ telle que
$$
\arg\min_{S} \sum_{i=1}^K \sum_{x \in S_i} ||x - \mu_i||^2
$$
Expand All @@ -123,7 +140,7 @@ import matplotlib.pyplot as plt
1. Importer les données (l'appeler `df`) et de restreindre aux variables `'Unemployment_rate_2019', 'Median_Household_Income_2019', 'Percent of adults with less than a high school diploma, 2015-19', "Percent of adults with a bachelor's degree or higher, 2015-19"` et bien-sûr `'per_gop'`
2. Faire un kmeans avec $k=4$
3. Créer une variable supplémentaire stockant le résultat de la typologie
4. Choisir deux variables et représenter le nuage de point en colorant différemment
4. Choisir deux variables et représenter le nuage de points en colorant différemment
en fonction du label obtenu
5. Représenter la distribution du vote pour chaque *cluster*

Expand Down Expand Up @@ -185,24 +202,38 @@ p2.fig.savefig("displot.png")
knitr::include_graphics("displot.png")
```

## Choisir le nombre de classes
Il faut noter plusieurs points sur l'algorithme implémenté par défaut par scikit learn, que l'on peut lire dans
la documentation:
- l'algorithme implémenté par défaut est kmeans ++, cela est géré par le paramètre `init`, cela signifie que
l'initialisation des centroids est faite de manière intelligente pour que les centroids initiaux soient choisis
afin de ne pas être trop proches
- l'algorithme va être démarré avec `n_init` différents centroids et le modèle va choisir la meilleure initialisation
en fonction de l'**inertia** du modèle, par défaut égal à 10

Le modèle va renvoyer les `cluster_centers_`, les labels `labels_`, l'inertia `inertia_` et le nombre d'itérations
`n_iter_`

## Choisir le nombre de clusters

Le nombre de classes est fixé par hypothèse du modélisateur. Il y a un arbitrage
entre biais et variance. Un grand nombre de classes implique une variance
infra-classe très faible. Avec beaucoup de classes, on tend à sur-apprendre, ce
Le nombre de clusters est fixé par le modélisateur.
Il existe plusieurs façons de fixer ce nombre: connaissance a priori du problème,
analyse d'une métrique spécifique pour définir le nombre de clusters à choisir, etc.

Il y a un arbitrage
entre biais et variance. Un grand nombre de clusters implique une variance
intra-cluster très faible. Avec beaucoup de clusters, on tend à sur-apprendre, ce
qui est mauvais pour la prédiction (même s'il n'est jamais possible de déterminer
le vrai type d'une observation puisqu'on est en apprentissage non supervisé).
le vrai type d'une observation puisqu'on est en apprentissage non supervisé).

Si le nombre de classes à fixer est inconnu (il n'y a pas d'hypothèses de
modélisation qui justifient plus ou moins de classes), il existe des méthodes
statistiques:
Sans connaissance a priori du nombre de clusters, on peut recourir à deux types de méthode:

* Méthode du coude (*elbow method*): on prend le point d'inflexion de la courbe
de performance du modèle. Cela représente le moment où ajouter une classe
(complexité croissante du modèle) n'apporte que des gains modérer dans la
* Plus empirique, la méthode du coude (*elbow method*): on prend le point d'inflexion de la courbe
de performance du modèle. Cela représente le moment où ajouter un cluster
(complexité croissante du modèle) n'apporte que des gains modérés dans la
modélisation des données

* Score de silhouette: mesure de similarité entre un point et les autres points
du cluster par rapport aux autres clusters. Moins succinctement:
du cluster par rapport aux autres clusters. Plus spécifiquement:

> Silhouette value is a measure of how similar an object is to its own cluster
> (cohesion) compared to other clusters (separation). The silhouette ranges
Expand All @@ -211,9 +242,15 @@ du cluster par rapport aux autres clusters. Moins succinctement:
> clusters. If most objects have a high value, then the clustering
> configuration is appropriate. If many points have a low or negative
> value, then the clustering configuration may have too many or too few clusters
>
>
> Source: [Wikipedia](https://en.wikipedia.org/wiki/Silhouette_(clustering))
Le score de silhouette d'une observation est donc égal à
`(m_nearest_cluster - m_intra_cluster)/max( m_nearest_cluster,m_intra_cluster)`
`m_intra_cluster` est la moyenne des distances de l'observation aux observations du même cluster
et `m_nearest_cluster` est la moyenne des distances de l'observation aux observations du cluster le plus proche.


Le package `yellowbrick` fournit une extension utile à `scikit` pour représenter
facilement la performance en *clustering*.

Expand All @@ -237,9 +274,9 @@ visualizer.show(outpath="elbow-yellowbrick.png") # Finalize and render th
knitr::include_graphics("elbow-yellowbrick.png")
```

`yellowbrick` permet également de représenter des silhouettes mais
l'interprétation en est moins aisée:
`yellowbrick` permet également de représenter des silhouettes mais
l'interprétation en est moins aisée et le coût computationnel plus élevé:

```{python silhouette, include = FALSE, echo=TRUE, error = TRUE}
from yellowbrick.cluster import SilhouetteVisualizer
Expand Down Expand Up @@ -268,3 +305,64 @@ fig.savefig("silhouette-yellowbrick.png")
```{r}
knitr::include_graphics("silhouette-yellowbrick.png")
```

Le score de silhouette offre une représentation plus riche que la courbe coudée.
Sur ce graphique, les barres verticales en rouge et en pointillé représentent le score de silhouette
global pour chaque `k` choisi. On voit par exemple que pour tous les `k` représentés ici, le
score de silhouette se situe entre 0.5 et 0.6 et varie peu.
Ensuite, pour un `k` donné, on va avoir la représentation des scores de silhouette de chaque
observation, regroupées par cluster.
Par exemple, pour `k=4`, ici, on voit bien quatre couleurs différentes qui sont les 4 clusters modélisés.
Les ordonnées sont toutes les observations clusterisées et en abscisses on a le score de silhouette de
chaque observation. Si au sein d'un cluster, les observations ont un score de silhouette plus faible que le
score de silhouette global (ligne verticale en rouge), cela signifie que les observations du clusters sont
trop proches des autres clusters.

Grâce à cette représentation on peut aussi se rendre compte de la taille relative des clusters. Par exemple,
avec `k=3`, on voit qu'on a deux clusters conséquents et un plus "petit" cluster relativement aux deux autres.
Cela peut nous permettre de choisir des clusters de taille homogène ou non.

Enfin, quand le score de silhouette est négatif, cela signifie que la moyenne des distances de l'observation
aux observations du cluster le plus proche est inférieure à la moyenne des distances de l'observation aux
observations de son cluster. Cela signifie que l'observation est mal classée.



## Autres méthodes de clustering

Il existe de nombreuses autres méthodes de clustering. Parmi les plus connues, on peut citer deux exemples en particulier:

- DBSCAN
- les mélanges de Gaussiennes

### DBSCAN

L'algorithme DBSCAN est implémenté dans `sklearn.cluster`. Il peut être utilisé pour faire de la détection d'anomalie
notamment.
En effet, cette méthode repose sur le clustering en régions où la densité
des observations est continue, grâce à la notion de voisinage selon une certaine distance epsilon.
Pour chaque observation, on va regarder si dans son voisinage selon une distance epsilon, il y a des voisins. S'il y a au
moins `min_samples` voisins, alors l'observation sera une *core instance*.

Les observations qui ne sont pas des *core instances* et qui n'en ont pas dans leur voisinage selon une distance espilon
vont être détectées comme des anomalies.


### Les mélanges de gaussiennes

En ce qui concerne la théorie, voir le cours [Probabilités numériques et statistiques computationnelles, M1 Jussieu, V.Lemaire et T.Rebafka](http://www.proba.jussieu.fr/pageperso/rebafka/#enseignement)
Se référer notamment aux notebooks pour l'algorithme EM pour mélange gaussien.

Dans `sklearn`, les mélanges gaussiens sont implémentés dans `sklearn.mixture` comme `GaussianMixture`.
Les paramètres importants sont alors le nombre de gaussiennes `n_components` et le nombre d'initiatisation `n_init`.
Il est possible de faire de la détection d'anomalie avec les mélanges de gaussiennes.


{{% panel status="hint" title="Pour aller plus loin" icon="fas fa-glasses" %}}

Il existe de nombreuses autres méthodes de clustering:
- Local outlier factor
- bayesian gaussian mixture models
- différentes méthodes de clustering hiérarchique
- etc.
{{% /panel %}}

0 comments on commit c6fa115

Please sign in to comment.