diff --git a/.gitignore b/.gitignore index a04ba19..cba13b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ Code/__pycache__/ *.pdf +Code/.ipynb_checkpoints/ diff --git a/Code/Knn.py b/Code/Knn.py index 47607c5..165f2d1 100644 --- a/Code/Knn.py +++ b/Code/Knn.py @@ -1,220 +1,221 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -* -""" -Vous allez definir une classe pour chaque algorithme que vous allez développer, -votre classe doit contenit au moins les 3 methodes definies ici bas, - * train : pour entrainer le modèle sur l'ensemble d'entrainement - * predict : pour prédire la classe d'un exemple donné - * test : pour tester sur l'ensemble de test -vous pouvez rajouter d'autres méthodes qui peuvent vous etre utiles, mais moi -je vais avoir besoin de tester les méthodes test, predict et test de votre code. -""" - -import numpy as np -import metrics - -def minkowski_distance(x,y,p_value): - return pow(sum(pow(abs(a-b),p_value) for a,b in zip(x, y)),1/p_value) - -def mode(a): - u, c = np.unique(a, return_counts=True) - return u[c.argmax()] - -# le nom de votre classe -# BayesNaif pour le modèle bayesien naif -# Knn pour le modèle des k plus proches voisins - -class Knn: #nom de la class à changer - - def __init__(self, k=5, **kwargs): - """ - c'est un Initializer. - Vous pouvez passer d'autre paramètres au besoin, - c'est à vous d'utiliser vos propres notations - """ - self.k=k - - def set_best_k(self, train, train_labels, nb_split, k_potentiel): - - ## Création des échantillons de validation croisée - shuffle_indices = np.random.permutation([i for i in range(train.shape[0])]) - validation_index = np.array_split(shuffle_indices, nb_split) - - train_index = [] - for i in range(nb_split): - train_index.append(list(set(shuffle_indices)-set(validation_index[i]))) - - ## Itération sur les valeurs de K et sur les échantillons de validation croisée - accuracy_cv = np.empty((len(k_potentiel),nb_split)) - - for k_index in range(len(k_potentiel)): - for i in range(nb_split): - self.k=k_potentiel[k_index] - self.train(train[train_index[i]], train_labels[train_index[i]], verbose=False) - cm,accuracy,precision,recall = self.test(train[validation_index[i]], train_labels[validation_index[i]], verbose=False) - accuracy_cv[k_index][i] = accuracy - - ## Calcul de la moyenne - mean_accuracy = accuracy_cv.mean(axis=1) - - ## Extraction du meilleur K - best_k = k_potentiel[int(min(np.argwhere(mean_accuracy==max(mean_accuracy))))] - - ## Assignation - self.k=best_k - - ## Retourner la valeur - return best_k - - - - def train(self, train, train_labels, verbose=True): #vous pouvez rajouter d'autres attribus au besoin - """ - c'est la méthode qui va entrainer votre modèle, - train est une matrice de type Numpy et de taille nxm, avec - n : le nombre d'exemple d'entrainement dans le dataset - m : le mobre d'attribus (le nombre de caractéristiques) - - train_labels : est une matrice numpy de taille nx1 - - vous pouvez rajouter d'autres arguments, il suffit juste de - les expliquer en commentaire - - - - ------------ - Après avoir fait l'entrainement, faites maintenant le test sur - les données d'entrainement - IMPORTANT : - Vous devez afficher ici avec la commande print() de python, - - la matrice de confision (confusion matrix) - - l'accuracy - - la précision (precision) - - le rappel (recall) - - Bien entendu ces tests doivent etre faits sur les données d'entrainement - nous allons faire d'autres tests sur les données de test dans la méthode test() - """ - - # on fait seulement utiliser les données du jeu d'entrainement comme paramètre d'un modèle Knn - self.train_set=train - self.train_labels=train_labels - - n,m = train.shape - nn=np.empty((n,self.k,2)) - - self.minkowski_p=m - - # On trouve les k plus proches voisins et leur distance pour chacunes des observations du training set - # On enlève la valeur testée de la liste des points pour lesquels on mesure la distance car on sait qu'elle vaut 0. - # On veut tester sur les autres points seulement - for x in range(n): - i_range = [i for i in range(n)] - i_range.pop(x) - nn[x,:,0]=i_range[0:self.k] - nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[i_range[0:self.k]],train[x],self.minkowski_p) - for i in i_range[self.k:n]: - dist = minkowski_distance(self.train_set[i],train[x],self.minkowski_p) - nn_dist=nn[x,:,1] - distdiff = nn_dist-dist - max_distdiff=max(distdiff) - if(max_distdiff>0): - pos_changement = np.argwhere(nn_dist==max(nn_dist))[0] - nn[x,pos_changement,0]=i - nn[x,pos_changement,1]=max_distdiff - # on retrouve le label modal pour chacunes des observations - nn_labels = self.train_labels[nn[:,:,0].astype(np.int)] - nn_mode_label = np.apply_along_axis(mode,1,nn_labels) - - # on construit la matrice de confusion - cm = metrics.confusion_matrix(train_labels,nn_mode_label) - accuracy, precision, recall = metrics.prediction_metrics(cm,train_labels,nn_mode_label) - if (verbose): - metrics.print_prediction_metrics(cm,accuracy,precision,recall) - - return cm,accuracy,precision,recall - - - def predict(self, exemple, label, verbose=True): - """ - Prédire la classe d'un exemple donné en entrée - exemple est de taille 1xm - - si la valeur retournée est la meme que la veleur dans label - alors l'exemple est bien classifié, si non c'est une missclassification - - """ - n,m = self.train_set.shape - nn=np.empty((self.k,2)) - nn[:,0]=[i for i in range(self.k)] - nn[:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[0:self.k],exemple,self.minkowski_p) - for i in range(self.k,n): - dist = minkowski_distance(self.train_set[i],exemple,self.minkowski_p) - nn_dist=nn[:,1] - distdiff = nn_dist-dist - max_distdiff=max(distdiff) - if(max_distdiff>0): - pos_changement = np.argwhere(nn_dist==max(nn_dist))[0] - nn[pos_changement,0]=i - nn[pos_changement,1]=max_distdiff - nn_labels = self.train_labels[nn[:,0].astype(np.int)] - nn_mode_label = mode(nn_labels) - - if (verbose): - print("Observé:"+str(label)+" Prédit:"+str(nn_mode_label)) - - return (nn_mode_label,label) - - def test(self, test, test_labels, verbose=True): - """ - c'est la méthode qui va tester votre modèle sur les données de test - l'argument test est une matrice de type Numpy et de taille nxm, avec - n : le nombre d'exemple de test dans le dataset - m : le mobre d'attribus (le nombre de caractéristiques) - - test_labels : est une matrice numpy de taille nx1 - - vous pouvez rajouter d'autres arguments, il suffit juste de - les expliquer en commentaire - - Faites le test sur les données de test, et afficher : - - la matrice de confision (confusion matrix) - - l'accuracy - - la précision (precision) - - le rappel (recall) - - Bien entendu ces tests doivent etre faits sur les données de test seulement - - """ - - n,m = test.shape - n_ex,m_ex = self.train_set.shape - nn=np.empty((n,self.k,2)) - # Boucle sur chaque ligne du jeu de test - for x in range(n): - nn[x,:,0]=[i for i in range(self.k)] - nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[0:self.k],test[x],self.minkowski_p) - for i in range(self.k,n_ex): - dist = minkowski_distance(self.train_set[i],test[x],self.minkowski_p) - nn_dist=nn[x,:,1] - distdiff = nn_dist-dist - max_distdiff=max(distdiff) - if(max_distdiff>0): - pos_changement = np.argwhere(nn_dist==max(nn_dist))[0] - nn[x,pos_changement,0]=i - nn[x,pos_changement,1]=max_distdiff - nn_labels = self.train_labels[nn[:,:,0].astype(np.int)] - nn_mode_label = np.apply_along_axis(mode,1,nn_labels) - # on construit la matrice de confusion - cm = metrics.confusion_matrix(test_labels,nn_mode_label) - accuracy, precision, recall = metrics.prediction_metrics(cm,test_labels,nn_mode_label) - if (verbose): - metrics.print_prediction_metrics(cm,accuracy,precision,recall) - - return cm,accuracy,precision,recall - - - - - # Vous pouvez rajouter d'autres méthodes et fonctions, - # il suffit juste de les commenter. +#!/usr/bin/env python3 +# -*- coding: utf-8 -* +""" +Vous allez definir une classe pour chaque algorithme que vous allez développer, +votre classe doit contenit au moins les 3 methodes definies ici bas, + * train : pour entrainer le modèle sur l'ensemble d'entrainement + * predict : pour prédire la classe d'un exemple donné + * test : pour tester sur l'ensemble de test +vous pouvez rajouter d'autres méthodes qui peuvent vous etre utiles, mais moi +je vais avoir besoin de tester les méthodes test, predict et test de votre code. +""" + +import numpy as np +import metrics + +def minkowski_distance(x,y,p_value): + return pow(sum(pow(abs(a-b),p_value) for a,b in zip(x, y)),1/p_value) + +def mode(a): + u, c = np.unique(a, return_counts=True) + return u[c.argmax()] + +# le nom de votre classe +# BayesNaif pour le modèle bayesien naif +# Knn pour le modèle des k plus proches voisins + +class Knn: #nom de la class à changer + + def __init__(self, k=5, **kwargs): + """ + c'est un Initializer. + Vous pouvez passer d'autre paramètres au besoin, + c'est à vous d'utiliser vos propres notations + """ + self.k=k + + def set_best_k(self, train, train_labels, nb_split, k_potentiel): + ## Création des échantillons de validation croisée + shuffle_indices = np.random.permutation([i for i in range(train.shape[0])]) + validation_index = np.array_split(shuffle_indices, nb_split) + + train_index = [] + for i in range(nb_split): + train_index.append(list(set(shuffle_indices)-set(validation_index[i]))) + + ## Itération sur les valeurs de K et sur les échantillons de validation croisée + accuracy_cv = np.empty((len(k_potentiel),nb_split)) + + for k_index in range(len(k_potentiel)): + for i in range(nb_split): + self.k=k_potentiel[k_index] + self.train(train[train_index[i]], train_labels[train_index[i]], verbose=False) + cm,accuracy,precision,recall = self.test(train[validation_index[i]], train_labels[validation_index[i]], verbose=False) + accuracy_cv[k_index][i] = accuracy + + ## Calcul de la moyenne + mean_accuracy = accuracy_cv.mean(axis=1) + + ## Extraction du meilleur K + best_k = k_potentiel[int(min(np.argwhere(mean_accuracy==max(mean_accuracy))))] + + ## Assignation + self.k=best_k + + print("Le meilleur k est: "+str(best_k)) + + ## Retourner la valeur + return best_k + + + + def train(self, train, train_labels, verbose=True): #vous pouvez rajouter d'autres attribus au besoin + """ + c'est la méthode qui va entrainer votre modèle, + train est une matrice de type Numpy et de taille nxm, avec + n : le nombre d'exemple d'entrainement dans le dataset + m : le mobre d'attribus (le nombre de caractéristiques) + + train_labels : est une matrice numpy de taille nx1 + + vous pouvez rajouter d'autres arguments, il suffit juste de + les expliquer en commentaire + + + + ------------ + Après avoir fait l'entrainement, faites maintenant le test sur + les données d'entrainement + IMPORTANT : + Vous devez afficher ici avec la commande print() de python, + - la matrice de confision (confusion matrix) + - l'accuracy + - la précision (precision) + - le rappel (recall) + + Bien entendu ces tests doivent etre faits sur les données d'entrainement + nous allons faire d'autres tests sur les données de test dans la méthode test() + """ + + # on fait seulement utiliser les données du jeu d'entrainement comme paramètre d'un modèle Knn + self.train_set=train + self.train_labels=train_labels + + n,m = train.shape + nn=np.empty((n,self.k,2)) + + self.minkowski_p=m + + # On trouve les k plus proches voisins et leur distance pour chacunes des observations du training set + # On enlève la valeur testée de la liste des points pour lesquels on mesure la distance car on sait qu'elle vaut 0. + # On veut tester sur les autres points seulement + for x in range(n): + i_range = [i for i in range(n)] + i_range.pop(x) + nn[x,:,0]=i_range[0:self.k] + nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[i_range[0:self.k]],train[x],self.minkowski_p) + for i in i_range[self.k:n]: + dist = minkowski_distance(self.train_set[i],train[x],self.minkowski_p) + nn_dist=nn[x,:,1] + distdiff = nn_dist-dist + max_distdiff=max(distdiff) + if(max_distdiff>0): + pos_changement = np.argwhere(nn_dist==max(nn_dist))[0] + nn[x,pos_changement,0]=i + nn[x,pos_changement,1]=max_distdiff + # on retrouve le label modal pour chacunes des observations + nn_labels = self.train_labels[nn[:,:,0].astype(np.int)] + nn_mode_label = np.apply_along_axis(mode,1,nn_labels) + + # on construit la matrice de confusion + cm = metrics.confusion_matrix(train_labels,nn_mode_label) + accuracy, precision, recall = metrics.prediction_metrics(cm,train_labels,nn_mode_label) + if (verbose): + metrics.print_prediction_metrics(cm,accuracy,precision,recall) + + return cm,accuracy,precision,recall + + + def predict(self, exemple, label, verbose=True): + """ + Prédire la classe d'un exemple donné en entrée + exemple est de taille 1xm + + si la valeur retournée est la meme que la veleur dans label + alors l'exemple est bien classifié, si non c'est une missclassification + + """ + n,m = self.train_set.shape + nn=np.empty((self.k,2)) + nn[:,0]=[i for i in range(self.k)] + nn[:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[0:self.k],exemple,self.minkowski_p) + for i in range(self.k,n): + dist = minkowski_distance(self.train_set[i],exemple,self.minkowski_p) + nn_dist=nn[:,1] + distdiff = nn_dist-dist + max_distdiff=max(distdiff) + if(max_distdiff>0): + pos_changement = np.argwhere(nn_dist==max(nn_dist))[0] + nn[pos_changement,0]=i + nn[pos_changement,1]=max_distdiff + nn_labels = self.train_labels[nn[:,0].astype(np.int)] + nn_mode_label = mode(nn_labels) + + if (verbose): + print("Observé:"+str(label)+" Prédit:"+str(nn_mode_label)) + + return (nn_mode_label,label) + + def test(self, test, test_labels, verbose=True): + """ + c'est la méthode qui va tester votre modèle sur les données de test + l'argument test est une matrice de type Numpy et de taille nxm, avec + n : le nombre d'exemple de test dans le dataset + m : le mobre d'attribus (le nombre de caractéristiques) + + test_labels : est une matrice numpy de taille nx1 + + vous pouvez rajouter d'autres arguments, il suffit juste de + les expliquer en commentaire + + Faites le test sur les données de test, et afficher : + - la matrice de confision (confusion matrix) + - l'accuracy + - la précision (precision) + - le rappel (recall) + + Bien entendu ces tests doivent etre faits sur les données de test seulement + + """ + + n,m = test.shape + n_ex,m_ex = self.train_set.shape + nn=np.empty((n,self.k,2)) + # Boucle sur chaque ligne du jeu de test + for x in range(n): + nn[x,:,0]=[i for i in range(self.k)] + nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[0:self.k],test[x],self.minkowski_p) + for i in range(self.k,n_ex): + dist = minkowski_distance(self.train_set[i],test[x],self.minkowski_p) + nn_dist=nn[x,:,1] + distdiff = nn_dist-dist + max_distdiff=max(distdiff) + if(max_distdiff>0): + pos_changement = np.argwhere(nn_dist==max(nn_dist))[0] + nn[x,pos_changement,0]=i + nn[x,pos_changement,1]=max_distdiff + nn_labels = self.train_labels[nn[:,:,0].astype(np.int)] + nn_mode_label = np.apply_along_axis(mode,1,nn_labels) + # on construit la matrice de confusion + cm = metrics.confusion_matrix(test_labels,nn_mode_label) + accuracy, precision, recall = metrics.prediction_metrics(cm,test_labels,nn_mode_label) + if (verbose): + metrics.print_prediction_metrics(cm,accuracy,precision,recall) + + return cm,accuracy,precision,recall + + + + + # Vous pouvez rajouter d'autres méthodes et fonctions, + # il suffit juste de les commenter. diff --git a/Code/Rapport-Partiel.ipynb b/Code/Rapport-Partiel.ipynb new file mode 100644 index 0000000..855d8ef --- /dev/null +++ b/Code/Rapport-Partiel.ipynb @@ -0,0 +1,778 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Introduction\n", + "\n", + "## Définitions\n", + "\n", + "La **matrice de confusion** est un tableau où on décompte les valeurs réelle O et prédites S pour chaque observation du jeu de données dans un problème de classification. Par sa conception, on peut valider rapidement le nombre d'observations où la prédiction est égale à la valeur réelle sur la diagonale de la matrice. Par convention, on place les valeurs prédites à la verticale et les valeurs observées à l'horizontale. Lorsque le nombre de modalités de la variable prédite est de deux, on a un problème de classification binaire et on obtient alors le décompte des vrais positifs, faux positifs, faux négatifs et vrais négatifs.\n", + "\n", + "La **précision** correspont à la proportion d'observations où la prédiction et la valeur réelle est dans une même classe par rapport au nombre d'observations où la prédiction est dans cette classe\n", + "\n", + "$$ \\text{Précision}_c = \\frac{\\sum_{i=1}^N 1_{s_i=c}1_{o_i=c}}{\\sum_{i=1}^N 1_{s_i=c}}$$\n", + "\n", + "Le **rappel** correspond à la proportions d'observations où la prédiction est dans une classe par rapport au nombre d'observations où la valeur réelle est dans cette classe.\n", + "\n", + "$$ \\text{Rappel}_c =  \\frac{\\sum_{i=1}^N 1_{s_i=c}}{\\sum_{i=1}^N 1_{o_i=c}}$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Librairies utilisées\n", + "\n", + "Le project actuel est programmé dans le langage Python 3, et ce rapport est produit à l'aide de Jupyter Notebook. Seule les librairie standard `numpy` et `math` est utilisée, les autres ont été développées dans le cadre de ce projet." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# Librairies standard\n", + "import numpy as np\n", + "import math\n", + "# Librairies développées par l'étudiant\n", + "import load_datasets as ld\n", + "import BayesNaif\n", + "import Knn\n", + "import metrics" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jeux de données\n", + "\n", + "Ce projet utilise 3 jeux de données: [Iris](https://archive.ics.uci.edu/ml/datasets/Iris), [MONKS](https://archive.ics.uci.edu/ml/datasets/MONK's+Problems) et [Congressional Voting Records Dataset](https://archive.ics.uci.edu/ml/datasets/Congressional+Voting+Records)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Algorithme des k plus proches voisins (kNN)\n", + "\n", + "Dans cette section, on présente les résultats obtenus pour l'algorithme des k plus proches voisins. Ce n'est pas un algorithme d'apprentissage à proprement parler, car il n'y a aucun modèle d'entrainé. On prédit la classe d'un nouvel élément en recherchant les k plus proches voisins selon une métrique choisie. Dans notre cas, nous utiliserons la distance de Minkowski, qui est une généralisation de la distance euclidienne et de la distance de Manhattan à l'aide d'un paramètre p. \n", + "\n", + "$${\\displaystyle D\\left(X,Y\\right)=\\left(\\sum _{i=1}^{N}|o_{i}-s_{i}|^{p}\\right)^{1/p}}$$\n", + "\n", + "On peut ainsi itérer sur différentes valeurs de ce paramètre pour trouver la mesure la plus adaptée au problème, tout en réutilisant la même fonction. Cette métrique s'utilise aurant pour des domaines de valeurs continus que discrets.\n", + "\n", + "## Pseudocode\n", + "\n", + "- Entrainement\n", + "\n", + "```\n", + "Copier le jeu d'entrainement et les étiquettes d'entrainement dans la mémoire du modèle\n", + "```\n", + "\n", + "- Prédiction Knn\n", + "```\n", + "Pour une observation x_i:\n", + " Entrainement <- Vrai si on fait le premier entrainement\n", + " T = copie jeu d'entrainement\n", + " L = copie des étiquettes d'entrainement\n", + " K = tableau de paires (point, distance) de longueur k\n", + " Si Entrainement:\n", + " Enlever x de T et l'étiquette de x_i de L\n", + " Pour chaque observation t_j, j=[1,k]) de T:\n", + " d(x_i,t_i) = distance de Minkowski entre x_i et t_j\n", + " K[j] <- (t_i,d(x_i,t_j)) \n", + " Pour chaque observation t_j, j=[k+1,N-1] de T:\n", + " d(x,t_i) = distance de Minkowski entre x_i et t_j\n", + " d_max <- distance maximum dans K\n", + " pos_d_max <- position de d_max dans K\n", + " Si d(x_i,t_j) < d_max\n", + " Remplacer le point K[pos_d_max] par (t_j,d(x,t_j))\n", + " s <- mode des valeurs des étiquettes des points dans K\n", + " retourner s\n", + "```\n", + "\n", + "- Test\n", + "\n", + "```\n", + "Pour chaque observation x_i, i=1,N:\n", + " S_i <- Prédiction(x_i)\n", + "M <- matrice de confusion avec les étiquettes d'entrainement et les étiquettes S\n", + "Calculer les métriques depuis M\n", + "```\n", + "\n", + "- Validation croisée\n", + "\n", + "```\n", + "K <- Valeurs à tester pour le nombre de voisins\n", + "Pour un jeu d'entrainement x\n", + "Permuter aléatoirement les nombre de 1 à N\n", + "Diviser la permutation en L groupes approximativement égaux\n", + "Pour l dans L:\n", + " \n", + "\n", + "Pour k dans K:\n", + " Pour l dans L:\n", + " Effectuer l'entrainement avec k voisins, x[sans l] comme jeu d'entrainement \n", + " Effectuer le test avec x[l] comme jeu de validation\n", + " Calculer l'exactitude\n", + " Prendre la moyenne des exactitudes\n", + "Prendre le k avec la meilleur exactitude moyenne\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Iris Dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On utilise 70% des données pour le jeu d'entrainement et 30% des données pour le jeu de test" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "train1, train_labels1, test1, test_labels1 = ld.load_iris_dataset(train_ratio = 0.7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On crée un premier modèle afin d'identifier la meilleure valeur de k" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/francois/gitea/ift7025-projet/Code/metrics.py:40: RuntimeWarning: invalid value encountered in double_scalars\n", + " precision.append(cm[label_num,label_num] / sum(cm[:,label_num]))\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Le meilleur k est: 9\n" + ] + } + ], + "source": [ + "findbest_Knn = Knn.Knn()\n", + "meilleur_k = findbest_Knn.set_best_k(train1, train_labels1, nb_split=5, k_potentiel=range(2,12))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On crée maintenant un nouveau modèle où on initialise la valeur de K avec celle trouvée précédemment" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "myKnn = Knn.Knn(meilleur_k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On effectue l'entrainement du modèle (la copie du jeu d'entrainement et des étiquettes en mémoire) et on obtient les mesures de validation pour ce jeu d'entraînement. Les valeurs des métriques de précision et de rappel sont calculées pour chacune des étiquettes." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[35. 0. 0.]\n", + " [ 0. 32. 1.]\n", + " [ 0. 3. 34.]]\n", + "\n", + "Accuracy:\n", + "0.9619047619047619\n", + "\n", + "Precision:\n", + "[1.0, 0.9142857142857143, 0.9714285714285714]\n", + "\n", + "Recall\n", + "[1.0, 0.9696969696969697, 0.918918918918919]\n" + ] + } + ], + "source": [ + "training_iris_knn = myKnn.train(train1, train_labels1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On effectue maintenant le test avec l'échantillon de test" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[15. 0. 0.]\n", + " [ 0. 16. 1.]\n", + " [ 0. 1. 12.]]\n", + "\n", + "Accuracy:\n", + "0.9555555555555556\n", + "\n", + "Precision:\n", + "[1.0, 0.9411764705882353, 0.9230769230769231]\n", + "\n", + "Recall\n", + "[1.0, 0.9411764705882353, 0.9230769230769231]\n" + ] + } + ], + "source": [ + "test_iris_knn = myKnn.test(test1, test_labels1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Monks Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "train2, train_labels2, test2, test_labels2 = ld.load_monks_dataset(1)\n", + "train3, train_labels3, test3, test_labels3 = ld.load_monks_dataset(2)\n", + "train4, train_labels4, test4, test_labels4 = ld.load_monks_dataset(3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Premier sous-ensemble" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On identifie la meilleure valeur de k" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Le meilleur k est: 4\n" + ] + } + ], + "source": [ + "findbest_Knn = Knn.Knn()\n", + "meilleur_k = findbest_Knn.set_best_k(train2, train_labels2, nb_split=5, k_potentiel=range(2,12))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "myKnn2 = Knn.Knn(meilleur_k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue l'entrainement du modèle" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[32. 30.]\n", + " [16. 46.]]\n", + "\n", + "Accuracy:\n", + "0.6290322580645161\n", + "\n", + "Precision:\n", + "[0.6666666666666666, 0.6052631578947368]\n", + "\n", + "Recall\n", + "[0.5161290322580645, 0.7419354838709677]\n" + ] + } + ], + "source": [ + "training_monks1_knn = myKnn2.train(train2, train_labels2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue maintenant le test avec l'échantillon de test" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[129. 87.]\n", + " [ 38. 178.]]\n", + "\n", + "Accuracy:\n", + "0.7106481481481481\n", + "\n", + "Precision:\n", + "[0.7724550898203593, 0.6716981132075471]\n", + "\n", + "Recall\n", + "[0.5972222222222222, 0.8240740740740741]\n" + ] + } + ], + "source": [ + "test_monks1_knn = myKnn2.test(test2, test_labels2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Second sous-ensemble" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On identifie la meilleure valeur de k" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Le meilleur k est: 5\n" + ] + } + ], + "source": [ + "findbest_Knn = Knn.Knn()\n", + "meilleur_k = findbest_Knn.set_best_k(train3, train_labels3, nb_split=5, k_potentiel=range(2,12))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "myKnn3 = Knn.Knn(meilleur_k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue l'entrainement du modèle" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[104. 1.]\n", + " [ 63. 1.]]\n", + "\n", + "Accuracy:\n", + "0.621301775147929\n", + "\n", + "Precision:\n", + "[0.6227544910179641, 0.5]\n", + "\n", + "Recall\n", + "[0.9904761904761905, 0.015625]\n" + ] + } + ], + "source": [ + "training_monks2_knn = myKnn3.train(train3, train_labels3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue maintenant le test avec l'échantillon de test" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[286. 4.]\n", + " [133. 9.]]\n", + "\n", + "Accuracy:\n", + "0.6828703703703703\n", + "\n", + "Precision:\n", + "[0.6825775656324582, 0.6923076923076923]\n", + "\n", + "Recall\n", + "[0.9862068965517241, 0.06338028169014084]\n" + ] + } + ], + "source": [ + "test_monks2_knn = myKnn3.test(test3, test_labels3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Troisième sous-ensemble" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On identifie la meilleure valeur de k" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Le meilleur k est: 5\n" + ] + } + ], + "source": [ + "findbest_Knn = Knn.Knn()\n", + "meilleur_k = findbest_Knn.set_best_k(train4, train_labels4, nb_split=5, k_potentiel=range(2,12))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "myKnn4 = Knn.Knn(meilleur_k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue l'entrainement du modèle" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[27. 35.]\n", + " [ 1. 59.]]\n", + "\n", + "Accuracy:\n", + "0.7049180327868853\n", + "\n", + "Precision:\n", + "[0.9642857142857143, 0.6276595744680851]\n", + "\n", + "Recall\n", + "[0.43548387096774194, 0.9833333333333333]\n" + ] + } + ], + "source": [ + "training_monks3_knn = myKnn4.train(train4, train_labels4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue maintenant le test avec l'échantillon de test" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[ 99. 105.]\n", + " [ 8. 220.]]\n", + "\n", + "Accuracy:\n", + "0.7384259259259259\n", + "\n", + "Precision:\n", + "[0.9252336448598131, 0.676923076923077]\n", + "\n", + "Recall\n", + "[0.4852941176470588, 0.9649122807017544]\n" + ] + } + ], + "source": [ + "test_monks3_knn = myKnn4.test(test4, test_labels4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Congressional Voting Records Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "train5, train_labels5, test5, test_labels5 = ld.load_congressional_dataset(0.7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On identifie la meilleure valeur de k" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Le meilleur k est: 9\n" + ] + } + ], + "source": [ + "findbest_Knn = Knn.Knn()\n", + "meilleur_k = findbest_Knn.set_best_k(train5, train_labels5, nb_split=5, k_potentiel=range(2,12))" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "myKnn5 = Knn.Knn(meilleur_k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue l'entrainement du modèle" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[ 76. 33.]\n", + " [ 15. 180.]]\n", + "\n", + "Accuracy:\n", + "0.8421052631578947\n", + "\n", + "Precision:\n", + "[0.8351648351648352, 0.8450704225352113]\n", + "\n", + "Recall\n", + "[0.6972477064220184, 0.9230769230769231]\n" + ] + } + ], + "source": [ + "training_congres_knn = myKnn5.train(train5, train_labels5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- On effectue maintenant le test avec l'échantillon de test" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Matrice de confusion:\n", + "[[42. 17.]\n", + " [ 6. 66.]]\n", + "\n", + "Accuracy:\n", + "0.8244274809160306\n", + "\n", + "Precision:\n", + "[0.875, 0.7951807228915663]\n", + "\n", + "Recall\n", + "[0.711864406779661, 0.9166666666666666]\n" + ] + } + ], + "source": [ + "test_congres_knn = myKnn5.test(test5, test_labels5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Algorithme Naive Bayes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Code/entrainer_tester.py b/Code/entrainer_tester.py index cb4ff4b..1c22306 100644 --- a/Code/entrainer_tester.py +++ b/Code/entrainer_tester.py @@ -1,65 +1,65 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -* -import numpy as np -import sys -import load_datasets as ld -import BayesNaif # importer la classe du classifieur bayesien -import Knn # importer la classe du Knn -#importer d'autres fichiers et classes si vous en avez développés - - -""" -C'est le fichier main duquel nous allons tout lancer -Vous allez dire en commentaire c'est quoi les paramètres que vous avez utilisés -En gros, vous allez : -1- Initialiser votre classifieur avec ses paramètres -2- Charger les datasets -3- Entrainer votre classifieur -4- Le tester - -""" - -# Charger/lire les datasets - -train, train_labels, test, test_labels = ld.load_iris_dataset(0.7) -train, train_labels, test, test_labels = ld.load_congressional_dataset(0.7) -train, train_labels, test, test_labels = ld.load_monks_dataset(1) -train, train_labels, test, test_labels = ld.load_monks_dataset(2) -train, train_labels, test, test_labels = ld.load_monks_dataset(3) - -# KNN - -## Choix du meilleur K -findbest_Knn = Knn.Knn() -meilleur_k = findbest_Knn.set_best_k(train, train_labels, nb_split=5, k_potentiel=range(5,15)) -print("Le meilleur K est:"+str(meilleur_k)+"\n\n") - -## Initializer/instanciez vos classifieurs avec leurs paramètres -myKnn = Knn.Knn(meilleur_k) - -## Entrainez votre classifieur -myKnn.train(train, train_labels) - -## Tester votre classifieur -myKnn.test(test, test_labels) - -# Naive Bayes - -## Initializer/instanciez vos classifieurs avec leurs paramètres -BN = BayesNaif.BayesNaif(False) - -## Entrainez votre classifieur -BN.train(train, train_labels) - -## Prediction -BN.test(train, train_labels) - -## Test -BN.test(test,test_labels) - - - - - - - +#!/usr/bin/env python3 +# -*- coding: utf-8 -* +import numpy as np +import load_datasets as ld +import BayesNaif +import Knn +import metrics +#importer d'autres fichiers et classes si vous en avez développés + + +""" +C'est le fichier main duquel nous allons tout lancer +Vous allez dire en commentaire c'est quoi les paramètres que vous avez utilisés +En gros, vous allez : +1- Initialiser votre classifieur avec ses paramètres +2- Charger les datasets +3- Entrainer votre classifieur +4- Le tester + +""" + +# Charger/lire les datasets + +train, train_labels, test, test_labels = ld.load_iris_dataset(0.7) +train, train_labels, test, test_labels = ld.load_congressional_dataset(0.7) +train, train_labels, test, test_labels = ld.load_monks_dataset(1) +train, train_labels, test, test_labels = ld.load_monks_dataset(2) +train, train_labels, test, test_labels = ld.load_monks_dataset(3) + +# KNN + +## Choix du meilleur K +findbest_Knn = Knn.Knn() +meilleur_k = findbest_Knn.set_best_k(train, train_labels, nb_split=5, k_potentiel=range(5,15)) +print("Le meilleur K est:"+str(meilleur_k)+"\n\n") + +## Initializer/instanciez vos classifieurs avec leurs paramètres +myKnn = Knn.Knn(meilleur_k) + +## Entrainez votre classifieur +myKnn.train(train, train_labels) + +## Tester votre classifieur +myKnn.test(test, test_labels) + +# Naive Bayes + +## Initializer/instanciez vos classifieurs avec leurs paramètres +BN = BayesNaif.BayesNaif(False) + +## Entrainez votre classifieur +BN.train(train, train_labels) + +## Prediction +BN.test(train, train_labels) + +## Test +BN.test(test,test_labels) + + + + + + + diff --git a/Code/load_datasets.py b/Code/load_datasets.py index b3cd6ea..25781de 100644 --- a/Code/load_datasets.py +++ b/Code/load_datasets.py @@ -1,216 +1,216 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -* -import numpy as np -import random - -def load_iris_dataset(train_ratio=0.7): - """Cette fonction a pour but de lire le dataset Iris - - Args: - train_ratio: le ratio des exemples (ou instances) qui vont etre attribués à l'entrainement, - le rest des exemples va etre utilisé pour les tests. - Par exemple : si le ratio est 50%, il y aura 50% des exemple (75 exemples) qui vont etre utilisé - pour l'entrainement, et 50% (75 exemples) pour le test. - - Retours: - Cette fonction doit retourner 4 matrices de type Numpy, train, train_labels, test, et test_labels - - - train : une matrice numpy qui contient les exemples qui vont etre utilisés pour l'entrainement, chaque - ligne dans cette matrice représente un exemple (ou instance) d'entrainement. - - - train_labels : contient les labels (ou les étiquettes) pour chaque exemple dans train, de telle sorte - que : train_labels[i] est le label (ou l'etiquette) pour l'exemple train[i] - - - test : une matrice numpy qui contient les exemples qui vont etre utilisés pour le test, chaque - ligne dans cette matrice représente un exemple (ou instance) de test. - - - test_labels : contient les labels (ou les étiquettes) pour chaque exemple dans test, de telle sorte - que : test_labels[i] est le label (ou l'etiquette) pour l'exemple test[i] - """ - - random.seed(1) # Pour avoir les meme nombres aléatoires à chaque initialisation. - - # Vous pouvez utiliser des valeurs numériques pour les différents types de classes, tel que : - conversion_labels = {'Iris-setosa': 0, 'Iris-versicolor' : 1, 'Iris-virginica' : 2} - - # Le fichier du dataset est dans le dossier datasets en attaché - - f = open('datasets/bezdekIris.data', 'r') - lines=[line.strip() for line in f.readlines()] - f.close() - - lines=[line.split(",") for line in lines if line] - - features=[] - labels=[] - - for line in lines: - features.append(line[0:4]) - labels.append(conversion_labels[line[4]]) - - np_features=np.array(features,dtype=np.float) - np_labels=np.array(labels,dtype=np.int) - - n_obs = np_features.shape[0] - - n_train = int(n_obs*train_ratio) - - all_indices = [i for i in range(n_obs)] - random.shuffle(all_indices) - - train_index = all_indices[0:n_train] - test_index = all_indices[n_train:n_obs] - - train = np_features[train_index] - train_labels = np_labels[train_index] - test = np_features[test_index] - test_labels = np_labels[test_index] - - - # REMARQUE très importante : - # remarquez bien comment les exemples sont ordonnés dans - # le fichier du dataset, ils sont ordonnés par type de fleur, cela veut dire que - # si vous lisez les exemples dans cet ordre et que si par exemple votre ration est de 60%, - # vous n'allez avoir aucun exemple du type Iris-virginica pour l'entrainement, pensez - # donc à utiliser la fonction random.shuffle pour melanger les exemples du dataset avant de séparer - # en train et test. - - - # Tres important : la fonction doit retourner 4 matrices (ou vecteurs) de type Numpy. - return (train, train_labels, test, test_labels) - - - -def load_congressional_dataset(train_ratio): - """Cette fonction a pour but de lire le dataset Congressional Voting Records - - Args: - train_ratio: le ratio des exemples (ou instances) qui vont servir pour l'entrainement, - le rest des exemples va etre utilisé pour les test. - - Retours: - Cette fonction doit retourner 4 matrices de type Numpy, train, train_labels, test, et test_labels - - - train : une matrice numpy qui contient les exemples qui vont etre utilisés pour l'entrainement, chaque - ligne dans cette matrice représente un exemple (ou instance) d'entrainement. - - - train_labels : contient les labels (ou les étiquettes) pour chaque exemple dans train, de telle sorte - que : train_labels[i] est le label (ou l'etiquette) pour l'exemple train[i] - - - test : une matrice numpy qui contient les exemples qui vont etre utilisés pour le test, chaque - ligne dans cette matrice représente un exemple (ou instance) de test. - - - test_labels : contient les labels (ou les étiquettes) pour chaque exemple dans test, de telle sorte - que : test_labels[i] est le label (ou l'etiquette) pour l'exemple test[i] - """ - - random.seed(1) # Pour avoir les meme nombres aléatoires à chaque initialisation. - - # Vous pouvez utiliser un dictionnaire pour convertir les attributs en numériques - # Notez bien qu'on a traduit le symbole "?" pour une valeur numérique - # Vous pouvez biensur utiliser d'autres valeurs pour ces attributs - conversion_labels = {'republican' : 0, 'democrat' : 1, - 'n' : 0, 'y' : 1, '?' : 2} - - # Le fichier du dataset est dans le dossier datasets en attaché - f = open('datasets/house-votes-84.data', 'r') - lines=[line.strip() for line in f.readlines()] - f.close() - - lines=[line.split(",") for line in lines if line] - - features=[] - labels=[] - - for line in lines: - features.append([conversion_labels[i] for i in line[1:17]]) - labels.append(conversion_labels[line[0]]) - - np_features=np.array(features,dtype=np.float) - np_labels=np.array(labels,dtype=np.int) - - n_obs = np_features.shape[0] - - - n_train = int(n_obs*train_ratio) - - all_indices = [i for i in range(n_obs)] - random.shuffle(all_indices) - - train_index = all_indices[0:n_train] - test_index = all_indices[n_train:n_obs] - - train = np_features[train_index] - train_labels = np_labels[train_index] - test = np_features[test_index] - test_labels = np_labels[test_index] - - # La fonction doit retourner 4 structures de données de type Numpy. - return (train, train_labels, test, test_labels) - - -def load_monks_dataset(numero_dataset): - """Cette fonction a pour but de lire le dataset Monks - - Notez bien que ce dataset est différent des autres d'un point de vue - exemples entrainement et exemples de tests. - Pour ce dataset, nous avons 3 différents sous problèmes, et pour chacun - nous disposons d'un fichier contenant les exemples d'entrainement et - d'un fichier contenant les fichiers de tests. Donc nous avons besoin - seulement du numéro du sous problème pour charger le dataset. - - Args: - numero_dataset: lequel des sous problèmes nous voulons charger (1, 2 ou 3 ?) - par exemple, si numero_dataset=2, vous devez lire : - le fichier monks-2.train contenant les exemples pour l'entrainement - et le fichier monks-2.test contenant les exemples pour le test - les fichiers sont tous dans le dossier datasets - Retours: - Cette fonction doit retourner 4 matrices de type Numpy, train, train_labels, test, et test_labels - - - train : une matrice numpy qui contient les exemples qui vont etre utilisés pour l'entrainement, chaque - ligne dans cette matrice représente un exemple (ou instance) d'entrainement. - - train_labels : contient les labels (ou les étiquettes) pour chaque exemple dans train, de telle sorte - que : train_labels[i] est le label (ou l'etiquette) pour l'exemple train[i] - - - test : une matrice numpy qui contient les exemples qui vont etre utilisés pour le test, chaque - ligne dans cette matrice représente un exemple (ou instance) de test. - - test_labels : contient les labels (ou les étiquettes) pour chaque exemple dans test, de telle sorte - que : test_labels[i] est le label (ou l'etiquette) pour l'exemple test[i] - """ - - - # TODO : votre code ici, vous devez lire les fichiers .train et .test selon l'argument numero_dataset - - f = open('datasets/monks-'+str(numero_dataset)+'.train', 'r') - lines_train=[line.strip() for line in f.readlines()] - f.close() - - f = open('datasets/monks-'+str(numero_dataset)+'.test', 'r') - lines_test=[line.strip() for line in f.readlines()] - f.close() - - lines_train=[line.split(" ") for line in lines_train if line] - lines_test=[line.split(" ") for line in lines_test if line] - - features_train=[] - labels_train=[] - features_test=[] - labels_test=[] - - for line in lines_train: - features_train.append(line[1:7]) - labels_train.append(line[0]) - - for line in lines_test: - features_test.append(line[1:7]) - labels_test.append(line[0]) - - train=np.array(features_train,dtype=np.float) - train_labels=np.array(labels_train,dtype=np.int) - - test=np.array(features_test,dtype=np.float) - test_labels=np.array(labels_test,dtype=np.int) - - # La fonction doit retourner 4 matrices (ou vecteurs) de type Numpy. +#!/usr/bin/env python3 +# -*- coding: utf-8 -* +import numpy as np +import random + +def load_iris_dataset(train_ratio=0.7): + """Cette fonction a pour but de lire le dataset Iris + + Args: + train_ratio: le ratio des exemples (ou instances) qui vont etre attribués à l'entrainement, + le rest des exemples va etre utilisé pour les tests. + Par exemple : si le ratio est 50%, il y aura 50% des exemple (75 exemples) qui vont etre utilisé + pour l'entrainement, et 50% (75 exemples) pour le test. + + Retours: + Cette fonction doit retourner 4 matrices de type Numpy, train, train_labels, test, et test_labels + + - train : une matrice numpy qui contient les exemples qui vont etre utilisés pour l'entrainement, chaque + ligne dans cette matrice représente un exemple (ou instance) d'entrainement. + + - train_labels : contient les labels (ou les étiquettes) pour chaque exemple dans train, de telle sorte + que : train_labels[i] est le label (ou l'etiquette) pour l'exemple train[i] + + - test : une matrice numpy qui contient les exemples qui vont etre utilisés pour le test, chaque + ligne dans cette matrice représente un exemple (ou instance) de test. + + - test_labels : contient les labels (ou les étiquettes) pour chaque exemple dans test, de telle sorte + que : test_labels[i] est le label (ou l'etiquette) pour l'exemple test[i] + """ + + random.seed(1) # Pour avoir les meme nombres aléatoires à chaque initialisation. + + # Vous pouvez utiliser des valeurs numériques pour les différents types de classes, tel que : + conversion_labels = {'Iris-setosa': 0, 'Iris-versicolor' : 1, 'Iris-virginica' : 2} + + # Le fichier du dataset est dans le dossier datasets en attaché + + f = open('datasets/bezdekIris.data', 'r') + lines=[line.strip() for line in f.readlines()] + f.close() + + lines=[line.split(",") for line in lines if line] + + features=[] + labels=[] + + for line in lines: + features.append(line[0:4]) + labels.append(conversion_labels[line[4]]) + + np_features=np.array(features,dtype=np.float) + np_labels=np.array(labels,dtype=np.int) + + n_obs = np_features.shape[0] + + n_train = int(n_obs*train_ratio) + + all_indices = [i for i in range(n_obs)] + random.shuffle(all_indices) + + train_index = all_indices[0:n_train] + test_index = all_indices[n_train:n_obs] + + train = np_features[train_index] + train_labels = np_labels[train_index] + test = np_features[test_index] + test_labels = np_labels[test_index] + + + # REMARQUE très importante : + # remarquez bien comment les exemples sont ordonnés dans + # le fichier du dataset, ils sont ordonnés par type de fleur, cela veut dire que + # si vous lisez les exemples dans cet ordre et que si par exemple votre ration est de 60%, + # vous n'allez avoir aucun exemple du type Iris-virginica pour l'entrainement, pensez + # donc à utiliser la fonction random.shuffle pour melanger les exemples du dataset avant de séparer + # en train et test. + + + # Tres important : la fonction doit retourner 4 matrices (ou vecteurs) de type Numpy. + return (train, train_labels, test, test_labels) + + + +def load_congressional_dataset(train_ratio): + """Cette fonction a pour but de lire le dataset Congressional Voting Records + + Args: + train_ratio: le ratio des exemples (ou instances) qui vont servir pour l'entrainement, + le rest des exemples va etre utilisé pour les test. + + Retours: + Cette fonction doit retourner 4 matrices de type Numpy, train, train_labels, test, et test_labels + + - train : une matrice numpy qui contient les exemples qui vont etre utilisés pour l'entrainement, chaque + ligne dans cette matrice représente un exemple (ou instance) d'entrainement. + + - train_labels : contient les labels (ou les étiquettes) pour chaque exemple dans train, de telle sorte + que : train_labels[i] est le label (ou l'etiquette) pour l'exemple train[i] + + - test : une matrice numpy qui contient les exemples qui vont etre utilisés pour le test, chaque + ligne dans cette matrice représente un exemple (ou instance) de test. + + - test_labels : contient les labels (ou les étiquettes) pour chaque exemple dans test, de telle sorte + que : test_labels[i] est le label (ou l'etiquette) pour l'exemple test[i] + """ + + random.seed(1) # Pour avoir les meme nombres aléatoires à chaque initialisation. + + # Vous pouvez utiliser un dictionnaire pour convertir les attributs en numériques + # Notez bien qu'on a traduit le symbole "?" pour une valeur numérique + # Vous pouvez biensur utiliser d'autres valeurs pour ces attributs + conversion_labels = {'republican' : 0, 'democrat' : 1, + 'n' : 0, 'y' : 1, '?' : 2} + + # Le fichier du dataset est dans le dossier datasets en attaché + f = open('datasets/house-votes-84.data', 'r') + lines=[line.strip() for line in f.readlines()] + f.close() + + lines=[line.split(",") for line in lines if line] + + features=[] + labels=[] + + for line in lines: + features.append([conversion_labels[i] for i in line[1:17]]) + labels.append(conversion_labels[line[0]]) + + np_features=np.array(features,dtype=np.float) + np_labels=np.array(labels,dtype=np.int) + + n_obs = np_features.shape[0] + + + n_train = int(n_obs*train_ratio) + + all_indices = [i for i in range(n_obs)] + random.shuffle(all_indices) + + train_index = all_indices[0:n_train] + test_index = all_indices[n_train:n_obs] + + train = np_features[train_index] + train_labels = np_labels[train_index] + test = np_features[test_index] + test_labels = np_labels[test_index] + + # La fonction doit retourner 4 structures de données de type Numpy. + return (train, train_labels, test, test_labels) + + +def load_monks_dataset(numero_dataset): + """Cette fonction a pour but de lire le dataset Monks + + Notez bien que ce dataset est différent des autres d'un point de vue + exemples entrainement et exemples de tests. + Pour ce dataset, nous avons 3 différents sous problèmes, et pour chacun + nous disposons d'un fichier contenant les exemples d'entrainement et + d'un fichier contenant les fichiers de tests. Donc nous avons besoin + seulement du numéro du sous problème pour charger le dataset. + + Args: + numero_dataset: lequel des sous problèmes nous voulons charger (1, 2 ou 3 ?) + par exemple, si numero_dataset=2, vous devez lire : + le fichier monks-2.train contenant les exemples pour l'entrainement + et le fichier monks-2.test contenant les exemples pour le test + les fichiers sont tous dans le dossier datasets + Retours: + Cette fonction doit retourner 4 matrices de type Numpy, train, train_labels, test, et test_labels + + - train : une matrice numpy qui contient les exemples qui vont etre utilisés pour l'entrainement, chaque + ligne dans cette matrice représente un exemple (ou instance) d'entrainement. + - train_labels : contient les labels (ou les étiquettes) pour chaque exemple dans train, de telle sorte + que : train_labels[i] est le label (ou l'etiquette) pour l'exemple train[i] + + - test : une matrice numpy qui contient les exemples qui vont etre utilisés pour le test, chaque + ligne dans cette matrice représente un exemple (ou instance) de test. + - test_labels : contient les labels (ou les étiquettes) pour chaque exemple dans test, de telle sorte + que : test_labels[i] est le label (ou l'etiquette) pour l'exemple test[i] + """ + + + # TODO : votre code ici, vous devez lire les fichiers .train et .test selon l'argument numero_dataset + + f = open('datasets/monks-'+str(numero_dataset)+'.train', 'r') + lines_train=[line.strip() for line in f.readlines()] + f.close() + + f = open('datasets/monks-'+str(numero_dataset)+'.test', 'r') + lines_test=[line.strip() for line in f.readlines()] + f.close() + + lines_train=[line.split(" ") for line in lines_train if line] + lines_test=[line.split(" ") for line in lines_test if line] + + features_train=[] + labels_train=[] + features_test=[] + labels_test=[] + + for line in lines_train: + features_train.append(line[1:7]) + labels_train.append(line[0]) + + for line in lines_test: + features_test.append(line[1:7]) + labels_test.append(line[0]) + + train=np.array(features_train,dtype=np.float) + train_labels=np.array(labels_train,dtype=np.int) + + test=np.array(features_test,dtype=np.float) + test_labels=np.array(labels_test,dtype=np.int) + + # La fonction doit retourner 4 matrices (ou vecteurs) de type Numpy. return (train, train_labels, test, test_labels) \ No newline at end of file diff --git a/Code/metrics.py b/Code/metrics.py index 16678f3..05c4d90 100644 --- a/Code/metrics.py +++ b/Code/metrics.py @@ -36,7 +36,10 @@ def prediction_metrics(cm,obs_labels,pred_labels): precision=[] recall=[] for label_num in np.unique(obs_labels): - precision.append(cm[label_num,label_num] / sum(cm[:,label_num])) + try: + precision.append(cm[label_num,label_num] / sum(cm[:,label_num])) + except: + print(str(Exception)) recall.append(cm[label_num,label_num] / sum(cm[label_num,:])) return accuracy, precision, recall