diff --git a/content/annexes/corrections.qmd b/content/annexes/corrections.qmd
index 18da5363d..960818c6e 100644
--- a/content/annexes/corrections.qmd
+++ b/content/annexes/corrections.qmd
@@ -62,7 +62,7 @@ print_badges("content/manipulation/03_geopandas_TP.qmd", correction=True)
```
:::
-Webscraping
+* [Exercices _webscraping_](../manipulation/04a_webscraping.qmd)
::: {.cell .markdown}
```{python}
@@ -74,7 +74,9 @@ print_badges("content/manipulation/04a_webscraping_TP.qmd", correction=True)
```
:::
-Expressions régulières:
+
+* [Exercices expressions régulières](../manipulation/04b_regex_TP.qmd)
+
::: {.cell .markdown}
```{python}
@@ -86,7 +88,8 @@ print_badges("content/manipulation/04b_regex_TP.qmd", correction=True)
```
:::
-Chapitre sur les API:
+* [Exercices API](../manipulation/04c_API_TP.qmd)
+
::: {.cell .markdown}
```{python}
@@ -100,23 +103,26 @@ print_badges("content/manipulation/04c_API_TP.qmd", correction=True)
## Partie 2: visualiser les données
+* [Exercices graphiques classiques](../visualisation/matplotlib.qmd)
::: {.cell .markdown}
```{python}
-#| echo: false
+#| echo: true
#| output: 'asis'
#| include: true
-#| eval: false
+#| eval: true
print_badges("content/visualisation/matplotlib.qmd", correction=True)
```
:::
+* [Exercices sur la cartographie](../visualisation/maps.qmd)
+
::: {.cell .markdown}
```{python}
#| echo: false
#| output: 'asis'
#| include: true
-#| eval: false
+#| eval: true
print_badges("content/visualisation/maps.qmd", correction=True)
```
:::
@@ -124,32 +130,41 @@ print_badges("content/visualisation/maps.qmd", correction=True)
## Partie 3: modéliser
+* [Exercices sur le _preprocessing_](../modelisation/0_preprocessing.qmd)
+
+
::: {.cell .markdown}
```{python}
#| echo: false
#| output: 'asis'
#| include: true
-#| eval: false
+#| eval: true
print_badges("content/modelisation/0_preprocessing.qmd", correction=True)
```
:::
+* [Exercices sur l'évaluation des modèles](../modelisation/1_modelevaluation.qmd)
+
+
::: {.cell .markdown}
```{python}
#| echo: false
#| output: 'asis'
#| include: true
-#| eval: false
+#| eval: true
print_badges("content/modelisation/1_modelevaluation.qmd", correction=True)
```
:::
+* [Exercices sur la classification](../modelisation/2_SVM.qmd)
+
+
::: {.cell .markdown}
```{python}
#| echo: false
#| output: 'asis'
#| include: true
-#| eval: false
+#| eval: true
print_badges("content/modelisation/2_SVM.qmd", correction=True)
```
:::
diff --git a/content/modelisation/0_preprocessing.qmd b/content/modelisation/0_preprocessing.qmd
index 037abfa32..777c76a21 100644
--- a/content/modelisation/0_preprocessing.qmd
+++ b/content/modelisation/0_preprocessing.qmd
@@ -181,6 +181,7 @@ par comté x année avec en colonnes les résultats de chaque candidat dans cet
Si vous ne faites pas l'exercice 1, pensez à charger les données en executant la fonction `get_data.py` :
+::: {.python}
```{python}
#| echo: true
#| output: false
@@ -194,6 +195,8 @@ open('getdata.py', 'wb').write(r.content)
import getdata
votes = getdata.create_votes_dataframes()
```
+:::
+
Ce code introduit une base nommée `votes` dans l'environnement. Il s'agit d'une
base rassemblant les différentes sources. Elle a l'aspect
@@ -346,6 +349,9 @@ ainsi que les relations entre les variables explicatives.
@@ -201,7 +181,7 @@ fois on va chercher à modéliser directement le score des Républicains.
1. A partir de quelques variables, par exemple, *'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"*, expliquer la variable `per_gop` à l'aide d'un échantillon d'entraînement `X_train` constitué au préalable.
-:warning: utiliser la variable `Median_Household_Income_2019`
+⚠️ Utiliser la variable `Median_Household_Income_2019`
en `log` sinon son échelle risque d'écraser tout effet.
2. Afficher les valeurs des coefficients, constante comprise
@@ -219,7 +199,7 @@ un problème de spécification ?
:::
```{python}
-#| include: false
+#| output: false
# 1. Régression linéaire de per_gop sur différentes variables explicatives
xvars = ['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"]
@@ -242,8 +222,7 @@ y_pred = ols.predict(X_test)
```{python}
-#| include: false
-#| echo: false
+#| output: false
#2. Afficher les valeurs des coefficients
print(ols.intercept_, ols.coef_)
@@ -251,8 +230,7 @@ print(ols.intercept_, ols.coef_)
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 3. Evaluer la pertinence du modèle
@@ -267,8 +245,7 @@ print('Coefficient of determination: %.2f'
```
```{python}
-#| include: false
-#| echo: false
+#| output: false
#4. Nuage de points des valeurs observées
tempdf = pd.DataFrame({"prediction": y_pred, "observed": y_test,
@@ -284,18 +261,19 @@ g.axhline(0, color = "red")
# donc d'un problème de spécification.
```
+Voici le nuage de points de nos erreurs:
+
```{python}
-#| include: false
g.figure.get_figure()
```
```{python}
-#| include: false
+#| output: false
g.figure.get_figure().savefig("featured_regression.png")
```
-
+Clairement, le modèle présente un problème de spécification.
```{python}
@@ -317,7 +295,8 @@ L'objectif est toujours d'expliquer le score des Républicains en fonction de qu
variables.
-1. A partir de quelques variables, par exemple, *'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"*, expliquer la variable `per_gop`. :warning: utiliser la variable `Median_Household_Income_2019`
+1. A partir de quelques variables, par exemple, *'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"*, expliquer la variable `per_gop`.
+⚠️ utiliser la variable `Median_Household_Income_2019`
en `log` sinon son échelle risque d'écraser tout effet.
2. Afficher un tableau de régression.
3. Evaluer la pertinence du modèle avec le R^2.
@@ -330,8 +309,7 @@ en `log` sinon son échelle risque d'écraser tout effet.
:::
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 1. Régression linéaire de per_gop sur différentes variables explicatives
xvars = ['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"]
@@ -349,8 +327,7 @@ results = sm.OLS(df2[['per_gop']], X).fit()
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 2. Afficher le tableau de régression
print(results.summary())
@@ -359,8 +336,7 @@ print(results.summary())
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 3. Calcul du R^2
print("R2: ", results.rsquared)
@@ -369,8 +345,7 @@ print("R2: ", results.rsquared)
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 4. Nouvelle régression avec l'API formula
results = smf.ols('per_gop ~ Unemployment_rate_2019 + I(Unemployment_rate_2019**2) + np.log(Median_Household_Income_2019)', data=df2).fit()
@@ -415,11 +390,11 @@ englober ces modèles.
### La régression logistique
Ce modèle s'applique à une distribution binaire.
-Dans ce cas, $\mathbb{E}\_{\theta}(Y|X) = \mathbb{P}\_{\theta}(Y = 1|X)$.
+Dans ce cas, $\mathbb{E}_{\theta} (Y|X) = \mathbb{P}_{\theta} (Y = 1|X)$.
La régression logistique peut être vue comme un modèle linéaire en probabilité :
$$
-\text{logit}\bigg(\mathbb{E}\_{\theta}(Y|X)\bigg) = \text{logit}\bigg(\mathbb{P}\_{\theta}(Y = 1|X)\bigg) = X\beta
+\text{logit}\bigg(\mathbb{E}_{\theta}(Y|X)\bigg) = \text{logit}\bigg(\mathbb{P}_{\theta}(Y = 1|X)\bigg) = X\beta
$$
La fonction $\text{logit}$ est $]0,1[ \to \mathbb{R}: p \mapsto \log(\frac{p}{1-p})$.
@@ -483,8 +458,7 @@ une mesure de qualité du modèle.
:::
```{python}
-#| include: false
-#| echo: false
+#| output: false
#1. Modèle logit avec les mêmes variables que précédemment
xvars = ['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"]
@@ -503,15 +477,13 @@ X_train, X_test, y_train, y_test = train_test_split(
clf = LogisticRegression().fit(X_train, y_train)
y_pred = clf.predict(X_test)
-#y_pred[:10]
+
print(clf.intercept_, clf.coef_)
-# Lino : KA a fait un début de corrigé rapidos : à vérifier
```
```{python}
-#| include: false
-#| echo: false
+#| output: false
from sklearn.metrics import ConfusionMatrixDisplay
@@ -523,19 +495,16 @@ sc_f1 = sklearn.metrics.f1_score(y_pred, y_test)
sc_recall = sklearn.metrics.recall_score(y_pred, y_test)
sc_precision = sklearn.metrics.precision_score(y_pred, y_test)
-#print(sc_accuracy)
-#print(sc_f1)
-#print(sc_recall)
-#print(sc_precision)
-
-# Lino : KA a fait un début de corrigé rapidos : à vérifier
+print(sc_accuracy)
+print(sc_f1)
+print(sc_recall)
+print(sc_precision)
```
```{python}
-#| include: false
-#| echo: false
+#| output: false
#3. Supprimer la régularisation
clf2 = LogisticRegression(penalty='none').fit(X_train, y_train)
@@ -543,7 +512,6 @@ y_pred2 = clf.predict(X_test)
print(clf2.intercept_, clf2.coef_)
# Les coefficients sont complètement différents
-# Lino : KA a fait un début de corrigé rapidos : à vérifier
```
@@ -570,8 +538,7 @@ de gagner.
```{python}
-#| include: false
-#| echo: false
+#| output: false
#1. Modèle logit avec les mêmes variables que précédemment
xvars = [
@@ -593,8 +560,7 @@ print(mylogit.summary())
```{python}
-#| include: false
-#| echo: false
+#| output: false
#2. Faire un test de ratio de vraisemblance
logit_h0 = smf.logit(
@@ -636,13 +602,18 @@ $$
```
:::
-
-
-
+## Pour aller plus loin
-
+Ce chapitre n'évoque les enjeux de la régression
+que de manière très introductive. Pour compléter ceci,
+il est recommandé d'explorer les champs suivants:
-
+- Les modèles linéaires généralisés pour découvrir la régression
+avec des hypothèses plus générales que celles que nous avons posées
+jusqu'à présent ;
+- Les autres modèles de régression de _machine learning_ comme les forêts
+aléatoires ;
+- Les tests d'hypothèses pour aller plus loin sur ces questions que notre
+test de ratio de vraisemblance.
-
diff --git a/content/modelisation/4_featureselection.qmd b/content/modelisation/4_featureselection.qmd
index 3ee5c90fd..ab78591b9 100644
--- a/content/modelisation/4_featureselection.qmd
+++ b/content/modelisation/4_featureselection.qmd
@@ -28,6 +28,7 @@ description: |
pertinent dilué au milieu du bruit lorsqu'on a beaucoup d'information à
traiter.
image: featured_selection.png
+echo: false
---
@@ -60,13 +61,10 @@ Le code
est disponible [sur Github](https://github.com/linogaliana/python-datascientist/blob/master/content/modelisation/get_data.py).
+::: {.python}
```{python}
#| echo: true
-#| message: false
-#| warning: false
-
-#!pip install --upgrade xlrd #colab bug verson xlrd
-#!pip install geopandas
+#| output: false
import requests
@@ -77,6 +75,8 @@ open('getdata.py', 'wb').write(r.content)
import getdata
votes = getdata.create_votes_dataframes()
```
+:::
+
Jusqu'à présent, nous avons supposé que les variables utiles à la prévision du
vote Républicain étaient connues du modélisateur. Nous n'avons ainsi exploité qu'une partie
@@ -144,6 +144,7 @@ celles qui concernent les votes des partis concurrents (forcément très
corrélés au vote Républicain...) :
```{python}
+#| echo: true
df2 = votes.loc[:,~votes.columns.str.endswith(
('_democrat','_green','_other', 'per_point_diff', 'per_dem')
)]
@@ -153,7 +154,7 @@ Nous allons utiliser par la suite les fonctions ou
packages suivants :
```{python}
-# packages utiles
+#| echo: true
import numpy as np
from sklearn.svm import LinearSVC
from sklearn.feature_selection import SelectFromModel
@@ -196,8 +197,7 @@ varie (parcourir $\alpha \in [0.001,0.01,0.02,0.025,0.05,0.1,0.25,0.5,0.8,1.0]$
```{python}
-#| include: false
-#| echo: false
+#| output: false
#1. Garder uniquement les variables numériques et standardiser.
df2 = votes.loc[:,~votes.columns.str.endswith(('_democrat','_green','_other', 'per_point_diff', 'per_dem'))]
@@ -212,8 +212,7 @@ df2[col_names] = features
```
```{python}
-#| include: false
-#| echo: false
+#| output: false
#2. Echantillon d'entraînement et échantillon test
X_train, X_test, y_train, y_test = train_test_split(
@@ -228,8 +227,6 @@ A l'issue de la question 3,
les variables sélectionnées sont :
```{python}
-#| include: true
-#| echo: false
#3. Estimer un modèle LASSO et afficher les valeurs des coefficients
lasso1 = Lasso(fit_intercept=True, alpha = 0.1).fit(X_train, y_train)
@@ -248,9 +245,6 @@ Par ailleurs, on sélectionne des variables redondantes. Une phase plus approfon
```{python}
-#| include: false
-#| echo: false
-
#4. Corrélations entre les variables sélectionnées
corr = df2[features_selec].corr()
@@ -261,8 +255,7 @@ p
```{python}
-#| include: false
-#| echo: false
+#| output: false
#5. Faire une régression linéaire parcimonieuse et non parcimonieuse
@@ -286,27 +279,25 @@ print("rsq_nonparci : ", rsq_nonparci)
```
```{python}
-#| include: false
-#| echo: false
-
+#| output: false
+#| eval: false
### Autres exemples Lino :
-#import statsmodels.api as sm
-#import statsmodels.formula.api as smf
-#print(smf.ols("per_gop ~ share_2016_republican", data = #df2).fit().summary())
+import statsmodels.api as sm
+import statsmodels.formula.api as smf
+print(smf.ols("per_gop ~ share_2016_republican", data = df2).fit().summary())
+
# Performance du modèle déjà bonne avec une variable explicative
# Par la suite : se contenter de variables moins bonnes mais qui
# présentent un intérêt pour la sélection
-#df2 = votes.loc[:,~votes.columns.str.endswith(("_republican",'_democrat','_green','_other', 'per_point_diff', 'per_dem'))]
-# df2 = df[[c for c in df.columns if c not in cols_to_exclude] + ['rep16_frac']]
-
+df2 = votes.loc[:,~votes.columns.str.endswith(("_republican",'_democrat','_green','_other', 'per_point_diff', 'per_dem'))]
+df2 = df[[c for c in df.columns if c not in cols_to_exclude] + ['rep16_frac']]
```
```{python}
-#| include: false
-#| echo: false
+#| output: false
#6. Utilisation de lasso_path
my_alphas = np.array([0.001,0.01,0.02,0.025,0.05,0.1,0.25,0.5,0.8,1.0])
@@ -325,7 +316,6 @@ p.set(title = r"Number variables and regularization parameter ($\alpha$)", xlabe
```{python}
#| echo: false
-
p.figure.get_figure()
```
@@ -335,7 +325,7 @@ On voit que plus $\alpha$ est élevé, moins le modèle sélectionne de variable
```{python}
-#| include: false
+#| output: false
p.figure.get_figure().savefig("featured_selection.png")
```
@@ -348,6 +338,7 @@ prédire le résultat Républicain :
```{python}
#| echo: true
+#| output: false
from sklearn.linear_model import LassoCV
df3 = df2.select_dtypes(include=np.number)
diff --git a/content/modelisation/5_clustering.qmd b/content/modelisation/5_clustering.qmd
index db70bcb45..7ee9ec5c2 100644
--- a/content/modelisation/5_clustering.qmd
+++ b/content/modelisation/5_clustering.qmd
@@ -1,7 +1,6 @@
---
title: "Clustering"
date: 2023-07-20T13:00:00Z
-draft: false
weight: 60
slug: clustering
type: book
@@ -11,7 +10,7 @@ tags:
- US elections
- clustering
- Kmeans
- - Modelisatoin
+ - Modelisation
- Exercice
categories:
- Modélisation
@@ -26,6 +25,8 @@ description: |
au monde réel sont nombreuses, notamment dans le domaine de la
segmentation tarifaire.
image: featured_clustering.png
+bibliography: ../../reference.bib
+echo: false
---
@@ -55,13 +56,10 @@ Le code
est disponible [sur Github](https://github.com/linogaliana/python-datascientist/blob/master/content/modelisation/get_data.py).
+::: {.python}
```{python}
#| echo: true
-#| message: false
-#| warning: false
-
-#!pip install --upgrade xlrd #colab bug verson xlrd
-#!pip install geopandas
+#| output: false
import requests
@@ -72,6 +70,7 @@ open('getdata.py', 'wb').write(r.content)
import getdata
votes = getdata.create_votes_dataframes()
```
+:::
## Introduction sur le *clustering*
@@ -81,13 +80,26 @@ connaissions la vraie valeur de la variable à expliquer/prédire (`y`). Ce n'es
l'apprentissage non supervisé.
Le *clustering* est un champ d'application de l'apprentissage non-supervisé.
-Il s'agit d'exploiter l'information disponible pour regrouper des observations
-qui se ressemblent.
+Il s'agit d'exploiter l'information disponible en regroupant des observations
+qui se ressemblent à partir de leurs caractéristiques (_features_) communes.
+
+::: {.cell .markdown}
+
+
+
+Rappel: l'arbre de décision des méthodes `Scikit`
-L'objectif est de créer des clusters d'observations pour lesquels :
+
-* 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 les uns des autres (variance inter-cluster maximale)
+![](https://upload.wikimedia.org/wikipedia/commons/a/a4/Scikit-learn_machine_learning_decision_tree.png)
+
+
+:::
+
+L'objectif est de créer des groupes d'observations (_clusters_) pour lesquels :
+
+* 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 les uns des autres (variance inter-cluster 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
@@ -98,15 +110,21 @@ Ces méthodes ont également un intérêt en économie et sciences sociales parc
de regrouper des observations sans *a priori* et ainsi interpréter une variable
d'intérêt à l'aune de ces résultats. Cette [publication sur la ségrégation spatiale utilisant des données de téléphonie mobile](https://www.insee.fr/fr/statistiques/4925200)
utilise par exemple cette approche.
+Dans certaines bases de données, on peut se retrouver avec quelques exemples labellisés mais la plupart sont
+non labellisés. Les labels ont par exemple été faits manuellement par des experts.
+
+
+::: {.cell .markdown}
+```{=html}
+
+
Note
+```
Les méthodes de *clustering* peuvent aussi intervenir en amont d'un problème de classification (dans des
problèmes d'apprentissage semi-supervisé).
-Le manuel *Hands-on machine learning with scikit-learn, Keras et TensorFlow* présente dans le
+Le manuel *Hands-on machine learning with scikit-learn, Keras et TensorFlow* [@geron2022hands] 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 sont
-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.
@@ -114,6 +132,11 @@ 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.
+```{=html}
+
+```
+:::
+
Les méthodes de *clustering* sont nombreuses.
Nous allons nous pencher sur la plus intuitive : les *k-means*.
@@ -146,9 +169,12 @@ avec $\mu_i$ la moyenne des $x_i$ dans l'ensemble de points $S_i$
```
:::
+Dans ce chapitre nous allons principalement
+utiliser `Scikit`. Voici néanmoins une proposition
+d'imports de packages, pour gagner du temps.
```{python}
-# packages utiles
+#| echo: true
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
@@ -179,8 +205,7 @@ en fonction du label obtenu.
:::
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 1. Chargement de la base restreinte.
xvars = ['Unemployment_rate_2019', 'Median_Household_Income_2019',
@@ -193,8 +218,7 @@ df2 = votes[xvars + ["per_gop"]].dropna()
```{python}
-#| include: false
-#| echo: false
+#| output: false
#2. kmeans avec k=4
model = KMeans(n_clusters=4)
@@ -204,8 +228,7 @@ model.fit(df2[xvars])
```{python}
-#| include: false
-#| echo: false
+#| output: false
#3. Création de la variable label dans votes
votes['label'] = model.labels_
@@ -218,8 +241,7 @@ la suivante :
```{python}
-#| include: false
-#| echo: false
+#| output: false
#4. Carte de la typologie
p = votes.plot(column = "label", cmap = "inferno")
@@ -227,17 +249,15 @@ p.set_axis_off()
```
```{python}
-#| echo: false
p.get_figure()
```
Le nuage de point de la question 5, permettant de représenter
-la relation entre `Median_Household_Incomme_2019`
+la relation entre `Median_Household_Income_2019`
et `Unemployment_rate_2019`, aura l'aspect suivant :
```{python}
-#| include: false
-#| echo: false
+#| output: false
#5. Nuage de points de 2 variables et coloration selon le label
plt.figure()
@@ -255,15 +275,14 @@ p.figure.get_figure()
```
```{python}
-#| include: false
+#| output: false
p.figure.get_figure().savefig("featured_clustering.png")
```
Enfin, l'histogramme des votes pour chaque cluster est :
```{python}
-#| include: false
-#| echo: false
+#| output: false
# 6. Distribution du vote selon chaque cluster
plt.figure()
@@ -284,13 +303,14 @@ p2.figure.get_figure()
```
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 ++ (cf. paramètre `init`). Cela signifie que
l'initialisation des centroïdes est faite de manière intelligente pour que les centroïdes initiaux soient choisis
afin de ne pas être trop proches.
- l'algorithme va être démarré avec `n_init` centroïdes différents et le modèle va choisir la meilleure initialisation
-en fonction de l'**inertia** du modèle, par défaut égale à 10.
+en fonction de l'_inertie_ du modèle, par défaut égale à 10.
-Le modèle renvoie les `cluster_centers_`, les labels `labels_`, l'inertia `inertia_` et le nombre d'itérations
+Le modèle renvoie les `cluster_centers_`, les labels `labels_`, l'inertie `inertia_` et le nombre d'itérations
`n_iter_`.
```{=html}
@@ -344,6 +364,7 @@ facilement la performance en *clustering*.
```{python}
#| echo: true
+#| output: false
from sklearn.cluster import KMeans
from yellowbrick.cluster import KElbowVisualizer
@@ -390,7 +411,7 @@ for i in [3, 4, 6, 10]:
```
```{python}
-#| include: false
+#| output: false
fig.savefig("silhouette-yellowbrick.png")
```
diff --git a/reference.bib b/reference.bib
index 905e7306c..1e71cf483 100644
--- a/reference.bib
+++ b/reference.bib
@@ -6,6 +6,14 @@ @book{Turrell2021
url = "https://aeturrell.github.io/coding-for-economists"
}
+@book{geron2022hands,
+ title={Hands-on machine learning with Scikit-Learn, Keras, and TensorFlow},
+ author={G{\'e}ron, Aur{\'e}lien},
+ year={2022},
+ publisher={" O'Reilly Media, Inc."}
+}
+
+
@article{breiman2001random,
title={Random forests},
author={Breiman, Leo},