Skip to content

Commit 6b7266b

Browse files
xadupresdpythonCopilotCopilot
authored
add datasets - teaching (#89)
* add datasets * fix pretraitement image * update * fix * fix * se3 * plan * fix * fix * fix * Update _doc/examples/ml/plot_template_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update _doc/examples/ml/plot_template_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update _doc/examples/ml/plot_template_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update _doc/examples/ml/plot_template_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update _doc/examples/ml/plot_template_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update _doc/examples/ml/plot_template_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix four bugs in plot_template_data.py causing compute_oracle and pipeline to fail (#90) * Initial plan * Fix multiple bugs in plot_template_data.py Co-authored-by: xadupre <22452781+xadupre@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: xadupre <22452781+xadupre@users.noreply.github.com> Co-authored-by: xavier dupré <sdpython@users.noreply.github.com> * fix --------- Co-authored-by: xavier dupré <sdpython@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: xadupre <22452781+xadupre@users.noreply.github.com>
1 parent 7ee259b commit 6b7266b

File tree

11 files changed

+86243
-182589
lines changed

11 files changed

+86243
-182589
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,4 @@ _doc/c_data/*.txt
7878
_doc/c_data/*.xlsx
7979
_doc/c_data/*.zip
8080
_doc/c_data/*.dbf
81+
_notebooks/*qwen*

_doc/articles/2026/2026-03-15-route2026-ml.rst

Lines changed: 148 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ Fonctions utiles:
1717

1818
* :func:`teachpyx.tools.pandas.read_csv_cached`
1919

20-
Séance 1 (6/2)
21-
==============
20+
Séance 1 (27/2)
21+
===============
2222

2323
* rappels sur la régression, classification, clustering, ACP, prétraitements
2424
* train test, validation croisée
2525
* rappels sur l'apprentissage d'un arbre de régression
2626

2727
*présentation de modules*
2828

29-
* données : :epkg:`pandas`
29+
* données : :epkg:`pandas`, :epkg:`skrub`
3030
* graphes : :epkg:`matplotlib`, :epkg:`seaborn`, :epkg:`bokeh`, :epkg:`altair`
3131
* cartes : :epkg:`geopandas`, :epkg:`folium`
3232
* machine learning : :epkg:`scikit-learn`, :epkg:`skrub`, :epkg:`skore`, :epkg:`imbalanced-learn`, :epkg:`hazardous`, :epkg:`fairlearn`,
@@ -40,28 +40,155 @@ Séance 1 (6/2)
4040

4141
*problème*
4242

43-
Peut-on prédire le nombre de condidatures en 2026 pour chaque établissement ?
43+
Peut-on prédire le nombre de candidatures en 2026 pour chaque établissement ?
4444

4545
:ref:`Données parcours-sup 2021-2025 <nbl-practice-years-2026-parcoursup_2026>`
4646

47-
Séance 2 (13/2)
47+
Séance 2 (5/3)
48+
==============
49+
50+
* tests unitaires, pourquoi en faire
51+
* pipelines : pourquoi en faire
52+
* arbre de décision, comment ça marche ?
53+
* pourquoi les random forest sont résistantes à l'overfitting
54+
* qu'est-ce que le gradient boosting tree ?
55+
* réseau de neurones, comment ça marche ?
56+
* réseau diabolo et la compression
57+
* notion d'embedding
58+
59+
quelques notebooks
60+
61+
* arbre de régression, de classification
62+
:ref:`RandomForest, Overfitting <nbl-practice-ml-ml_a_tree_overfitting>`
63+
* Gradient Boosting, :ref:`Gradient Boosting et Learning Rate avec les Random Forest <nbl-practice-ml-gradient_boosting>`
64+
* Régression linéaire et contraintes sur les coefficients,
65+
`Ridge <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html>`_,
66+
`Lasso <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html>`_,
67+
`ElasticNet <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.ElasticNet.html>`_,
68+
:ref:`Ridge, Lasso, mathématiques <nbl-practice-ml-ridge_lasso>`
69+
* paramètres et hyper paramètres, :ref:`Sélection des hyper-paramètres <nbl-practice-ml-winesr_knn_hyper>`,
70+
:class:`sklearn.model_selection.GridSearchCV`
71+
* `Data challenge - Algorithme machine learning qui permet de prédire la gravité d’un accident de la rout
72+
<https://www.data.gouv.fr/fr/reuses/data-challenge-algorithme-machine-learning-qui-permet-de-predire-la-gravite-dun-accident-de-la-route/>`_
73+
74+
Séance 3 (12/3)
4875
===============
4976

77+
* Régression linéaire et contraintes sur les coefficients,
78+
`Ridge <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html>`_,
79+
`Lasso <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html>`_,
80+
`ElasticNet <https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.ElasticNet.html>`_,
81+
:ref:`Ridge, Lasso, mathématiques <nbl-practice-ml-ridge_lasso>`
82+
* paramètres et hyper paramètres, :ref:`Sélection des hyper-paramètres <nbl-practice-ml-winesr_knn_hyper>`,
83+
:class:`sklearn.model_selection.GridSearchCV`
84+
* pipelines (encore)
85+
* créer son propre estimateur
5086
* tests unitaires
51-
* pipelines : pourquoi en faire
5287

53-
Séance 3 (27/2)
54-
===============
88+
Pour cette séance, on souhaite construire un estimateur qui estime
89+
une régression linéaire à coefficients positifs, une autre avec
90+
des coefficients uniquement négatifs puis pour finir une dernière
91+
régression linéaire qui considère les deux premières comme features.
5592

56-
Séance 4 (6/3)
57-
==============
93+
Une régression linéaire minimise l'erreur
94+
:math:`\sum_i \left\Vert X_i\theta - y_i \right\Vert^2`.
95+
Le gradient est :math:`\sum_i X_i'\left( X_i\theta - y_i \right)`.
96+
97+
Comme le modèle souhaité est équivalent à une optimisation sous contrainte,
98+
on propose de le résoudre comme ceci :
5899

59-
Séance 5 (13/3)
100+
* On applique une itération de l'algorithme de la descente de gradient :
101+
:math:`\theta_{t+1} = \theta_t - \epsilon_t \sum_i X_i'\left( X_i\theta - y_i \right)`.
102+
* On ne garde que les coefficients positifs : :math:`\theta_{t+1} = \max(0, \theta_t)`.
103+
* On retourne à l'étape 1 ou on s'arrête si l'algorithme a convergé.
104+
105+
On appliquera cela au jeu de données :func:`sklearn.datasets.load_diabetes` ou
106+
`Wine Quality <https://archive.ics.uci.edu/datasets?search=wine>`_
107+
on comparera à une simple régression linéaire, les coefficients sont-ils
108+
équivalents ? Comment comparer les modèles ?
109+
110+
* :ref:`Nouvel estimateur <nbl-practice-ml-custom_estimator>`
111+
112+
Si on a le temps, traitement des données manquantes.
113+
114+
Séance 4 (19/3)
60115
===============
61116

62-
Séance 6 (20/3)
117+
* rappel : créer son propre estimateur
118+
* retour sur les tests unitaires
119+
120+
Et puis
121+
122+
* prétraitements : catégorie, dirty catégories, :epkg:`category_encoders`
123+
* anomalie
124+
* cartes : :ref:`Tracer une carte <nbl-c_data-enedis_cartes>`,
125+
:epkg:`cartopy`, :epkg:`folium`, :epkg:`geopandas`
126+
* clustering (trainable and pas trainable)
127+
* TSNE
128+
129+
Un exemple :
130+
131+
* `clustering <https://scikit-learn.org/stable/modules/clustering.html>`_
132+
* Vieux notebooks sur l'utilisation de vélos à Chicago
133+
`City Bike Views <https://github.com/sdpython/ensae_projects/blob/master/_doc/notebooks/challenges/city_bike/city_bike_views.ipynb>`_,
134+
`City Bike Clustering <https://github.com/sdpython/ensae_projects/blob/master/_doc/notebooks/challenges/city_bike/city_bike_solution_cluster_start.ipynb>`_,
135+
136+
Séance 5 (26/3)
63137
===============
64138

139+
série temporelles
140+
141+
Le modèle de référence est :epkg:`statsmodels`
142+
143+
* :ref:`Single Spectrum Analysis (SSA) <nbl-practice-ml-timeseries_ssa>`
144+
* :ref:`Décomposition d'une série temporelle <nbl-practice-ml-timeseries_seasonal>`
145+
146+
:epkg:`sktime` propose une API plus proche de :epkg:`scikit-learn`
147+
et d'autres modèles comme le clusting ou la segmentation de séries temporelles.
148+
Voir `Estimator Overview <https://www.sktime.net/en/v0.40.1/estimator_overview.html>`_.
149+
150+
* moyennes mobiles
151+
* saisonnalité
152+
* DTW
153+
* HMM, Gaussian HMM
154+
* ruptures (changements de régime)
155+
156+
:epkg:`prophet` fait aussi de la prédiction et contient aussi des algorithmes
157+
de détection de changement de régime, il contient une bonne base de jours
158+
fériés.
159+
160+
**Analyse de survie**
161+
162+
* :epkg:`scikit-survival`, :epkg:`lifelines`, analyses de survie,
163+
`Analyse de survie <https://sdpython.github.io/doc/mlstatpy/dev/c_ml/survival_analysis.html>`_,
164+
165+
**Interprétabilité**
166+
167+
* `Partial Dependence <https://scikit-learn.org/stable/modules/partial_dependence.html>`_
168+
* `Permutation Importance <https://scikit-learn.org/stable/modules/permutation_importance.html>`_
169+
* `LIME <https://arxiv.org/abs/1602.04938>`_
170+
* `Shapley value <https://en.wikipedia.org/wiki/Shapley_value>`_,
171+
`SHAP <https://shap.readthedocs.io/en/latest/index.html>`_
172+
* `Counterfactual Reasoning and Learning Systems <https://arxiv.org/abs/1209.2355>`_
173+
174+
**Municipales 2026**
175+
176+
* `premier tour <https://www.data.gouv.fr/datasets/elections-municipales-2026-resultats-du-premier-tour>`_
177+
* `liste candidates second tour <https://www.data.gouv.fr/datasets/elections-municipales-2026-listes-candidates-au-second-tour>`_
178+
* `second tour <https://www.data.gouv.fr/datasets/elections-municipales-2026-resultats-du-second-tour>`_
179+
180+
Séance 6 (3/4)
181+
==============
182+
183+
* anonymisation : `Latanya Sweeney <https://en.wikipedia.org/wiki/Latanya_Sweeney>`_, vidéo : `Latanya Sweeney: When anonymized data is anything but anonymous <https://www.youtube.com/watch?v=tivCK_fBBfo>`_
184+
(k-anonimity, l-diversité, hasard, ...)
185+
* éthique : apprendre avec et sans, grille
186+
* LLMs et code
187+
188+
* `premier tour <https://www.data.gouv.fr/datasets/elections-municipales-2026-resultats-du-premier-tour>`_
189+
* `liste candidates second tour <https://www.data.gouv.fr/datasets/elections-municipales-2026-listes-candidates-au-second-tour>`_
190+
* `second tour <https://www.data.gouv.fr/datasets/elections-municipales-2026-resultats-du-second-tour>`_
191+
65192
Evaluation
66193
==========
67194

@@ -73,21 +200,14 @@ Evaluation
73200
Quelques jeux de données
74201
========================
75202

76-
* `Parcoursup 2025 - vœux de poursuite d'études et de réorientation dans l'enseignement supérieur et réponses des établissements
77-
<https://www.data.gouv.fr/datasets/parcoursup-2025-voeux-de-poursuite-detudes-et-de-reorientation-dans-lenseignement-superieur-et-reponses-des-etablissements>`_
78-
* `Patrimoine immobilier des opérateurs de l’Enseignement supérieur
79-
<https://www.data.gouv.fr/datasets/patrimoine-immobilier-des-operateurs-de-lenseignement-superieur>`_
80-
* `Prix des carburants en France - Flux quotidien
81-
<https://www.data.gouv.fr/datasets/prix-des-carburants-en-france-flux-quotidien-1>`_
82-
* `Prix des carburants en France - Flux instantané - v2
83-
<https://www.data.gouv.fr/datasets/prix-des-carburants-en-france-flux-instantane-v2-amelioree>`_
84-
* `Séries sur les surfaces, rendements, production céréales
85-
<https://visionet.franceagrimer.fr/Pages/SeriesChronologiques.aspx?menuurl=SeriesChronologiques/productions%20vegetales/grandes%20cultures/surfaces,productions,rendements>`_
86-
* `Effectifs d'étudiants inscrits dans les établissements et les formations de l'enseignement supérieur - détail par établissements
87-
<https://www.data.gouv.fr/datasets/effectifs-detudiants-inscrits-dans-les-etablissements-et-les-formations-de-lenseignement-superieur-detail-par-etablissements>`_
88-
* `Résultats du contrôle sanitaire de l'eau distribuée commune par commune
89-
<https://www.data.gouv.fr/datasets/resultats-du-controle-sanitaire-de-leau-distribuee-commune-par-commune>`_
203+
* `Parcoursup 2025 - vœux de poursuite d'études et de réorientation dans l'enseignement supérieur et réponses des établissements <https://www.data.gouv.fr/datasets/parcoursup-2025-voeux-de-poursuite-detudes-et-de-reorientation-dans-lenseignement-superieur-et-reponses-des-etablissements>`_
204+
* `Patrimoine immobilier des opérateurs de l'Enseignement supérieur <https://www.data.gouv.fr/datasets/patrimoine-immobilier-des-operateurs-de-lenseignement-superieur>`_
205+
* `Prix des carburants en France - Flux quotidien <https://www.data.gouv.fr/datasets/prix-des-carburants-en-france-flux-quotidien-1>`_
206+
* `Prix des carburants en France - Flux instantané - v2 <https://www.data.gouv.fr/datasets/prix-des-carburants-en-france-flux-instantane-v2-amelioree>`_
207+
* `Séries sur les surfaces, rendements, production céréales <https://visionet.franceagrimer.fr/Pages/SeriesChronologiques.aspx?menuurl=SeriesChronologiques/productions%20vegetales/grandes%20cultures/surfaces,productions,rendements>`_
208+
* `Effectifs d'étudiants inscrits dans les établissements et les formations de l'enseignement supérieur - détail par établissements <https://www.data.gouv.fr/datasets/effectifs-detudiants-inscrits-dans-les-etablissements-et-les-formations-de-lenseignement-superieur-detail-par-etablissements>`_
209+
* `Résultats du contrôle sanitaire de l'eau distribuée commune par commune <https://www.data.gouv.fr/datasets/resultats-du-controle-sanitaire-de-leau-distribuee-commune-par-commune>`_
90210
* `Résultats du contrôle sanitaire de l'eau du robinet <https://www.data.gouv.fr/datasets/resultats-du-controle-sanitaire-de-leau-du-robinet>`_
91211
* `Données climatologiques de base - horaires <https://www.data.gouv.fr/datasets/donnees-climatologiques-de-base-horaires>`_
92-
* `Données climatologiques de base - mensuelles <https://www.data.gouv.fr/datasets/donnees-climatologiques-de-base-mensuelles>`_
93-
212+
* `Données climatologiques de base - mensuelles <https://www.data.gouv.fr/datasets/donnees-climatologiques-de-base-mensuelles>`_
213+
* `Base de donnée de surveillance de pesticides dans l air par les AASQA à partir de 2002 <https://www.data.gouv.fr/datasets/base-de-donnee-de-surveillance-de-pesticides-dans-l-air-par-les-aasqa-a-partir-de-2002>`_

_doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def linkcode_resolve(domain, info):
113113
nitpick_ignore = [
114114
("py:class", "False"),
115115
("py:class", "True"),
116+
("py:class", "pandas.core.frame.DataFrame"),
116117
("py:class", "pipeline.Pipeline"),
117118
("py:class", "default=sklearn.utils.metadata_routing.UNCHANGED"),
118119
("py:class", "sklearn.utils._metadata_requests.RequestMethod"),
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
Données parcours-sup 2021-2025
3+
==============================
4+
5+
"""
6+
7+
import pandas
8+
from teachpyx.tools.pandas import read_csv_cached
9+
from sklearn.metrics import mean_absolute_error
10+
from sklearn.pipeline import Pipeline
11+
from sklearn.compose import ColumnTransformer
12+
from sklearn.preprocessing import OneHotEncoder, StandardScaler
13+
from sklearn.ensemble import HistGradientBoostingRegressor
14+
15+
# from skrub import TableReport
16+
17+
18+
def get_data():
19+
urls = {
20+
"2021": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2021/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
21+
"2022": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2022/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
22+
"2023": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2023/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
23+
"2024": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2024/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
24+
"2025": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
25+
}
26+
27+
dfs = {}
28+
for k, url in urls.items():
29+
print(f"loading {k!r}")
30+
dfs[k] = read_csv_cached(url, sep=";")
31+
32+
return pandas.concat(dfs.values(), axis=0)
33+
34+
35+
def select_variables_and_clean(df):
36+
keys = [
37+
"Région de l’établissement",
38+
"Session",
39+
"Statut de l’établissement de la filière de formation (public, privé…)",
40+
"Sélectivité",
41+
"Code UAI de l'établissement",
42+
"Établissement",
43+
"Filière de formation détaillée bis",
44+
"Filière de formation très agrégée",
45+
"Filière de formation.1",
46+
"Académie de l’établissement",
47+
"Code départemental de l’établissement",
48+
"Commune de l’établissement",
49+
"Concours communs et banque d'épreuves",
50+
]
51+
cible = "Effectif total des candidats pour une formation"
52+
columns = set(df.columns)
53+
assert set(keys) & set(columns) == set(
54+
keys
55+
), f"Missing columns {set(keys) - set(keys) & set(columns)} in {sorted(df.columns)}"
56+
subset = df[[*keys, cible]]
57+
mask = subset.duplicated(subset=keys, keep=False)
58+
return subset[~mask].reset_index(drop=True), cible
59+
60+
61+
def compute_oracle(table, cible):
62+
vars = [c for c in table.columns if c != cible]
63+
f2025 = table["Session"] == 2025
64+
f2024 = table["Session"] == 2024
65+
ftwo = table[f2025 | f2024]
66+
piv = (
67+
pandas.pivot_table(
68+
ftwo,
69+
index=[c for c in vars if c != "Session"],
70+
columns="Session",
71+
values=cible,
72+
)
73+
.dropna(axis=0)
74+
.sort_index()
75+
)
76+
# Keep only rows where both 2024 and 2025 have non-missing values
77+
piv = piv.dropna(axis=0, how="any")
78+
if piv.empty:
79+
raise ValueError(
80+
"Not enough overlapping data between 2024 and 2025 to compute oracle."
81+
)
82+
return mean_absolute_error(piv[2025], piv[2024])
83+
84+
85+
def split_train_test(table, cible):
86+
X, y = table.drop(cible, axis=1), table[cible]
87+
88+
train_test = X["Session"] < 2025
89+
90+
drop = ["Session", "Code UAI de l'établissement", "Établissement"]
91+
92+
train_X = X[train_test].drop(drop, axis=1)
93+
train_y = y[train_test]
94+
test_X = X[~train_test].drop(drop, axis=1)
95+
test_y = y[~train_test]
96+
return train_X, test_X, train_y, test_y
97+
98+
99+
def make_pipeline(table, cible):
100+
vars = [c for c in table.columns if c != cible]
101+
num_cols = ["Capacité de l’établissement par formation"]
102+
cat_cols = [c for c in vars if c not in num_cols]
103+
104+
transformers = []
105+
if num_cols:
106+
transformers.append(("num", StandardScaler(), num_cols))
107+
if cat_cols:
108+
transformers.append(
109+
("cats", OneHotEncoder(handle_unknown="ignore"), cat_cols)
110+
)
111+
112+
model = Pipeline(
113+
[
114+
(
115+
"preprocessing",
116+
ColumnTransformer(transformers),
117+
),
118+
("regressor", HistGradientBoostingRegressor()),
119+
]
120+
)
121+
return model
122+
123+
124+
data = get_data()
125+
table, cible = select_variables_and_clean(data)
126+
# oracle = compute_oracle(table, cible)
127+
# print(f"oracle : {oracle}")
128+
129+
# train_X, test_X, train_y, test_y = split_train_test(table, cible)
130+
# model = make_pipeline(table, cible)
131+
# model.fit(train_X, train_y)

_doc/practice/index_algo.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ angles d'approches.
7070
algo-compose/vigenere
7171
algo-compose/exercice_morse
7272

73-
Les exercices suivants fonctionnent par pair énoncé et correction.
73+
Les exercices suivants fonctionnent par paire énoncé et correction.
7474

7575
.. toctree::
7676
:maxdepth: 1

_doc/practice/index_python.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Exercices sur le langage python
6868
../auto_examples/prog/plot_gil_example
6969
../auto_examples/prog/plot_lambda_function
7070

71-
Les exercices suivants fonctionnent par pair énoncé et correction.
71+
Les exercices suivants fonctionnent par paire énoncé et correction.
7272

7373
.. toctree::
7474
:maxdepth: 1

0 commit comments

Comments
 (0)