commit 869225a0ffbd4f06f7d3d3455512bf9bffe05190
parent b077d82226d675e4283d4b182e27470c338e57e3
Author: Étienne Simon <etienne.jl.simon@gmail.com>
Date: Fri, 22 Feb 2013 06:40:11 +0100
Mise à jour du plan de développement et du cahier des charges.
Diffstat:
2 files changed, 161 insertions(+), 84 deletions(-)
diff --git a/doc/operational plan.tex b/doc/operational plan.tex
@@ -13,7 +13,7 @@
\begin{titlepage}
\begin{center}
\begin{minipage}{0.58\textwidth}
- \includegraphics[width=\textwidth]{images/UPMC_logotype.eps}
+ \includegraphics[width=\textwidth]{images/UPMC_logotype}
\end{minipage}
\begin{minipage}{0.4\textwidth}
\begin{center}
@@ -42,11 +42,8 @@
\section{Aperçu du PIAD}
\subsection{Objectifs}
Ce PIAD est intitulé «~Vers une Machine d'apprentissage persistante.~»
-L'objectif sera d'étendre les fonctionnalités de la bibliothèque \nmlp{} pour permettre la persistance des objets utilisés par celle-ci.
-
-\nmlp{} est une bibliothèque permettant l'apprentissage de perceptrons multicouches (MLP).
-Les MLP sont traités comme des ensembles de modules, qui sont appris sous la gouvernance d'un critère.
-Le but sera d'écrire un ensemble d'outil pour manipuler ces modules et, plus généralement, faciliter l'apprentissage des MLP.
+L'objectif sera d'écrire une plateforme pour l'apprentissage et le raisonnement sur des données hétérogènes.
+Les modèles ainsi appris devront être conservés dans une base de données en vue de leur réutilisation.
\subsection{Références}
L'ensemble du livrable est disponible sur un dépôt Mercurial, il est possible de le cloner avec la commande~:\\
@@ -59,43 +56,42 @@ Ce PIAD est réalisé par un seul étudiant~: Étienne Simon (numéro étudiant
Il est encadré par Ludovic Denoyer (professeur au LIP6.)
\subsection{Activités}
-\subsubsection{Phase 1~: Serveur}
-\paragraph{Interfaçage avec \nmlp{}}
-Présentation de l'interface de \nmlp{} à travers la nouvelle bibliothèque.
-Bien que rapide, cette tâche permettra aussi de se familiarisé avec \nmlp{}, une semaine entière y est donc alloué.
-Il faudra en particulier prendre soin à discerner le code des objets CPU du code des objets GPU ainsi que les contraintes qui y sont liées (e.g. espace mémoire plus limité en GPU.)
-\paragraph{Serialisation}
+\subsubsection{Phase 1~: Bases}
+\paragraph{Interfaçage avec \nmlp{}}
Ajout d'opérateurs de serialisation aux classes de \nmlp{}, utilisation possible de Boost.Serialization.
-Il faudra ajouter les opérateurs sans modifier le code de \nmlp{}.
-Il peut être intéressant d'avoir un format d'archive portable en prévision des tâches de la phase 3.
+Il faudra ajouter les opérateurs sans modifier le code de \nmlp{} et prendre soin à discerner le code des objets CPU du code des objets GPU ainsi que les contraintes qui y sont liées (e.g. espace mémoire plus limité en GPU.)
+Il peut être intéressant d'avoir un format d'archive portable.
\paragraph{Persistance}
Gestion d'une base de donnée des objets de \nmlp{} en utilisant les opérateurs de serialisation écrits lors de la tâche précédente.
-Il faudra également stocker des métadonnées, par exemple des descriptions pour les modules et les tests ou encore les paramètres d'apprentissage utilisés pour l'entraînement d'un module.
-De plus une interface pour manipuler ces objets devra être implémenté (e.g. faire cent coups de gradients sur le module X avec le jeu de données Y.)
-Il sera intéressant d'avoir des identificateurs universels pour les modules et les jeux de données (par exemple en les hachant), le cas des critères est plus simple car ceux-ci sont peu nombreux.
+Il faudra également stocker des métadonnées, par exemple un nom et une description pour les encodeur et les tests ou encore les paramètres d'apprentissage utilisés pour l'entraînement d'un modèle.
+Il sera intéressant d'avoir des identificateurs universels pour les modèles et les jeux de données (par exemple en les hachant).
-\subsubsection{Phase 2~: Clients}
-\paragraph{Test}
-Un premier client se limitera à l'apprentissage d'un MLP sur des couples de vecteurs d'entrée et de sortie.
-Cela permettra principalement de s'assurer que le serveur fonctionne correctement.
+SQLite est déjà présent dans le dépôt de \nmlp{}.
+Pour s'assurer une plus grande flexibilité, une couche d'abstraction telle que SOCI sera utilisée.
-\paragraph{Application}
-Une des applications de \nmlp{} est l'apprentissage d'encodeurs et de décodeurs pour la classification de données hétérogènes.
-Il serait intéressant d'écrire un client pour faire de la classification sur un tel jeu de données.
+\paragraph{Supervision}
+Le superviseur est une interface pour manipuler les objets de \nmlp{} présents dans la base de données.
+C'est lui qui se charge de l'apprentissage des modèles sur les données présentes dans la base de données.
+Il devra permettre l'exécution de commandes telles que «~faire Z coups de gradients sur le modèle X avec le jeu de données Y.~»
+Pour cella, il s'appuiera sur les algorithmes implémentés dans \nmlp{}.
-\subsubsection{Phase 3~: Finalisations}
-\paragraph{Réseau}
-Rendre le serveur accessible par un protocole réseau.
+\paragraph{Test}
+Après l'écriture du superviseur, il est possible de tester l'ensemble du code écrit jusqu'alors.
+Il sera question d'apprendre un modèle simple sur deux ou trois types de données différents.
+
+\subsubsection{Phase 2~: Développements}
+\paragraph{Contrôleur}
+Le contrôleur devra présenter une interface plus haut niveau que le superviseur.
+En acceptant des commandes par un protocole réseau et en lançant le superviseur en tâche de fond par exemple.
+Le contrôleur pourra également fournir une interface pour l'ajout de données.
Cela se réduira à l'interprétation de requêtes récupérées par Boost.Asio.
Dans un premier temps, le serveur devra accepter une seule connexion.
Une file de requête pourra être crée pour la gestion de connexions simultanées.
-Il faudra ensuite repérer les opérations qui sont exécutables de manière concurrentielles pour pouvoir exécuter plusieurs requêtes simultanément.
-Par ailleurs, alors que le serveur sous forme de bibliothèque pouvait tout charger en mémoire lors d'un appel client puis tout écrire en fin d'opération, un serveur réseau doit distinguer ce qu'il garde en mémoire dynamique de ce qui doit être lu ou écrit sur le disque.
-\paragraph{Parallélisation} (optionnel)
-Enfin, une optimisation intéressante consisterait à utiliser Boost.MPI pour paralléliser les opérations sur plusieurs machines.
+\paragraph{Parallélisation}
+Enfin, une optimisation intéressante consisterait à lancer plusieurs superviseurs concurrentiellement, voire d'utiliser Boost.MPI pour paralléliser les opérations sur plusieurs machines.
\subsubsection{Documentations et tests}
\paragraph{Documentation développeur}
@@ -103,10 +99,10 @@ L'outil \emph{de facto} standard d'écriture de documentation développeur pour
Ce n'est pas une dépendance de \nmlp{}, mais il est possible de générer la documentation séparément, cela ne devrait donc pas poser de problème.
\paragraph{Documentation utilisateur}
-L'objet principal de ce PIAD étant un serveur, l'utilisateur sera principalement renseigné par la documentation développeur.
-Toute fois, un guide d'installation et une documentation des clients devra être écrite séparément.
+L'installation devrait être assez simple pour ne nécessiter rien de plus qu'un fichier INSTALL.
+Les binaires et leurs fonctionnalités devront cependant être décris entièrement.
-\paragraph{Tests}
+\paragraph{Tests unitaires}
Les dépendances de \nmlp{} offrent déjà un \emph{framework} de test avec CTest et Boost.Test.
Des tests unitaires seront écrit avec ces outils tout au long du développement.
@@ -114,25 +110,18 @@ Des tests unitaires seront écrit avec ces outils tout au long du développement
\noindent
\begin{tabular}{ | c | c | p{0.58\textwidth} | } \hline
\multicolumn{1}{|c|}{\textbf{Date}} & \textbf{Semaine} & \multicolumn{1}{|c|}{\textbf{Description}}\\\hline
-\textit{01/02} & \textit{0} & \textit{Remise du cahier des charges et du plan de développement.}\\\hline
-\textbf{04/02-10/03} & \textbf{1..5} & \multicolumn{1}{|c|}{\textbf{Phase 1~: Serveur}}\\\hline
-04/02-10/02 & 1 & Familiarisation et interfaçage avec \nmlp{}.\\
-11/02-17/02 & 2 & Écriture des opérateurs de serialisation.\\
-18/02-03/03 & 3..4 & Utilisation d'une base de données pour activer la persistance des objets.\\
-04/03-10/03 & 5 & Debug, test et documentation.\\\hline
-\textbf{11/03-31/03} & \textbf{6..8} & \multicolumn{1}{|c|}{\textbf{Phase 2~: Clients}}\\\hline
-11/03-24/03 & 6..7 & Écriture de clients exploitant les fonctionnalités offertes par le serveur.\\
-25/03-31/03 & 8 & Debug, test et documentation.\\\hline
-\textbf{01/04-05/05} & \textbf{9..13} & \multicolumn{1}{|c|}{\textbf{Phase 3~: Finalisations}}\\\hline
-01/04-14/03 & 9..10 & Mise en réseau du serveur.\\
-15/04-28/03 & 11..12 & Parallélisation du serveur.\\
-29/04-05/05 & 13 & Debug, test et documentation.\\\hline
-\textit{09/05} & \textit{14} & \textit{Remise du rapport final.}\\\hline
-\textit{13/05-20/05} & \textit{15} & \textit{Soutenance.}\\\hline
+\textit{24/02} & \textit{0} & \textit{Remise du cahier des charges et du plan de développement.}\\\hline
+\textbf{25/02-31/03} & \textbf{1..5} & \multicolumn{1}{|c|}{\textbf{Phase 1~: Bases}}\\\hline
+25/02-03/03 & 1 & Interfaçage avec \nmlp{}. Écriture des opérateurs de serialisation.\\
+04/03-10/03 & 2 & Utilisation d'une base de données pour activer la persistance des objets.\\
+11/03-24/03 & 3..4 & Écriture du superviseur. Utilisation des algorithmes de \nmlp{}.\\
+25/03-31/03 & 5 & Test du superviseur sur un jeu de données simple.\\\hline
+\textbf{01/04-05/05} & \textbf{6..10} & \multicolumn{1}{|c|}{\textbf{Phase 2~: Développements}}\\\hline
+01/04-14/03 & 6..7 & Mise en serveur autour d'un contrôleur.\\
+15/04-28/03 & 8..9 & Parallélisation du serveur.\\
+29/04-05/05 & 10 & Debug, test et documentation.\\\hline
+\textit{09/05} & \textit{11} & \textit{Remise du rapport final.}\\\hline
+\textit{13/05-20/05} & \textit{12} & \textit{Soutenance.}\\\hline
\end{tabular}
-\paragraph{}
-Bien qu'une semaine soit allouée au debug, test et documentation pour chaque phase, ces tâches seront à effectuer pendent la période de développement.
-Il peut toute fois être intéressant de faire le point en fin de chaque phase, de plus ces semaines peuvent servir de tampons contre un retard.
-
\end{document}
diff --git a/doc/specifications.tex b/doc/specifications.tex
@@ -1,4 +1,5 @@
\documentclass[11pt,a4paper]{report}
+\usepackage{amsfonts}
\usepackage{setspace}
\usepackage{graphicx}
\usepackage{url}
@@ -6,6 +7,9 @@
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
+\usepackage{tikz}
+\usepackage{tikz-uml}
+\usetikzlibrary{positioning,chains,fit,shapes,calc,arrows,decorations.text}
\newcommand{\nmlp}{\textsc{nmlp}}
\renewcommand{\thesection}{\arabic{section}}
@@ -14,7 +18,7 @@
\begin{titlepage}
\begin{center}
\begin{minipage}{0.58\textwidth}
- \includegraphics[width=\textwidth]{images/UPMC_logotype.eps}
+ \includegraphics[width=\textwidth]{images/UPMC_logotype}
\end{minipage}
\begin{minipage}{0.4\textwidth}
\begin{center}
@@ -43,54 +47,138 @@
\section{Objectif du PIAD}
\subsection{Présentation}
Ce PIAD est intitulé «~Vers une Machine d'apprentissage persistante.~»
-L'objectif sera d'étendre les fonctionnalités de la bibliothèque \nmlp{} pour permettre la persistance des objets utilisés par celle-ci.
+L'objectif sera d'écrire une plateforme pour l'apprentissage et le raisonnement sur des données hétérogènes.
+Les modèles ainsi appris devront être conservés dans une base de données en vue de leur réutilisation.
-\nmlp{} est une bibliothèque permettant l'apprentissage de perceptrons multicouches (MLP).
-Les MLP sont traités comme des ensembles de modules, qui sont appris sous la gouvernance d'un critère.
-Le but sera d'écrire un ensemble d'outil pour manipuler ces modules et, plus généralement, faciliter l'apprentissage des MLP.
+\subsection{Cadre}
+Le projet sera utilisé dans le cadre de la classification dans des réseaux hétérogènes.
+Cela fera en projetant les données de différents types dans un espace latente (commun).
+
+\begin{figure}[h]
+ \centering
+ \begin{tikzpicture}
+ [coder/.style={->,ultra thick,postaction={decorate,decoration={raise=1ex,text along path,text align=center,text={|\sffamily|#1}}}}]
+
+ \node [draw,rectangle,rounded corners,minimum size=3cm] (latent space) {Espace latent \(Z\)};
+ \path (latent space.south)+(-4,-4) node [draw,rectangle,minimum size=2cm] (view 1) {Vue \(X_1\)};
+ \path (latent space.south)+(0,-4) node [draw,rectangle,minimum size=2cm] (view 2) {Vue \(X_2\)};
+ \path (latent space.south)+(4,-4) node [draw,rectangle,minimum size=2cm] (view 3) {Vue \(X_3\)};
+ \draw [coder=encodeur] (view 1.95) to [bend left=15] (latent space.-125);
+ \draw [coder=d{é}codeur] (latent space.-115) to [bend left=15] (view 1.85);
+ \draw [coder=encodeur] (view 2.95) to [bend left=15] (latent space.-95);
+ \draw [coder=d{é}codeur] (latent space.-85) to [bend left=15] (view 2.85);
+ \draw [coder=encodeur] (view 3.95) to [bend left=15] (latent space.-65);
+ \draw [coder=d{é}codeur] (latent space.-55) to [bend left=15] (view 3.85);
+ \draw (latent space.center)+(0,1) node {\(\times z_1\)};
+ \draw (latent space.center)+(1,0.5) node {\(\times z_2\)};
+ \draw (latent space.center)+(-0.5,-1) node {\(\times z_3\)};
+ \draw (view 1.center)+(0.5,0.5) node {\scriptsize\(\times x_1^1\)};
+ \draw (view 1.center)+(-0.5,-0.5) node {\scriptsize\(\times x_1^2\)};
+ \draw (view 2.center)+(-0.5,0.5) node {\scriptsize\(\times x_2^3\)};
+ \draw (view 2.center)+(0,-0.5) node {\scriptsize\(\times x_2^2\)};
+ \draw (view 3.center)+(0.5,0.5) node {\scriptsize\(\times x_3^2\)};
+ \end{tikzpicture}
+ \caption{Relation entre les différents espaces}
+ \label{fig:latent_space_presentation}
+\end{figure}
+
+La figure \ref{fig:latent_space_presentation} présente les différents espaces entrant en jeu~:
+\begin{itemize}
+ \item Les vues sont les espaces d'observation, il y en a autant que de type de donnée.
+ Par exemple la vue 1 peut être un espace d'observation textuel et la vue 2 un espace d'observation visuel, au quel cas le vecteur \(x_1^2\) correspond à un mot du type «~chat~» et le vecteur \(x_2^2\) à l'image d'un chat.
+ \item L'espace latent contient les concepts associés aux observations. En conservant l'exemple précèdent, \(z_2\) correspond au concept «~chat.~»
+\end{itemize}
+
+Pour faire le lien entre les vecteurs des espaces d'observation et le vecteur de l'espace latent, des encodeur et décodeur sont utilisés, il s'agit de fonctions \( e_i: X_i \mapsto Z \) et \( d_i: Z \mapsto X_i \).
+Celles-ci sont apprises par des perceptrons multicouches (MLP) selon les observations faites.
+
+Par ailleurs, des relations sont définis sur les concepts.
+Les relations sont des sous ensemble de \(Z^2\) elles aussi apprises par des MLP (qui apprendront plutôt des métriques du type \(Z^2 \mapsto \mathbb{R}\).)
+Un exemple de relation est «~auteur de~» dans le cadre d'un réseau avec des nœuds «~article~» et «~personne.~»
\subsection{Objectifs principaux}
-La première tâche à effectuée sera la construction d'une bibliothèque autour de \nmlp{}.
-Celle-ci agira comme un serveur et devra permettre la persistance des objets manipulés par \nmlp{}, c'est-à-dire des modules, des critères et des données.
+\begin{figure}[ht]
+ \centering
+ \begin{tikzpicture}[scale=0.75, every node/.style={transform shape}]
+ \begin{umlsystem}[x=5]{Solution logicielle}
+ \umlusecase[y=-1,name=add_observation,width=3cm]{Ajout d'observation}
+ \umlusecase[y=-3,name=add_relation,width=3cm]{Ajout d'une relation}
+ \umlusecase[x=4,name=add_concept,width=3cm]{Ajout d'un concept}
+ \umlusecase[x=4,y=-2,name=add_relation_type,width=3cm]{Ajout d'un type de relation}
+ \umlusecase[x=4,y=-4,name=config_supervisor,width=3cm]{Configuration du superviseur}
+ \end{umlsystem}
+ \umlactor[y=-2]{Utilisateur}
+ \umlactor[x=14,y=-2]{Administrateur}
-Par la suite, de simples clients devront être écrits, permettant de tester la bibliothèques en lançant, par exemple, des apprentissages sur des MLP classiques ou des apprentissages d'auto-encoders.
-En particulier, il est prévu d'utiliser le serveur pour l'apprentissage d'encodeur de données hétérogènes vers un espace latent.
+ \umlassoc{Utilisateur}{add_observation}
+ \umlassoc{Utilisateur}{add_relation}
+ \umlassoc{Administrateur}{add_concept}
+ \umlassoc{Administrateur}{add_relation_type}
+ \umlassoc{Administrateur}{config_supervisor}
+ \end{tikzpicture}
+ \caption{Diagramme des cas d'utilisation}
+ \label{fig:use_case_diagram}
+\end{figure}
-Enfin, il sera question de créer une interface réseau pour le serveur et pour les clients.
-Avec éventuellement une parallélisation des opérations effectuées par le serveur.
+L'objectif principal est d'écrire une plateforme d'apprentissage de représentations latentes.
+Les objets manipulés doivent être persistant, ainsi, on peut distinguer deux bases de données~:
+\begin{itemize}
+ \item Une base contenant les données d'apprentissage.
+ \item Une base contenant les modèles appris.
+\end{itemize}
+
+Les modèles sont appris sous l'égide d'un superviseur, se sont des MLP et il sont décomposables en trois catégories~:
+\begin{itemize}
+ \item Les encodeurs qui permettent de projeter un vecteur observé dans l'espace latent.
+ \item Les décodeurs qui permettent de projeter un vecteur concept de l'espace latent dans un espace d'observation.
+ \item Les métriques qui permettent d'établir des relations entre les concepts de l'espace latent.
+\end{itemize}
\subsection{Contraintes techniques}
-Le développement se fera en C++, la bibliothèques \nmlp{} utilisant uniquement des fonctionnalités C++03 (ISO/IEC 14882:2003), elle sera étendu également en C++03.
-De plus, le livrable ne devra avoir aucune dépendance autre que celles déjà présentes dans \nmlp{}, c'est à dire les bibliothèques Boost et CUDA.
+\nmlp{} est une bibliothèque permettant l'apprentissage de MLP.
+Les MLP sont traités comme des ensembles de modules, qui sont appris sous la gouvernance d'un critère.
+La plateforme développée utilisera \nmlp{} pour la représentation et l'apprentissage des modèles.
+
+Le développement se fera en C++03 (ISO/IEC 14882:2003).
+De plus, le livrable devra se limiter autant que possible aux dépendances de \nmlp{}, c'est à dire les bibliothèques Boost et CUDA.
Par ailleurs, le code devra fonctionner sous Windows et sous les divers *nix, n'ayant à disposition que des environnements FreeBSD et OpenBSD avec GCC et Clang, l'encadrant devra se charger de vérifier le fonctionnement du code sous Windows.
Le livrable devra être compilable avec le moteur de production CMake utilisé par \nmlp{}.
-Pour s'assurer d'un suivi en temps réel du travail effectué, l'ensemble du livrable sera maintenue par un logiciel de gestion de versions (VCS), en l'occurrence un dépôt Mercurial sur Bitbucket~:\\
+Pour s'assurer d'un suivi en temps réel du travail effectué, l'ensemble du livrable sera maintenue par un logiciel de gestion de versions, en l'occurrence un dépôt Mercurial sur Bitbucket~:\\
\indent\indent\url{https://bitbucket.org/ejls/mi024}
\section{Description de la solution demandée}
-L'outil principal créé lors de ce PIAD sera le serveur.
-Le but est d'avoir une interface simple aux fonctionnalités offertes par \nmlp{}.
-Par exemple, le serveur devra être capable d'exécuter une suite de commande du type~:\\
-\indent\indent\verb|split dataset("100 first dUSP", "digits USP", 1, 100)|\\
-\indent\indent\verb|concat mlp "digits encoder" "encoded digit rec"|\\
-\indent\indent\indent\verb|in "digit rec"|\\
-\indent\indent\verb|gradient iteration 1000 mlp "digit rec"|\\
-\indent\indent\indent\verb|on "100 first dUSP" constraint "least square"|
-
-La fonctionnalité principale de ce serveur est la persistance des objets qu'il manipule.
-L'intérêt est de construire une base de données de modules qui pourront être réutilisés par la suite.
-
-On peut distinguer trois classes d'actions effectuées par le serveur~: la manipulation des données, la manipulation des modules et l'application de l'algorithme d'apprentissage.
+\begin{figure}[h]
+ \centering
+ \begin{tikzpicture}
+ [action/.style={->,ultra thick,postaction={decorate,decoration={raise=1ex,text along path,text align=center,text={|\sffamily|#1}}}}]
+ \node [draw, cylinder, shape border rotate=90, minimum height=4cm, minimum width=3.5cm, aspect=2.5, label={[above]Bases de données}] (database) {};
+ \path (database.center)+(0,0.75) node [draw] (model) {Modèles};
+ \path (database.center)+(0,-0.75) node [draw,align=center] (data) {Données \\ d'apprentissage};
+ \path (database.west)+(-3,0) node [draw, rectangle, rounded corners] (supervisor) {Superviseur};
+ \draw [<->, ultra thick] (model) to (supervisor);
+ \draw [->, ultra thick] (data) to (supervisor);
+ \umlactor[x=-5,y=-1.5]{Utilisateur}
+ \umlactor[x=-8,y=1.8]{Administrateur}
+ \draw [action=remplit] (Utilisateur) to (data);
+ \draw [action=initialise] (Administrateur) to (model);
+ \draw [action=configure] (Administrateur) to (supervisor);
+ \end{tikzpicture}
+ \caption{Diagramme (informel) présentant l'architecture de la solution logicielle.}
+ \label{fig:architecture}
+\end{figure}
+La figure~\ref{fig:architecture} présente les principaux composant de l'architecture logicielle.
+La majeure partie du travail s'effectuera sur le superviseur.
+À noté, qu'une fonctionnalité intéressante qui pourra être ajouté est le lancement en parallèle de plusieurs superviseurs (chacun sur un modèle différent), il pourra alors être intéressant de construire un composant pour gérer un ensemble de superviseur (qui enverrait les mêmes données à des superviseurs paramétrés différemment par exemple.)
-Une description plus détaillé des activités est présente dans le plan de développement.
+Une description plus détaillée avec une liste des activités et un calendrier sont présents dans le plan de développement.
\section{Composition du livrable}
\begin{itemize}
\item Un script de compilation CMake
- \item Une bibliothèque serveur
- \item Un \emph{daemon} serveur
- \item Des exécutables clients testant les fonctionnalités du serveur (sous ses deux formes)
+ \item Un binaire superviseur
+ \item Une interface d'ajout de données d'apprentissage
+ \item Un contrôleur (serveur) gérant un ensemble de superviseur
\item La documentation du projet
\begin{itemize}
\item Le cahier des charges