Skip to content

Commit a5ecaed

Browse files
authored
Traduction du chapitre modélisation (#582)
* commence le chapitre * continue * statsmodels * summary tables * fin de la traduction * traduction chapitre regression * traduction feature selection
1 parent 240d69a commit a5ecaed

File tree

4 files changed

+857
-140
lines changed

4 files changed

+857
-140
lines changed

_quarto-en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ project:
2020
- content/modelisation/index.qmd
2121
- content/modelisation/0_preprocessing.qmd
2222
- content/modelisation/1_modelevaluation.qmd
23+
- content/modelisation/2_classification.qmd
24+
- content/modelisation/3_regression.qmd
2325

2426

2527
website:

content/modelisation/2_classification.qmd

Lines changed: 189 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
---
22
title: "Découverte de la classification avec la technique des SVM"
3+
title-en: "Discovering classification with the SVM technique"
34
categories:
45
- Modélisation
56
description: |
6-
La classification permet d'attribuer une classe d'appartenance (_label_
7-
dans la terminologie du _machine learning_)
8-
discrète à des données à partir de certaines variables explicatives
9-
(_features_ dans la même terminologie).
10-
Les algorithmes de classification sont nombreux. L'un des plus intuitifs et
11-
les plus fréquemment rencontrés sont les _SVM_ (*Support Vector Machine*).
12-
Ce chapitre illustre les enjeux de la classification à partir de
13-
ce modèle sur les données de vote aux élections présidentielles US de 2020.
7+
La classification permet d'attribuer une classe d'appartenance (_label_ dans la terminologie du _machine learning_) discrète à des données à partir de certaines variables explicatives (_features_ dans la même terminologie). Les algorithmes de classification sont nombreux. L'un des plus intuitifs et les plus fréquemment rencontrés sont les _SVM_ (*Support Vector Machine*). Ce chapitre illustre les enjeux de la classification à partir de ce modèle sur les données de vote aux élections présidentielles US de 2020.
8+
description-en: |
9+
Classification enables us to assign a discrete membership class (_label_ in machine learning terminology) to data, based on certain explanatory variables (_features_ in the same terminology). Classification algorithms are numerous. One of the most intuitive and frequently encountered is _SVM_ (*Support Vector Machine*). This chapter illustrates the challenges of using this model to classify model on voting data for the 2020 US presidential elections.
1410
echo: false
1511
---
1612

@@ -19,21 +15,31 @@ echo: false
1915
printMessage="true"
2016
>}}
2117
18+
::: {.content-visible when-profile="fr"}
2219
# Introduction
2320

24-
Ce chapitre vise à présenter de manière très succincte le principe de l'entraînement de modèles dans un cadre de classification. L'objectif est d'illustrer la démarche à partir d'un algorithme dont le principe est assez intuitif. Il s'agit d'illustrer quelques uns des concepts évoqués dans les chapitres précédents, notamment ceux relatifs à l'entraînement d'un modèle. D'autres cours de votre scolarité vous permettront de découvrir d'autres algorithmes de classification et les limites de chaque technique.
25-
21+
Ce chapitre vise à présenter de manière très succincte le principe de l'entraînement de modèles dans un cadre de classification. L'objectif est d'illustrer la démarche à partir d'un algorithme dont le principe est assez intuitif. Il s'agit d'illustrer quelques uns des concepts évoqués dans les chapitres précédents, notamment ceux relatifs à l'entraînement d'un modèle. D'autres cours de votre scolarité vous permettront de découvrir d'autres algorithmes de classification et les limites de chaque technique.
2622

2723
## Données
24+
:::
25+
26+
::: {.content-visible when-profile="en"}
27+
# Introduction
28+
29+
This chapter aims to very briefly introduce the principle of training models in a classification context. The goal is to illustrate the process using an algorithm with an intuitive principle. It seeks to demonstrate some of the concepts discussed in previous chapters, particularly those related to model training. Other courses in your curriculum will allow you to explore additional classification algorithms and the limitations of each technique.
30+
31+
## Data
32+
:::
2833

2934

3035
{{< include _import_data_ml.qmd >}}
3136

37+
:::: {.content-visible when-profile="fr"}
3238
## La méthode des _SVM_ (_Support Vector Machines_)
3339

3440
Les SVM (_Support Vector Machines_) font partie de la boîte à outil traditionnelle des _data scientists_.
3541
Le principe de cette technique est relativement intuitif grâce à son interprétation géométrique.
36-
Il s'agit de trouver une droite, avec des marges (les supports) qui discrimine au mieux le nuage de point de nos données.
42+
Il s'agit de trouver une droite, avec des marges (les supports) qui discrimine au mieux le nuage de points de nos données.
3743
Bien-sûr, dans la vraie vie, il est rare d'avoir des nuages de points bien ordonnés pour pouvoir les séparer par une droite. Mais une projection adéquate (un noyau ou _kernel_) peut arranger des données pour permettre de discriminer les données.
3844

3945
```{=html}
@@ -61,12 +67,52 @@ des _labels_ homogènes.
6167
On peut, sans perdre de généralité,
6268
supposer que le problème consiste à supposer l'existence d'une loi de probabilité $\mathbb{P}(x,y)$ ($\mathbb{P} \to \{-1,1\}$) qui est inconnue. Le problème de discrimination
6369
vise à construire un estimateur de la fonction de décision idéale qui minimise la probabilité d'erreur. Autrement dit
70+
:::
71+
72+
::::
73+
74+
:::: {.content-visible when-profile="en"}
75+
## The SVM Method (_Support Vector Machines_)
76+
77+
SVM (_Support Vector Machines_) is part of the traditional toolkit for _data scientists_.
78+
The principle of this technique is relatively intuitive thanks to its geometric interpretation.
79+
The goal is to find a line, with margins (supports), that best separates the point cloud in our data.
80+
Of course, in real life, it is rare to have well-organized point clouds that can be separated by a line. However, an appropriate projection (a kernel) can transform the data to enable separation.
81+
82+
```{=html}
83+
<img src="https://scikit-learn.org/stable/_images/sphx_glr_plot_iris_svc_001.png" alt="Iris SVC Plot" width="300px">
84+
```
85+
86+
::: {.tip}
87+
## Mathematical formalization
88+
89+
SVM is one of the most intuitive _machine learning_ methods
90+
due to its simple geometric interpretation. It is also
91+
one of the least complex _machine learning_ algorithms in terms of formalization
92+
for practitioners familiar with traditional statistics. This note provides an overview, though it is not essential for understanding this chapter.
93+
In _machine learning_, more than the mathematical details, the key is to build intuitions.
94+
95+
The goal of SVM, let us recall, is to find a hyperplane that
96+
best separates the different classes. For example, in a two-dimensional space,
97+
it aims to find a line with margins that best divides the space into regions
98+
with homogeneous _labels_.
99+
100+
Without loss of generality, we can assume the problem involves a probability distribution $\mathbb{P}(x,y)$ ($\mathbb{P} \to \{-1,1\}$) that is unknown. The goal of classification is to build an estimator of the ideal decision function that minimizes the probability of error. In other words
101+
:::
102+
64103

65104
$$
66105
\theta = \arg\min_\Theta \mathbb{P}(h_\theta(X) \neq y |x)
67106
$$
68107

108+
::: {.content-visible when-profile="fr"}
69109
Les SVM les plus simples sont les SVM linéaires. Dans ce cas, on suppose qu'il existe un séparateur linéaire qui permet d'associer chaque classe à son signe:
110+
:::
111+
112+
::: {.content-visible when-profile="en"}
113+
The simplest SVMs are linear SVMs. In this case, it is assumed that a linear separator exists that can assign each class based on its sign:
114+
:::
115+
70116

71117
$$
72118
h_\theta(x) = \text{signe}(f_\theta(x)) ; \text{ avec } f_\theta(x) = \theta^T x + b
@@ -77,20 +123,34 @@ avec $\theta \in \mathbb{R}^p$ et $w \in \mathbb{R}$.
77123
<img src="https://upload.wikimedia.org/wikipedia/commons/7/72/SVM_margin.png" alt="Les SVM dans le cas linéaire" style="width: 40%;">
78124
```
79125

80-
Lorsque des observations sont linéairement séparables,
81-
il existe une infinité de frontières de décision linéaire séparant les deux classes. Le _"meilleur"_ choix est de prendre la marge maximale permettant de séparer les données. La distance entre les deux marges est $\frac{2}{||\theta||}$. Donc maximiser cette distance entre deux hyperplans revient à minimiser $||\theta||^2$ sous la contrainte $y_i(\theta^Tx_i + b) \geq 1$.
126+
::: {.content-visible when-profile="fr"}
127+
Lorsque des observations sont linéairement séparables, il existe une infinité de frontières de décision linéaire séparant les deux classes. Le _"meilleur"_ choix est de prendre la marge maximale permettant de séparer les données. La distance entre les deux marges est $\frac{2}{||\theta||}$. Donc maximiser cette distance entre deux hyperplans revient à minimiser $||\theta||^2$ sous la contrainte $y_i(\theta^Tx_i + b) \geq 1$.
82128

83129
Dans le cas non linéairement séparable, la *hinge loss* $\max\big(0,y_i(\theta^Tx_i + b)\big)$ permet de linéariser la fonction de perte, ce qui donne le programme d'optimisation suivant :
130+
:::
131+
132+
::: {.content-visible when-profile="en"}
133+
When observations are linearly separable, there is an infinite number of linear decision boundaries separating the two classes. The _"best"_ choice is to select the maximum margin that separates the data. The distance between the two margins is $\frac{2}{||\theta||}$. Thus, maximizing this distance between two hyperplanes is equivalent to minimizing $||\theta||^2$ under the constraint $y_i(\theta^Tx_i + b) \geq 1$.
134+
135+
In the non-linearly separable case, the *hinge loss* $\max\big(0,y_i(\theta^Tx_i + b)\big)$ allows for linearizing the loss function, resulting in the following optimization problem:
136+
:::
84137

85138
$$
86139
\frac{1}{n} \sum_{i=1}^n \max\big(0,y_i(\theta^Tx_i + b)\big) + \lambda ||\theta||^2
87140
$$
88141

142+
::: {.content-visible when-profile="fr"}
89143
La généralisation au cas non linéaire implique d'introduire des noyaux transformant l'espace de coordonnées des observations.
144+
:::
90145

146+
::: {.content-visible when-profile="en"}
147+
Generalization to the non-linear case involves introducing kernels that transform the coordinate space of the observations.
91148
:::
92149

150+
::::
151+
93152

153+
::: {.content-visible when-profile="fr"}
94154
# Application
95155

96156
Pour appliquer un modèle de classification, il nous faut
@@ -101,6 +161,16 @@ défaite d'un des partis.
101161
Même si les Républicains ont perdu en 2020, ils l'ont emporté
102162
dans plus de comtés (moins peuplés). Nous allons considérer
103163
que la victoire des Républicains est notre _label_ 1 et la défaite _0_.
164+
:::
165+
166+
::: {.content-visible when-profile="en"}
167+
# Application
168+
169+
To apply a classification model, we need to find a dichotomous variable. The natural choice is to use the dichotomous variable of a party's victory or defeat.
170+
171+
Even though the Republicans lost in 2020, they won in more counties (less populated ones). We will consider a Republican victory as our _label_ 1 and a defeat as _0_.
172+
:::
173+
104174

105175
```{python}
106176
#| echo: true
@@ -111,7 +181,10 @@ from sklearn.model_selection import cross_val_score
111181
import matplotlib.pyplot as plt
112182
```
113183

114-
::: {.exercise}
184+
185+
::: {.content-visible when-profile="fr"}
186+
187+
:::: {.exercise}
115188
## Exercice 1 : Premier algorithme de classification
116189

117190
1. Créer une variable *dummy* appelée `y` dont la valeur vaut 1 quand les républicains l'emportent.
@@ -133,7 +206,48 @@ créer des échantillons de test (20 % des observations) et d'estimation (80 %)
133206
6. Changer de variables *x*. Utiliser uniquement le résultat passé du vote démocrate (année 2016) et le revenu. Les variables en question sont `share_2016_republican` et `Median_Household_Income_2019`. Regarder les résultats, notamment la matrice de confusion.
134207

135208
7. [OPTIONNEL] Faire une 5-fold validation croisée pour déterminer le paramètre *C* idéal.
209+
::::
210+
211+
:::
212+
213+
214+
:::: {.content-visible when-profile="en"}
215+
::: {.exercise}
216+
217+
## Exercise 1: First classification algorithm
218+
219+
1. Create a *dummy* variable called `y` with a value of 1 when the Republicans win.
220+
2. Using the ready-to-use function `train_test_split` from the `sklearn.model_selection` library,
221+
create test samples (20% of the observations) and training samples (80%) with the following *features*:
222+
223+
```python
224+
vars = [
225+
"Unemployment_rate_2019", "Median_Household_Income_2019",
226+
"Percent of adults with less than a high school diploma, 2015-19",
227+
"Percent of adults with a bachelor's degree or higher, 2015-19"
228+
]
229+
```
230+
231+
and use the variable `y` as the *label*.
232+
233+
*Note: You may encounter the following warning:*
234+
235+
> A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel()
236+
237+
*Note: To avoid this warning every time you train your model, you can use `DataFrame[['y']].values.ravel()` instead of `DataFrame[['y']]` when preparing your samples.*
238+
239+
3. Train an SVM classifier with a regularization parameter `C = 1`. Examine the following performance metrics: `accuracy`, `f1`, `recall`, and `precision`.
240+
241+
4. Check the confusion matrix: despite seemingly reasonable scores, you should notice a significant issue.
242+
243+
5. Repeat the previous steps using normalized variables. Are the results different?
244+
245+
6. Change the *x* variables. Use only the previous Democratic vote result (2016) and income. The variables in question are `share_2016_republican` and `Median_Household_Income_2019`. Examine the results, particularly the confusion matrix.
246+
247+
7. [OPTIONAL] Perform 5-fold cross-validation to determine the ideal *C* parameter.
248+
136249
:::
250+
::::
137251

138252

139253
```{python}
@@ -144,7 +258,11 @@ votes['y'] = (votes['votes_gop'] > votes['votes_dem']).astype(int)
144258

145259
```{python}
146260
#2. Création des échantillons d'entraînement et de validation
147-
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"]
261+
xvars = [
262+
'Unemployment_rate_2019', 'Median_Household_Income_2019',
263+
'Percent of adults with less than a high school diploma, 2015-19',
264+
"Percent of adults with a bachelor's degree or higher, 2015-19"
265+
]
148266
149267
df = votes.loc[:, ["y"] + xvars]
150268
@@ -154,13 +272,25 @@ X_train, X_test, y_train, y_test = train_test_split(
154272
)
155273
```
156274

275+
::: {.content-visible when-profile="fr"}
157276
On obtient donc un ensemble de _features_ d'entraînement ayant cette forme:
277+
:::
278+
279+
::: {.content-visible when-profile="en"}
280+
We thus obtain a set of training _features_ with the following structure:
281+
:::
158282

159283
```{python}
160284
X_train.head()
161285
```
162286

287+
::: {.content-visible when-profile="fr"}
163288
Et les _labels_ associés sont les suivants:
289+
:::
290+
291+
::: {.content-visible when-profile="en"}
292+
And the associated _labels_ are as follows:
293+
:::
164294

165295
```{python}
166296
y_test
@@ -179,11 +309,22 @@ sc_precision = sklearn.metrics.precision_score(y_pred, y_test)
179309
```
180310

181311
```{python}
182-
stats_perf = pd.DataFrame.from_dict({"Accuracy": [sc_accuracy], "Recall": [sc_recall],
183-
"Precision": [sc_precision], "F1": [sc_f1]}, orient = "index", columns = ["Score"])
312+
stats_perf = pd.DataFrame.from_dict(
313+
{
314+
"Accuracy": [sc_accuracy], "Recall": [sc_recall],
315+
"Precision": [sc_precision], "F1": [sc_f1]
316+
}, orient = "index", columns = ["Score"]
317+
)
184318
```
185319

186-
A l'issue de la question 3, notre classifieur manque totalement les labels 0, qui sont minoritaires. Parmi les raisons possibles: l'échelle des variables. Le revenu, notamment, a une distribution qui peut écraser celle des autres variables, dans un modèle linéaire. Il faut donc, a minima, standardiser les variables, ce qui est l'objet de la question 4
320+
321+
::: {.content-visible when-profile="fr"}
322+
A l'issue de la question 3, notre classifieur manque totalement les labels 0, qui sont minoritaires. Parmi les raisons possibles : l'échelle des variables. Le revenu, notamment, a une distribution qui peut écraser celle des autres variables, dans un modèle linéaire. Il faut donc, a minima, standardiser les variables, ce qui est l'objet de la question 4.
323+
:::
324+
325+
::: {.content-visible when-profile="en"}
326+
At the end of question 3, our classifier completely misses the 0 labels, which are in the minority. One possible reason is the scale of the variables. Income, in particular, has a distribution that can dominate the others in a linear model. Therefore, at a minimum, it is necessary to standardize the variables, which is the focus of question 4.
327+
:::
187328

188329

189330

@@ -201,15 +342,21 @@ disp.plot()
201342
plt.show()
202343
```
203344

204-
Standardiser les variables n'apporte finalement pas de gain:
345+
::: {.content-visible when-profile="fr"}
346+
Standardiser les variables n'apporte finalement pas de gain :
347+
:::
348+
349+
::: {.content-visible when-profile="en"}
350+
Standardizing the variables ultimately does not bring any improvement:
351+
:::
205352

206353
```{python}
207354
import sklearn.preprocessing as preprocessing
208355
209356
X = df.loc[:, xvars]
210357
y = df[['y']]
211-
scaler = preprocessing.StandardScaler().fit(X) #Ici on estime
212-
X = scaler.transform(X) #Ici on standardise
358+
scaler = preprocessing.StandardScaler().fit(X)
359+
X = scaler.transform(X)
213360
214361
X_train, X_test, y_train, y_test = train_test_split(
215362
X,
@@ -220,30 +367,39 @@ clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
220367
predictions = clf.predict(X_test)
221368
cm = sklearn.metrics.confusion_matrix(y_test, predictions, labels=clf.classes_)
222369
disp = sklearn.metrics.ConfusionMatrixDisplay(
223-
confusion_matrix=cm,
224-
display_labels=clf.classes_
225-
)
370+
confusion_matrix=cm,
371+
display_labels=clf.classes_
372+
)
226373
disp.plot()
227374
plt.show()
228375
```
229376

230-
Il faut donc aller plus loin : le problème ne vient pas de l'échelle mais du choix des variables. C'est pour cette raison que l'étape de sélection de variable est cruciale et qu'un chapitre y est consacré.
377+
::: {.content-visible when-profile="fr"}
378+
Il faut donc aller plus loin : le problème ne vient pas de l'échelle mais du choix des variables. C'est pour cette raison que l'étape de sélection de variables est cruciale et qu'un chapitre y est consacré.
231379

232-
A l'issue de la question 6,
233-
le nouveau classifieur avec devrait avoir les performances suivantes :
380+
À l'issue de la question 6, le nouveau classifieur devrait avoir les performances suivantes :
381+
:::
234382

235-
```{python}
236-
#| output: asis
383+
::: {.content-visible when-profile="en"}
384+
It is therefore necessary to go further: the problem does not lie in the scale but in the choice of variables. This is why the step of variable selection is crucial and why a chapter is dedicated to it.
237385

238-
out = pd.DataFrame.from_dict({"Accuracy": [sc_accuracy], "Recall": [sc_recall],
239-
"Precision": [sc_precision], "F1": [sc_f1]}, orient = "index", columns = ["Score"])
240-
```
386+
At the end of question 6, the new classifier should have the following performance:
387+
:::
241388

242389

390+
```{python}
391+
#| output: asis
243392
393+
out = pd.DataFrame.from_dict(
394+
{
395+
"Accuracy": [sc_accuracy], "Recall": [sc_recall],
396+
"Precision": [sc_precision], "F1": [sc_f1]
397+
}, orient = "index", columns = ["Score"]
398+
)
399+
```
244400

245401
```{python}
246-
# 6. Refaire les questions en changeant la variable X.
402+
# Question 6
247403
votes['y'] = (votes['votes_gop'] > votes['votes_dem']).astype(int)
248404
df = votes[["y", "share_2016_republican", 'Median_Household_Income_2019']]
249405
tempdf = df.dropna(how = "any")
@@ -266,19 +422,13 @@ sc_f1 = sklearn.metrics.f1_score(y_pred, y_test)
266422
sc_recall = sklearn.metrics.recall_score(y_pred, y_test)
267423
sc_precision = sklearn.metrics.precision_score(y_pred, y_test)
268424
269-
#print(sc_accuracy)
270-
#print(sc_f1)
271-
#print(sc_recall)
272-
#print(sc_precision)
273-
274425
predictions = clf.predict(X_test)
275426
cm = sklearn.metrics.confusion_matrix(y_test, predictions, labels=clf.classes_)
276427
disp = sklearn.metrics.ConfusionMatrixDisplay(
277428
confusion_matrix=cm,
278429
display_labels=clf.classes_
279430
)
280431
disp.plot()
281-
# On obtient un résultat beaucoup plus cohérent.
282432
283433
plt.savefig("confusion_matrix3.png")
284434
```

0 commit comments

Comments
 (0)