diff --git a/DevEfficace/rapport.md b/DevEfficace/rapport.md index 88110653b61e7e6f0c763359c635fd4c21e7f0a6..105d4153a8eae9076adf3a7c0c9a77587ac76df1 100644 --- a/DevEfficace/rapport.md +++ b/DevEfficace/rapport.md @@ -1,4 +1,4 @@ -# Algorithme K-NN - Rapport R3.02 (EN COURS - NON RELU) +# Algorithme K-NN - Rapport R3.02 ### Groupe H-4 @@ -8,7 +8,6 @@ - [DEKEISER Matisse](mailto:matisse.dekeiser.etu@univ-lille.fr) - [DESMONS Hugo](mailto:hugo.desmons.etu@univ-lille.fr) - --- ## Implémentation de K-NN @@ -17,55 +16,50 @@ pas à mettre en avant l’efficacité de ces méthodes (approprié pour un grand volume de données, normalisation efficace des distances).* -Nous avons implémenté l'algorithme K-NN dans une classe MethodKNN. Nous avons choisis d'utiliser des methodes statiques pour faciliter l'utilisation de cette algorithme. -Cette classe contient 5 methodes permettant d'implementer l'algorithme K-NN et ses differentes fonctionnalités. +Nous avons implémenté l'algorithme K-NN dans une classe `MethodKNN`. Nous avons choisi d'utiliser des méthodes statiques pour faciliter l'utilisation de cet algorithme. +Cette classe contient 5 méthodes permettant d'implémenter l'algorithme K-NN et ses différentes fonctionnalités. > public static void updateModel(List<LoadableData> datas) -Cette premiere methode permet de mettre a jour les données de l'algorithme. Ainsi il faut passer en parametre les données sur lesquelles ont souhaite travailler. -Cette methode va calculer les valeurs max et min ainsi que l'amplitude de chaque attribue des données passé en parametre. -Cette methode necessite 2 parcours, 1 sur les données, puis un sur les min et les max de chaque attribue pour calculer l'amplitude. Il est donc conseillé de n'utiliser cette methode qu'une fois par jeu de données (toute facon le resultat serait le meme) -C'est pour cela que cette methode n'est pas directement appelé dans les methodes ci-dessous mais qu'elle doit explicitement être appelé aupparavant. +Cette première méthode permet de mettre à jour les données de l'algorithme. Ainsi, il faut passer en paramètre les données sur lesquelles on souhaite travailler. +Cette méthode va calculer les valeurs max et min ainsi que l'amplitude de chaque attribut des données passé en paramètre. +Cette méthode nécessite 2 parcours : 1 sur les données, puis un sur les valeurs min et max de chaque attribut pour calculer l'amplitude. Il est donc conseillé de n'utiliser cette méthode qu'une fois par jeu de données (le résultat serait le même). +C'est pour cela que cette méthode n'est pas directement appelée dans les méthodes ci-dessous, mais qu'elle doit explicitement être appelée auparavant. -> public static List<LoadableData> kVoisins(List<LoadableData> datas, LoadableData data, int k, Distance distance) +> public static List<LoadableData> kVoisins(List<LoadableData> datas, LoadableData data, int k, Distance distance) -Cette methode a pour objectif de recupéré les k voisins les plus proches d'un donnée parmis un jeu de données et selon une distance. -Elle prends donc en parametre le jeu de données, la données pour laquelle on souhaite obtenir les voisins, le nombre de voisins souhaités ainsi que la distance avec laquelle les calculs doivent etres effectués. -Cette methode n'effectue qu'un seul parcours de boucle et calcul pour chacune des données sa distance avec la donnée passée en parametre. Les calculs de distance sont definis dans l'objet implémentant l'interface Distance passé en parametre. -Si il s'agit d'une distance normalisée la normalisation s'effectue au moment de la recherche des voisins. - ->public static double robustesse(List<LoadableData> datas, int k, Distance distance, double testPart) - +Cette méthode a pour objectif de récupérer les **k** voisins les plus proches d'une donnée parmi un jeu de données et selon une distance. +Elle prend donc en paramètres le jeu de données, la donnée pour laquelle on souhaite obtenir les voisins, le nombre de voisins souhaités ainsi que la distance avec laquelle les calculs doivent être effectués. +Cette méthode n'effectue qu'un seul parcours de boucle, et calcule pour chacune des données sa distance avec la donnée passée en paramètre. Les calculs de distance sont définis dans l'objet implémentant l'interface Distance passé en paramètre. +S'il s'agit d'une distance normalisée, la normalisation s'effectue au moment de la recherche des voisins. -Cette methode a pour objectif d'évaluer la robustesse de l'algorithme sur un jeu de donné avec un K donné et une distance donnée. Elle prends en parametre le jeu de données sur lequel effectué l'evalutation, -le k a tester, la distance a utiliser ainsi que un pourcentage correspondant a la partie des données qui sera utilisé afin de tester les données. Ex avec testPart=0.2, 80% des données serviront de données de reférence et 20% seront utilisé pour tester la -validité de l'algorithme. Cette effectue une validation croisée (Voir #Validation Croisée) +> public static double robustesse(List<LoadableData> datas, int k, Distance distance, double testPart) +Cette méthode a pour objectif d'évaluer la robustesse de l'algorithme sur un jeu de données avec un **k** et une distance donnés. Elle prend en paramètres le jeu de données sur lequel effectuer l'évaluation, +le **k** à tester, la distance à utiliser ainsi qu'un pourcentage correspondant à la partie des données qui sera utilisée afin de tester les données. Exemple avec testPart=0.2, 80% des données serviront de données de reférence et 20% seront utilisées pour tester la +validité de l'algorithme. Cette méthode effectue une validation croisée. (voir `Validation croisée`) > public static int bestK(List<LoadableData> datas, Distance distance) -Cette methode a pour objectif de rechercher le meilleur K possible pour un jeu de données et une distance données. -Elle va tester la totalité des K impair compris entre 1 et racine caré du nombre de données. Cette valeur max permet d'eviter que le K choisit soit trop grand et -fausse les résultats. Elle test donc la robustesse de chaque K et renvoie le K ayant la meilleure robustesse. Cette methode parcours le jeu de donnée Kmax*(1/testPart) fois, ou testPart correspond au pourcentage des données utilisé comme valeurs de test. - +Cette méthode a pour objectif de rechercher le meilleur **K** possible pour un jeu de données et une distance donnée. +Elle va tester la totalité des **K** impairs compris entre 1 et racine carrée du nombre de données. Cette valeur max permet d'éviter que le **K** choisi soit trop grand et +fausse les résultats. Elle teste donc la robustesse de chaque **K** et renvoie le **K** ayant la meilleure robustesse. Cette méthode parcourt le jeu de donnée `Kmax * (1/testPart)` fois, où testPart correspond au pourcentage des données utilisées comme valeurs de test. --- ## Validation croisée - -#### Rappel de la methode de validation croisée +#### Rappel de la méthode de validation croisée La validation croisée est une méthode d'évaluation utilisée pour mesurer la performance d'un modèle en le testant sur des données qu'il n'a pas utilisées pour l'entraînement. Dans ce cas précis : -Les données sont divisées en plusieurs parties égales (appelées folds ou partitions). +Les données sont divisées en plusieurs parties égales (appelées _folds_ ou _partitions_). À chaque itération, une des partitions est utilisée comme jeu de test, tandis que les autres servent pour l'entraînement. Les résultats des tests sont cumulés pour calculer un score global. Cette méthode permet de minimiser le biais d'évaluation en utilisant toutes les données tour à tour pour l'entraînement et le test. #### Implémentation de la validation croisée - La méthode effectue une validation croisée en divisant les données en plusieurs partitions. À chaque itération : Une partie des données sert de jeu de test. @@ -75,49 +69,46 @@ Voici les étapes principales : - Calcul du nombre d'itérations : Le nombre d'itérations est déterminé par -1/testPart. Par exemple, si testPart = 0.1, la méthode effectue 10 itérations, si testPart = 0.2, la méthode effectue 5 iterations, etc. +`1/testPart`. Par exemple, si testPart = 0.1, la méthode effectue 10 itérations, si testPart = 0.2, la méthode effectue 5 itérations, etc. - Division des données : -Pour chaque itération i, une sous-liste correspondant au pourcentage testPart (par exemple, 10 % des données) est extraite et utilisée comme jeu de test (testData). -Le reste des données sert de jeu d'entraînement (trainingData). +Pour chaque itération **i**, une sous-liste correspondant au pourcentage testPart (par exemple, 10% des données) est extraite et utilisée comme jeu de test (testData). +Le reste des données sert de jeu d'entraînement (`trainingData`). - Estimation des classes : -Chaque élément du jeu de test est classé à l’aide de la fonction MethodKNN.estimateClass(trainingData, l, k, distance) où trainingData correspond au reste des données. -Si la classe prédite correspond à la classe réelle (retournée par l.getClassification()), un compteur (totalFind) est incrémenté. +Chaque élément du jeu de test est classé à l’aide de la fonction `MethodKNN.estimateClass(trainingData, l, k, distance)`, où trainingData correspond au reste des données. +Si la classe prédite correspond à la classe réelle (retournée par `l.getClassification()`), un compteur (`totalFind`) est incrémenté. - Calcul du taux de réussite : -Après chaque itération, le taux de réussite est calculé totalFind/totalTry et ajouté à la variable taux. -- Renvoie du taux total moyen de reussite: Enfin, on divise la variable taux par le nombre d'itération afin d'obtenir un taux de reussite moyen. +Après chaque itération, le taux de réussite est calculé (`totalFind/totalTry`) et ajouté à la variable taux. +- Renvoi du taux total moyen de réussite : enfin, on divise la variable taux par le nombre d'itérations afin d'obtenir un taux de réussite moyen. --- ## Choix du meilleur K +Pour obtenir le meilleur **K**, on appelle la méthode `bestK(List<LoadableData> datas, Distance distance)` décrite plus haut. On obtient un **K** optimal, puis on appelle la méthode `robustesse(...)` avec le k trouvé plus tôt comme paramètre. -Pour obtenir le meilleur K, on appel la methode bestK(List<LoadableData> datas, Distance distance) decrite plus haut. On obtient un K optimal, puis on appel la methode robustesse(...) avec le k trouvé plutot comme parametre. - -En appliquant cette methode voici les resultats que nous avons obtenue avec: +En appliquant cette méthode, voici les résultats que nous avons obtenus avec : ##### Iris +| Distance \ k | 1 | 3 | 5 | 7 | 9 | 11 | k choisi | +|-----------------------------------|-------|-------|-------|-------|-------|-------|----------| +| Distance euclidienne | 0.96 | 0.966 | 0.96 | 0.98 | 0.98 | 0.98 | 5 | +| Distance euclidienne (normalisée) | 0.946 | 0.946 | 0.96 | 0.96 | 0.96 | 0.96 | 7 | +| Distance Manhattan | 0.953 | 0.946 | 0.946 | 0.96 | 0.96 | 0.953 | 7 | +| Distance Manhattan (normalisée) | 0.946 | 0.96 | 0.946 | 0.953 | 0.953 | 0.953 | 3 | +On obtient donc un taux de réussite plutôt élevé. À chaque fois, l'algorithme choisit le K avec le plus haut taux de réussite. En cas d'égalité, il choisit le plus petit K parmi les égalités. -| Distance \ K | 1 | 3 | 5 | 7 | 9 | 11 | K choisit | -|---------------------------------|-------|-------|-------|-------|-------|-------|----| -| Distance Euclidienne | 0.96 | 0.966 | 0.96 | 0.98 | 0.98 | 0.98 | 5 | -| Distance Euclidienne Normalisée | 0.946 | 0.946 | 0.96 | 0.96 | 0.96 | 0.96 | 7 | -| Distance Manhattan | 0.953 | 0.946 | 0.946 | 0.96 | 0.96 | 0.953 | 7 | -| Distance Manhattan Normalisée | 0.946 | 0.96 | 0.946 | 0.953 | 0.953 | 0.953 | 3 | - -On obtient donc un taux de reussiste plutôt élevé. A chaque fois l'algorithme choisit le K avec le plus haut taux de reussite. En cas d'égalité, il choisit le plus petit K parmis les égalités. - -##### Pokemon +##### Pokémon -| Distance \ K | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | K choisit | -|---------------------------------|-------|-------|-------|-------|-------|-------|----|----|----|----|----|----| -| Distance Euclidienne | 0.243 | 0.229 | 0.239 | 0.235 | 0.247 | 0.251 | 0.237 | 0.225 | 0.215 | 0.205 | 0.2 | 11 | -| Distance Euclidienne Normalisée | 0.211 | 0.229 | 0.251 | 0.245 | 0.245 | 0.239 | 0.245 | 0.243 | 0.237 | 0.239 | 0.225 | 5 | -| Distance Manhattan | 0.231 | 0.235 | 0.239 | 0.239 | 0.241 | 0.239 | 0.237 | 0.235 | 0.233 | 0.207 | 0.201 | 9 | -| Distance Manhattan Normalisée | 0.178 | 0.188 | 0.2 | 0.215 | 0.205 | 0.203 | 0.194 | 0.190 | 0.184 | 0.180 | 0.190 | 7 | +| Distance \ k | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | k choisi | +|-----------------------------------|-------|-------|-------|-------|-------|-------|----|----|----|----|----|----------| +| Distance euclidienne | 0.243 | 0.229 | 0.239 | 0.235 | 0.247 | 0.251 | 0.237 | 0.225 | 0.215 | 0.205 | 0.2 | 11 | +| Distance euclidienne (normalisée) | 0.211 | 0.229 | 0.251 | 0.245 | 0.245 | 0.239 | 0.245 | 0.243 | 0.237 | 0.239 | 0.225 | 5 | +| Distance Manhattan | 0.231 | 0.235 | 0.239 | 0.239 | 0.241 | 0.239 | 0.237 | 0.235 | 0.233 | 0.207 | 0.201 | 9 | +| Distance Manhattan (normalisée) | 0.178 | 0.188 | 0.2 | 0.215 | 0.205 | 0.203 | 0.194 | 0.190 | 0.184 | 0.180 | 0.190 | 7 | --- Le taux de reussiste est ici plus bas, cela s'explique notement par le nombre d'attribut different et la complexité a identifier le type d'un pokemon. @@ -127,6 +118,6 @@ Classification par isLegendary ## Efficacité -Comme expliqué pour chaque methode dans la partie Implementation de l'algorithme, nous avons chercher a minimiser le nombre de parcours du fichier de données et plus generalement le nombre de boucle. -L'algorithme necessite une List qui sera donnée en parametre, il est donc libre a la personne qui l'utilise de fournir l'implementation de List qu'il souhaite. De plus, pour le calcul des parametres du jeu de données ( -amplitude,valeur minimale, valeur maximal) nous avons utiliser un tableau de double afin de limiter les performances \ No newline at end of file +Comme expliqué pour chaque méthode dans la partie `Implémentation` de l'algorithme, nous avons cherché à minimiser le nombre de parcours du fichier de données, et plus généralement le nombre de boucles. +L'algorithme nécessite une `List` qui sera donnée en paramètre, il est donc libre à la personne qui l'utilise de fournir l'implémentation de `List` qu'il souhaite. De plus, pour le calcul des paramètres du jeu de données +`(amplitude, valeur minimale, valeur maximale)`, nous avons utilisé un tableau de `double` afin de limiter les performances. \ No newline at end of file