Le but de ce projet était de trouver un algorithme <b>généraliste</b> (qui puisse être uttilisé dans différents cas d'uttilisations), <b>rapide</b> (qui n'a pas une grande complexité ou qui trouve des solutions dans un temp résonable) et <b>précis</b> (qui trouve des solutions proche de la réalité dans une majorité des cas).<br/></br>
Pour ce faire j'avais plusieurs outil à ma disposition, mais celui sur laquel je me suis penché est l'algorithme <i>Knn</i> (n plus proche voisin). C'est un algorithme assez simple qui n'as pas réelement besoin d'entrainement contrairement à un réseau de neurone mais qui à cause de sa complexité algorithmique devient inutilisable dans sa forme naïve pour de large volume de données. J'ai donc du trouver un moyen de modifier l'implémentation de <i>Knn</i> pour réduire sa <b>complexité</b> tout en gardant si possible l'aspect <b>généraliste</b> et <b>précis</b> de Knn.
</p>
</section>
@ -21,7 +22,37 @@
<h2>
Algorithme et avantage par rapport à Knn
</h2>
<h3>
Point commun entre <i>Knn</i> et <i>3nar</i> :
</h3>
<p>
Ces deux algorithme sont cappables d'inférer une ou plusieures valeurs à partir d'une ou plusieurs valeurs en entrer grâce à des exemples fournit au préalable. ils sont également cappable de réaliser de la classification ou de la multi-classification (c'est à dire associer une ou plusieurs class à une ou un groupe de donnée en entrer).</br></br>
Outre leurs capacités, ils fonctionnent de la même façon. La phase d'entrainement consiste simplement à enregistrer en meimoir les différentes données d'exemples ainsi que leurs valeurs associées (valeur, groupe de valeurs, class ou groupe de class). Ensuite pour inférer la/les valeur.s/class associé à de nouvels coordonnées, on trouve les n exemples les plus proches et on retourne la moyenne des valeurs des n point multiplié par un poid calculé en fonction de leur distance.
</p>
<h3>
Problème de <i>Knn</i> :
</h3>
<p>
Le problème de l'implémentation naïve de <i>Knn</i> est que pour trouver les n points les plus proches d'un nouveau point A, on calcule la distance de chaque point en mémoir avec A puis on trouve les n points avec la plus petite distance. Ce qui veut dire que plus le nombre de point d'exemple en meimoir augmente plus on calcule de distance pour trouver la valeur d'un point. Ainsi, comme nous pouvons le voir sur le graphique ci-dessous la complexité de l'algorithme est en O(n) ??
</p>
<h3>
Solution de <i>3nar</i> :
</h3>
<p>
Pour trouver les n points les plus proches de A sans avoir à calculer les distances avec tout les autres points, <i>3nar</i> échange de la <b>RAM</b> contre de la <b>puissance de calcule</b></br></br>
A l'initialisation nous allons crée un espace orthonormé avec m dimention (le nombre de coordonées des exemples). Et nous allons remplire cet espace avec un certain nombre de sous espace à déterminer en fonction des cas d'uttilisations (ces espaces sont tous de tailles égaux et sont eux aussi orthonormé). Ensuite, lors de la phase d'entrainement, il suffit d'ajouter les points dans les différents sous éspaces en fonction de leurs coordonnées. Pour trouver le sous espace si vos sous éspace sont dans une liste vous pouvez calculer l'index avec cette formule:<br/>
Soit t la taille d'un sous espace et nb le nombre de sous espace dans une dimension:
<imgsrc="./rapport/formuleIdx.png"/><br/>
Dans le cas de ce programme, les sous éspaces sont stocké dans un tenseur et les coordonées du sous espace d'un point est donnée par la division euclidienne de toutes les coordonées du point par t.</br></br>
Une fois toutes les données ajouté dans le modèle, il est temp de lui demander la valeur de nouveau point. Pour cela l'algo vas trouver dans quel sous espace le point serait si il existait dans sa meimoir. Puis il verrifie si il a assez de point dans ce sous espace dans une distance (dont on parlera plus tard). Si c'est le cas alors il calcule les distances avec ces points et il retourne les n plus faible. Si non on trouve les sous espace à proximiter et on recommence jusqu'a avoir assez de point. Cela permet de grandement réduire le nombre de calcul de distance entre point pour trouver les n points les plus proches.<br/>
Concernant la distance, elle est calculé en fonction des coordonées du point que l'on veut deviner en fonction du centre de son sous espace. Cette distance doit être la plus grande possible (pour capté le plus de point) tout en ne sortant pas en aucun point du sous espace (pour être sûr de réelement trouver les points les plus proche). Cette distance peut être calculé de la façon suivante:</br>
<imagesrc="./rapport/rayon.png"/>
<i>dist = t - max(ABx,ABy) + t * nbSousEspaceAutour</i></br>
A noté que c'est un exemple en 2d, le même calcule peut être généralisé pour un nombre m de dimmension.<br/>
Dans le cas de ce programme, je n'ai pas uttilisé cette distance à la place j'ai uttilisé cette formule qui me garentis de ne jamais sortir de l'espace et qui est plus simple à calculer:
<imagesrc="./rapport/rayon2.png"></br>
<i>dist = t * nbSousEspaceAutour</i></br>
Enfin, dernière optimisation de l'algorithme, pour éviter de recalculer en boucle les différents sous espace autour d'un sous espace (ce qui est couteux à faire dinnamiquement pour m dimention), on enregistre en meimoir le résultat de cette opération. Puis lorsque l'on veut recalculer ce résultat, on a juste à l'appliquer à notre cas (car le sous espace ne sera pas le même mais les sous espace autour seront au même distance et dans les même directions).
</p>
</section>
@ -30,14 +61,31 @@
Cas d'uttilisation
</h2>
<p>
Comme nous l'avons vue dans la première partie, <i>3nar</i> est utilisable dans plein de context. Ce ne sera pas souvent le meilleur algo mais dans la plupart des cas il rendra un résultat satisfaisant en un temp satifaisant. Vous pouvez retrouver 4 cas d'uttilisations aussi appelé demo dans ce projet que vous pouvez lancer au choix avec <i>Knn</i> ou <i>3nar</i>. Pour lancer les demos placer vous dans le répertoir et appeler les script python de demo en ajoutant a votre commande le nom de l'algo (knn ou nnnar).<br/><br/>
</p>
</section>
<section>
<h2>
Complexité
</h2>
<h3>
demo1.py
</h3>
<p>
Dans la demo 1, nous utillisons le csv <i>./data/maison.csv</i>. Nous calculons une valeurs en sortie en fonction de 4 valeur en entrer. Nous calculons le prix des maisons en fonction du nombre de m², du nombre de chambre, du nombre de salle de bain et de l'étage. Sur ces données et avec 80% du dataset en entrainement et 20% en test, on arrive au alentour de 90% de precisions.
</p>
<h3>
demo2.py
</h3>
<p>
Dans cet exemple, nous générons aléatoirement une fonction polynomiale du second degré avec des paramètres étant des réels compris entre -5 et 5. Puis après avoir fournit à <i>3nar</i> quelques exemples (100 dans notre cas), nous uttilisons l'algorithme pour prédire de nouvelles valeurs choisit aléatoirement.
</p>
<h3>
demo3.py
</h3>
<p>
Cette demo est plus visuel est présente un cas d'uttilisation ou nous devons calculer plusieurs valeurs en fonction de plusieurs valeurs. Dans cette demo, nous prenons une image (<i>./data/img.jpg</i>) puis de manière aléatoire un viens remplacer des pixels par des pixels blanc. Puis nous venons retrouver algorithmiquement les pixels qui ont été changé (on pourrait aussi faire cette étap avec <i>3nar</i> mais ça serait plus long), puis enfin, on vient calculer la valeur de ces pixels avec <i>3nar</i>. Dans cette exemple, on commence à avoir pas mal de donnée et on voit l'aventage de <i>3nar</i> par rapport à <i>Knn</i>.
</p>
<h3>
demo4.py
</h3>
<p>
Dans cette exemple, on fait la classification des espèces d'Iris à partir de la taillet de de la largeur de la tige et des pétalles. En quelque second on arrive à avoir au alentour de 95% de précision.