Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problème avec le notebook de classification #579

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 23 additions & 56 deletions content/modelisation/2_classification.qmd
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
---
title: "Classification: premier modèle avec les SVM"
weight: 30
slug: SVM
tags:
- scikit
- Machine Learning
Expand All @@ -22,7 +20,6 @@ description: |
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.
image: featured_svm.png
echo: false
---

Expand Down Expand Up @@ -51,7 +48,7 @@ Bien-sûr, dans la vraie vie, il est rare d'avoir des nuages de points bien ordo
![](https://scikit-learn.org/stable/_images/sphx_glr_plot_iris_svc_001.png)


::: {.tip collapse="true"}
::: {.tip}
## Formalisation mathématique

Les SVM sont l'une des méthodes de _machine learning_ les plus intuitives
Expand Down Expand Up @@ -100,7 +97,7 @@ La généralisation au cas non linéaire implique d'introduire des noyaux transf
:::


## Application
# Application

Pour appliquer un modèle de classification, il nous faut
trouver une variable dichotomique. Le choix naturel est
Expand All @@ -113,15 +110,13 @@ que la victoire des Républicains est notre _label_ 1 et la défaite _0_.

```{python}
#| echo: true
# packages utiles
from sklearn import svm
import sklearn.metrics
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
```

::: {.exercise}
## Exercice 1 : Premier algorithme de classification

1. Créer une variable *dummy* appelée `y` dont la valeur vaut 1 quand les républicains l'emportent.
Expand All @@ -144,7 +139,6 @@ créer des échantillons de test (20 % des observations) et d'estimation (80 %)

7. [OPTIONNEL] Faire une 5-fold validation croisée pour déterminer le paramètre *C* idéal.

:::


```{python}
Expand All @@ -163,12 +157,19 @@ X_train, X_test, y_train, y_test = train_test_split(
df[xvars],
df[['y']].values.ravel(), test_size=0.2, random_state=123
)
#X_train.head()
#y_test

```

On obtient donc un ensemble de _features_ d'entraînement ayant cette forme:

```{python}
X_train.head()
```

Et les _labels_ associés sont les suivants:

```{python}
y_test
```


```{python}
Expand All @@ -180,27 +181,19 @@ sc_accuracy = sklearn.metrics.accuracy_score(y_pred, y_test)
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)
```

A l'issue de la question 3,
le classifieur avec `C = 1`
devrait avoir les performances suivantes :

```{python}
#| output: asis
out = pd.DataFrame.from_dict({"Accuracy": [sc_accuracy], "Recall": [sc_recall],
stats_perf = pd.DataFrame.from_dict({"Accuracy": [sc_accuracy], "Recall": [sc_recall],
"Precision": [sc_precision], "F1": [sc_f1]}, orient = "index", columns = ["Score"])
print(out.to_markdown())
```

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



```{python}
#| output: false
import matplotlib.pyplot as plt

# 4. Matrice de confusion
predictions = clf.predict(X_test)
Expand All @@ -210,31 +203,17 @@ disp = sklearn.metrics.ConfusionMatrixDisplay(
display_labels=clf.classes_
)
disp.plot()

#Réponse : Notre classifieur manque totalement les labels 0, qui sont minoritaires.
#Une raison possible ? L'échelle des variables : le revenu a une
#distribution qui peut écraser celle des autres variables,
#dans un modèle linéaire. Il faut donc, a minima,
#standardiser les variables.

plt.savefig("confusion_matrix.png")
plt.show()
```

La matrice de confusion associée
prend cette forme:

![](confusion_matrix.png)

Standardiser les variables n'apporte finalement pas de gain:

```{python}
#| output: false

# 5. Refaire les questions précédentes avec des variables normalisées.
import sklearn.preprocessing as preprocessing

X = df[xvars]
X = df.loc[:, xvars]
y = df[['y']]
scaler = preprocessing.StandardScaler().fit(X) #Ici on standardise
scaler = preprocessing.StandardScaler().fit(X) #Ici on estime
X = scaler.transform(X) #Ici on standardise

X_train, X_test, y_train, y_test = train_test_split(
Expand All @@ -250,16 +229,10 @@ disp = sklearn.metrics.ConfusionMatrixDisplay(
display_labels=clf.classes_
)
disp.plot()

#Réponse : Non, standardiser les variables n'apporte pas de gain
# 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.

plt.savefig("confusion_matrix2.png")
plt.show()
```

![](confusion_matrix2.png)

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é.

A l'issue de la question 6,
le nouveau classifieur avec devrait avoir les performances suivantes :
Expand All @@ -269,15 +242,12 @@ le nouveau classifieur avec devrait avoir les performances suivantes :

out = pd.DataFrame.from_dict({"Accuracy": [sc_accuracy], "Recall": [sc_recall],
"Precision": [sc_precision], "F1": [sc_f1]}, orient = "index", columns = ["Score"])
print(out.to_markdown())
```




```{python}
#| include: false

# 6. Refaire les questions en changeant la variable X.
votes['y'] = (votes['votes_gop'] > votes['votes_dem']).astype(int)
df = votes[["y", "share_2016_republican", 'Median_Household_Income_2019']]
Expand Down Expand Up @@ -318,9 +288,6 @@ disp.plot()
plt.savefig("confusion_matrix3.png")
```

Et la matrice de confusion associée :

![](confusion_matrix3.png)



Expand Down
Loading