Skip to content

Commit

Permalink
Adds content for machine learning (#54)
Browse files Browse the repository at this point in the history
* rappel

* first examples on ml

* ml

* black

* ut

* fix unittests

* urls

* url

* remove xavierdupre

* add notebook

* add notebook on classification

* add links

* add missing links

* url

* version

* fix links
  • Loading branch information
xadupre authored Jan 3, 2024
1 parent 772f1e3 commit f3310d3
Show file tree
Hide file tree
Showing 125 changed files with 14,904 additions and 638 deletions.
7 changes: 4 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ jobs:

- restore_cache:
keys:
- v2-dependencies-{{ checksum "requirements-dev.txt" }}
- v2-dependencies-
- v3-dependencies-{{ checksum "requirements-dev.txt" }}
- v3-dependencies-

- run:
name: Install pandoc
Expand Down Expand Up @@ -52,12 +52,13 @@ jobs:
- run:
name: install dependencies 2
command: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
- save_cache:
paths:
- ./venv
key: v2-dependencies-{{ checksum "requirements-dev.txt" }}
key: v3-dependencies-{{ checksum "requirements-dev.txt" }}

- run:
name: version
Expand Down
13 changes: 7 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ onnxruntime_profile*
prof
temp_*
essai.txt
schema.proto
.ipynb_checkpoints
_latex/ensae/*.aux
_latex/ensae/*.idx
Expand All @@ -24,12 +25,12 @@ _latex/ensae/*.pdf
_doc/CHANGELOGS.rst
_doc/LICENSE.txt
_doc/auto_examples/*
_doc/examples/*.proto
_doc/examples/schema_pb2.py
_doc/examples/plot_*.png
_doc/examples/plot_*.xlsx
_doc/examples/data/*.optimized.onnx
_doc/examples/*.html
_doc/examples/**/plot_*.png
_doc/examples/**/plot_*.xlsx
_doc/examples/prog/*.proto
_doc/examples/prog/schema_pb2.py
_doc/examples/prog/data/*.optimized.onnx
_doc/examples/prog/*.html
_doc/_static/require.js
_doc/_static/viz.js
_doc/practice/algo-compose/paris_54000.*
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOGS.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
Change Logs
===========

0.3.2
0.4.0
+++++

* :pr:`54`: add content for machine learning
* :pr:`47`: add helpers to create a video

0.3.1
Expand Down
2 changes: 1 addition & 1 deletion _doc/algorithm_culture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ Liens
* `Liste d'algorithme sur Wikipédia <http://en.wikipedia.org/wiki/List_of_algorithms>`_
(`version française <http://fr.wikipedia.org/wiki/Liste_d%27algorithmes>`_)
* `List of machine learning concepts <http://en.wikipedia.org/wiki/List_of_machine_learning_concepts>`_
* `Machine Learning, Statistiques et Programmation <http://www.xavierdupre.fr/app/mlstatpy/helpsphinx/index.html>`_
* `Machine Learning, Statistiques et Programmation <https://sdpython.github.io/doc/mlstatpy/dev/index.html>`_
* `Introduction to graphs and networks <http://freakonometrics.hypotheses.org/51106>`_
(échantillon dans un graphe, chaîne de Markov, centralité, ...)
* `Networks and Flows #2 <http://freakonometrics.hypotheses.org/51457>`_
Expand Down
18 changes: 18 additions & 0 deletions _doc/api/datasets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
===============
Jeux de données
===============

Classification
==============

.. autofunction:: teachpyx.datasets.wines.load_wines_dataset

Outils
======

.. autofunction:: teachpyx.datasets.data_helper.get_data_folder

Régression
==========

.. autofunction:: teachpyx.datasets.load_wine_dataset
1 change: 1 addition & 0 deletions _doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Code inclus dans cette librairie
:caption: Constructions classiques

classique
datasets
tools

.. toctree::
Expand Down
189 changes: 189 additions & 0 deletions _doc/articles/2022-01-01-assurance.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@

Assurance auto
==============

J'avoue que je ne savais pas trop où allait partir cette
séance de cours quand je l'ai commencée avec seulement
l'idée qu'on n'a pas toujours besoin des données pour
prédire ce qu'elle pourrait nous raconter si nous les avions.
Et pourquoi ne pas supposer que nous les avons...
J'ai donc demandé aux étudiants quelques problèmes
de prédiction qui pourrait intéresser une compagnie
d'assurance. Deux réponses sont restées, la fait qu'un
client reste client et ne parte pas pour une autre assurance,
et la prédiction d'un risque. Le risque est une notion
assez floue et qui nécessite quelques éclaircissements
avant d'utiliser des outils comme le machine learning.
Les maths n'aiment pas l'imprécision et tout ce qui
n'est pas quantifiable. Je dis cela même si je ne sais
pas vraiment compter. Je sais que je sais comment compter,
je sais que je ne sais pas faire deux fois le même calcul
et retrouve le même résultat. Je ne vais pas compter donc.
Nous sommes partis pour l'assurance auto même si je n'ai
pas le permis et que mon rêve est que les chauffeurs
disparaissent.

Assurance
+++++++++

L'assurance est un moyen de mutualiser les risques.
C'est-à-dire les conséquences financières d'un accident
puisque nous vivons dans une économie où tout a quasiment
une correspondance en argent. Le risque est donc l'ensemble
des dépenses financières. De quelles données faut-il disposer
pour estimer ces dépenses ?

Il nous faut une liste de sinistres avec les dépenses
financières associées, la date de chaque sinistre. Si on
veut moduler le risque en fonction d'autres facteurs,
comme l'âge, le genre, la marque de la voiture, le modèle,
la ville.

Mais comment mesurer un risque si on ne connaît que les accidents ?
Cela revient à dire que toutes les personnes de la base de
de données ont eu un accident ce qui n'est pas le but souhaité.
On peut ajouter à la liste des autres clients qui n'ont pas
eu d'accidents. Mais il semble que quelque chose manque.
La probabilité d'avoir un accident sur une vie est plus
importante que celle d'avoir un accident dans l'année qui suit.
Cela veut dire aussi qu'une personne n'est plus une seule
observation mais plusieurs, une pour chaque année. Cela permet
aussi de prendre en compte le fait qu'une personne change souvant
plusieurs fois de voiture tout au long de sa vie.

Données
+++++++

Ce problème est toujours théorique mais pour la suite,
on suppose que les données sont organisées dans une table
avec les colonnes suivantes :

* année
* identifiant personne
* âge
* genre
* modèle
* âge voiture
* kilométrage
* adresse sous la forme longitude lattitude,
ou celle du centre du quartier pour anonymiser
les données même si couplées aux autres variables,
il existe sans doute un nombre réduit de personnes
avec le même âge et la même voiture, pour la suite,
nous considérerons que le modèle utilise les coordonnées
de l'adresse
* montant du sinistre durant l'année suivante = Y

La dernière colonne est celle que nous souhaitons
prédire, elle correspond au risque et elle est nulle
la plupart du temps. On pourrait également se demander
pourquoi un an, pourquoi pas une semaine ? Mais plus
l'horizon est court, plus cette probabilité est pour le
moins difficile à évaluer et de plus en plus faible.
Il faut se fixer un horizon raisonnable.

Premier réflexe : apprentissage et test
+++++++++++++++++++++++++++++++++++++++

Le machine learning sert à prédire, il a tendance
à faire du surapprentissage dès qu'il en a la possibilité.
C'est pourquoi on divise la base dont on dispose en
base d'apprentissage et base de test. La base en cours
n'est pas une série temporelle mais il a une
composante temporelle. Cela veut dire qu'il faudra
faire attention à ne pas utiliser les informations
du futur pour prédire. Une **division selon une année** paraît
le plus simple pour découper la base.

Il existe une autre possibilité, celle de répartir chaque
client selon une base ou une autre. Cela permet d'éviter
que les données le passé d'un client soient en quelque
sorte mémorisé par le modèle pour prédire son futur dans la
base de test. Une division par client est l'assurance que le
modèle pourra s'adapter à des personnes qu'il n'a jamais vues.

Une division par modèle ou par âge rendrait le modèle incapable
de prédire pour toute nouvelle personne. Donc,
dans un premier temps une **division par personne** semble
le mieux adapté.

Il faudra utiliser les deux divisions à la fin pour s'assurer
que le modèle est robuste mais pour le moment,
cette division non temorelle est la plus simple.

Ajout de variables agrégées
+++++++++++++++++++++++++++

Parmi les variables qui permettent d'améliorer
la performance du modèle, il y a des statistiques agrégées
comme la probabilité d'avoir un accident avec tel ou tel
modèle de voiture, ou après un certain âge. Il faut à chaque fois
faire attention au temps.

La probabilité d'avoir un accident avec tel ou tel modèle
ne peut être calculée que les données passées au moment
où elle est considérée, ce nombre évoluera chaque année
pour une même personne.

Il est difficile d'estimer la probabilité d'avoir un accident
après un certain âge lorsque la variable à prédire fait elle
partie de l'agrégation qui est construite.
Il faut donc exclure la personne considéré avant de calculer ce
taux qui sera donc différent pour chacun. La pertinence du
modèle est plus simple à vérifier alors avec une division
apprentissage / test selon les personnes. Et pour la base
de test, il faudra s'assurer que les variables agrégées
soient calculées uniquement avec la base d'apprentissage.

Données géographiques
+++++++++++++++++++++

On s'aperçoit que les données géographiques ne sont
absolument pas utilisées par le modèle même s'il
paraît intuitif que certaines régions d'un pays
sont plus propices aux accidents. D'un autre côté,
il est improbable de trouver une corrélation entre
la latitude et le risque. Pourquoi serait-il plus risqué
de conduire au Nord plutôt qu'au Sud de la France ?

Pour utiliser cette variable, il faut regrouper les
habitants en zones. Faire un clustering en quelque sorte.
Le problème avec cette approche est qu'elle aboutira
à créer des zones très denses dans les villes et d'autres moins.
On peut constraindre le clustering à ne regrouper que plusieurs
milliers de personnes ou simplement utiliser le graphe
d'une classification ascendante hiérarchique pour regrouper
10.000 personnes dans chaque zone.

Grand nombre de variables
+++++++++++++++++++++++++

Pour que la clusterisation ait un impact, il faudra
sans doute beaucoup de clusters et le numéro de cluster
d'une personne est une variable catégorielle qu'on a l'habitude
de traiter avec un :epkg:`OneHotEncoder` qui crée une variable
pour chaque cluster. Il est alors probable que le nombre de
variables dépasse le nombre d'observations.
Il faut réduire la dimension !

Une ACP paraît le plus indiquée mais cela a-t-il vraiment un sens ?
On est sûr d'une chose, le modèle sera difficilement interprétable si
sa performance dépend fortement de la région géographique.
Une autre idée consiste à faire une moyenne du risque sur chaque zone,
et plutôt que d'utiliser la zone géographique, on utilise
les autres variables agrégées sur cette zone. De cette façon,
le nombre de variables reste petit. Là encore, il faut faire
attention à ne pas mélanger passé et futur.

Modélisation un peu plus anonyme
++++++++++++++++++++++++++++++++

La prédiction est personnalisée mais elle requiert de
connaître une personne beaucoup d'informations souvent
considéré comme sensible. C'est pourquoi, on peut construire
un modèle qui estime le risque annuel d'un côté pour des groupes
d'individus et qui le multiplie par la fréquence des accidents
d'une personne en particulier :
*risque(personne) = risque(groupe) * fréquence(accident / personne)*.
Cela permet de réduire la part des informations personnelles
à un simple facteur.
1 change: 0 additions & 1 deletion _doc/articles/2023-09-06-ensae.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Voir aussi les précédents énoncés : :ref:`l-exams`.
* exercices sur le langage :ref:`l-python`
* exercices sur des algortihmes :ref:`l-algo`
* examens passés :ref:`l-exams`
* Site plus tout-à-fait maintenu `www.xavierdupre.fr <http://www.xavierdupre.fr>`_
* :ref:`Plan suivi en 2022 <l-feuille-route-2022>`
* `Des aspects plus mathématiques d'algorithmes <https://sdpython.github.io/doc/mlstatpy/dev/>`_

Expand Down
1 change: 1 addition & 0 deletions _doc/articles/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ Ou *blog*.

2022-11-31-route2022
2022-12-07-cartopy
2022-01-01-assurance
30 changes: 1 addition & 29 deletions _doc/c_data/nb_array.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1119,13 +1119,6 @@
"L'opération précédente fonctionne car numpy effectue ce qu'on appelle un [broadcasting](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) de ``c`` : une dimension étant commune, tout se passe comme si on dupliquait c sur la dimension non-partagée avec b. (voir aussi [Broadcasting](https://numpy.org/doc/stable/user/basics.broadcasting.html)) :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 36,
Expand Down Expand Up @@ -1785,15 +1778,6 @@
"L'exercice précédent montre comment générer une marche aléatoire à partir d'une série temporelle aléatoire. Comment retrouver la série initiale à partir de la marche aléatoire ?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -1805,7 +1789,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Le module [scipy.optimize](http://docs.scipy.org/doc/scipy/reference/optimize.html) fournit un panel de méthodes d'optimisation. En fonction du problème que vous souhaitez résoudre, il vous faut choisir la méthode adéquate. Je vous conseille vivement la lecture de ce [tutoriel](http://scipy-lectures.github.io/advanced/mathematical_optimization/index.html) sur l'optimisation numérique, écrit par Gaël Varoquaux. \n"
"Le module [scipy.optimize](http://docs.scipy.org/doc/scipy/reference/optimize.html) fournit un panel de méthodes d'optimisation. En fonction du problème que vous souhaitez résoudre, il vous faut choisir la méthode adéquate. Je vous conseille vivement la lecture du tutoriel [Mathematical optimization: finding minima of functions](http://scipy-lectures.org/advanced/mathematical_optimization/index.html) sur l'optimisation numérique, écrit par Gaël Varoquaux. \n"
]
},
{
Expand Down Expand Up @@ -2741,18 +2725,6 @@
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion _doc/c_data/nb_dataframe.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"\n",
"**Taille de DataFrame**\n",
"\n",
"Les DataFrame en Python sont assez rapides lorsqu'il y a moins de 10 millions d'observations et que le fichier texte qui décrit les données n'est pas plus gros que 10 Mo. Au delà, il faut soit être patient, soit être astucieux comme ici : [DataFrame et SQL](http://www.xavierdupre.fr/blog/2014-07-19_nojs.html), [Data Wrangling with Pandas](http://nbviewer.jupyter.org/urls/gist.github.com/fonnesbeck/5850413/raw/3a9406c73365480bc58d5e75bc80f7962243ba17/2.+Data+Wrangling+with+Pandas.ipynb). D'autres options seront proposées plus tard durant ce cours.\n",
"Les DataFrame en Python sont assez rapides lorsqu'il y a moins de 10 millions d'observations et que le fichier texte qui décrit les données n'est pas plus gros que 10 Mo. Au delà, il faut soit être patient, soit être astucieux, utiliser sqllite et passer au SQL ou parcourir les données en streaming.\n",
"\n",
"**Valeurs manquantes**\n",
"\n",
Expand Down
Binary file added _doc/c_ml/images/Gradient_descent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/fonction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/fonctionc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/fonctiond.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/gauss.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/gauss2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/hist.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/nuage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/vinroc2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _doc/c_ml/images/vinsroc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit f3310d3

Please sign in to comment.