version avant compilation finale

This commit is contained in:
Francois Pelletier 2019-03-23 18:31:09 -04:00
parent db371fdcd7
commit 05bc54001f
5 changed files with 704 additions and 530 deletions

View file

@ -1,159 +1,162 @@
#!/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 math
import metrics
# le nom de votre classe
# BayesNaif pour le modèle bayesien naif
# Knn pour le modèle des k plus proches voisins
def gaussian_pdf(x, param):
"""
Fonction de densité de probabilité de la distribution gaussienne
"""
mu, sigma = param
return math.exp(-(float(x)-float(mu))**2/(2*float(sigma)**2)) / (float(sigma)*math.sqrt(2*math.pi))
class BayesNaif: #nom de la class à changer
def __init__(self, gaussian, **kwargs):
"""
c'est un Initializer.
Vous pouvez passer d'autre paramètres au besoin,
c'est à vous d'utiliser vos propres notations
"""
self.gaussian=gaussian
def train(self, train, train_labels):#TODO A ENLEVER #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()
"""
# Distribution a priori des étiquettes P(C)
n,m = train.shape
self.unique_labels = np.unique(train_labels)
self.labels_prob = {}
for i in self.unique_labels:
self.labels_prob.update({i:sum(train_labels == i) / n})
# Distribution des probabilités conditionnelles P(F1,F2,...|C)
self.features_cond = {}
self.unique_values_cond = {}
# on itère sur les labels, les colonnes et les valeurs uniques des colonnes (si discret)
for l in self.unique_labels:
subset = train[np.where(train_labels==self.unique_labels[l])[0]]
n_subset, m_subset = subset.shape
for c in range(m_subset):
current_column = subset[:,c]
if (self.gaussian):
self.features_cond.update({(l,c):(np.mean(current_column),np.std(current_column))})
else:
unique_values = np.unique(current_column)
self.unique_values_cond.update({(l,c):unique_values})
for v in unique_values:
self.features_cond.update({(l,c,v):sum(current_column==v)/n_subset})
def predict(self, exemple, label):
"""
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
"""
nb_unique_labels = len(self.unique_labels)
# P(X|C)
p_xc = {}
for l in range(nb_unique_labels):
if (self.gaussian):
p_xc.update({l:np.product([gaussian_pdf(exemple[c],self.features_cond.get((self.unique_labels[l],c))) for c in range(len(exemple))])})
else:
p_xc.update({l:np.product([self.features_cond.get((self.unique_labels[l],c,exemple[c])) for c in range(len(exemple))])})
prob = [self.labels_prob.get(i)*p_xc.get(i) for i in self.unique_labels]
prob = prob/sum(prob)
return (self.unique_labels[np.where(prob==max(prob))[0]].tolist()[0],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
"""
prediction_test = [self.predict(test[i],test_labels[i])[0] for i in range(len(test_labels))]
cm = metrics.confusion_matrix(test_labels,prediction_test)
accuracy, precision, recall = metrics.prediction_metrics(cm,test_labels,prediction_test)
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 math
import metrics
import time
# le nom de votre classe
# BayesNaif pour le modèle bayesien naif
# Knn pour le modèle des k plus proches voisins
def gaussian_pdf(x, param):
"""
Fonction de densité de probabilité de la distribution gaussienne
"""
mu, sigma = param
return math.exp(-(float(x)-float(mu))**2/(2*float(sigma)**2)) / (float(sigma)*math.sqrt(2*math.pi))
class BayesNaif:
def __init__(self, gaussian, **kwargs):
"""
c'est un Initializer.
Vous pouvez passer d'autre paramètres au besoin,
c'est à vous d'utiliser vos propres notations
gaussian: variable booléenne qui définit si on utilise la variante gaussienne de l'algorithme Bayes Naif
"""
self.gaussian=gaussian
def train(self, train, train_labels, verbose=True):
"""
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()
"""
start_time = time.time()
# Distribution a priori des classes de l'étiquette P(C)
n,m = train.shape
self.unique_labels = np.unique(train_labels)
self.labels_prob = {}
for c in self.unique_labels:
self.labels_prob.update({c:sum(train_labels == c) / n})
# Distribution des probabilités conditionnelles P(F1,F2,...|C)
self.features_cond = {}
self.unique_values_cond = {}
# on itère sur les labels, les colonnes et les valeurs uniques des colonnes (si discret)
for c in self.unique_labels:
subset = train[np.where(train_labels==self.unique_labels[c])[0]]
n_subset, m_subset = subset.shape
for f in range(m_subset):
current_column = subset[:,f]
if (self.gaussian):
self.features_cond.update({(c,f):(np.mean(current_column),np.std(current_column))})
else:
unique_values = np.unique(current_column)
self.unique_values_cond.update({(c,f):unique_values})
for v in unique_values:
self.features_cond.update({(c,f,v):sum(current_column==v)/n_subset})
cm,accuracy,precision,recall,compute_time = self.test(train, train_labels, verbose=False)
compute_time = time.time() - start_time
if (verbose):
metrics.print_prediction_metrics(cm,accuracy,precision,recall,compute_time)
return cm,accuracy,precision,recall,compute_time
def predict(self, exemple, label):
"""
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
"""
nb_unique_labels = len(self.unique_labels)
# P(X|C)
p_xc = {}
for l in range(nb_unique_labels):
if (self.gaussian):
p_xc.update({l:np.product([gaussian_pdf(exemple[f],self.features_cond.get((self.unique_labels[l],f))) or 1 for f in range(len(exemple))])})
else:
p_xc.update({l:np.product([self.features_cond.get((self.unique_labels[l],f,exemple[f])) or 1 for f in range(len(exemple))])})
prob = [self.labels_prob.get(i)*p_xc.get(i) for i in self.unique_labels]
prob = prob/sum(prob)
return (self.unique_labels[np.where(prob==max(prob))[0]].tolist()[0],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
"""
start_time = time.time()
prediction_test = [self.predict(test[i],test_labels[i])[0] for i in range(len(test_labels))]
cm = metrics.confusion_matrix(test_labels,prediction_test)
accuracy, precision, recall = metrics.prediction_metrics(cm,test_labels,prediction_test)
compute_time = time.time() - start_time
if (verbose):
metrics.print_prediction_metrics(cm,accuracy,precision,recall,compute_time)
return cm,accuracy,precision,recall,compute_time
# Vous pouvez rajouter d'autres méthodes et fonctions,
# il suffit juste de les commenter.

View file

@ -12,6 +12,7 @@ je vais avoir besoin de tester les méthodes test, predict et test de votre code
import numpy as np
import metrics
import time
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)
@ -26,13 +27,14 @@ def mode(a):
class Knn: #nom de la class à changer
def __init__(self, k=5, **kwargs):
def __init__(self, k=5, m=2, **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
self.minkowski_p=m
def set_best_k(self, train, train_labels, nb_split, k_potentiel):
## Création des échantillons de validation croisée
@ -50,7 +52,7 @@ class Knn: #nom de la class à changer
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)
cm,accuracy,precision,recall,compute_time = self.test(train[validation_index[i]], train_labels[validation_index[i]], verbose=False)
accuracy_cv[k_index][i] = accuracy
## Calcul de la moyenne
@ -62,7 +64,7 @@ class Knn: #nom de la class à changer
## Assignation
self.k=best_k
print("Le meilleur k est: "+str(best_k))
print("Le meilleur k est: "+str(best_k)+"\nCalculé en "+str(compute_time)+"s")
## Retourner la valeur
return best_k
@ -97,6 +99,8 @@ class Knn: #nom de la class à changer
nous allons faire d'autres tests sur les données de test dans la méthode test()
"""
start_time = time.time()
# 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
@ -104,8 +108,6 @@ class Knn: #nom de la class à changer
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
@ -130,10 +132,11 @@ class Knn: #nom de la class à changer
# 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)
compute_time = time.time() - start_time
if (verbose):
metrics.print_prediction_metrics(cm,accuracy,precision,recall)
metrics.print_prediction_metrics(cm,accuracy,precision,recall,compute_time)
return cm,accuracy,precision,recall
return cm,accuracy,precision,recall,compute_time
def predict(self, exemple, label, verbose=True):
@ -187,7 +190,7 @@ class Knn: #nom de la class à changer
Bien entendu ces tests doivent etre faits sur les données de test seulement
"""
start_time = time.time()
n,m = test.shape
n_ex,m_ex = self.train_set.shape
nn=np.empty((n,self.k,2))
@ -209,10 +212,11 @@ class Knn: #nom de la class à changer
# 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)
compute_time = time.time() - start_time
if (verbose):
metrics.print_prediction_metrics(cm,accuracy,precision,recall)
metrics.print_prediction_metrics(cm,accuracy,precision,recall,compute_time)
return cm,accuracy,precision,recall
return cm,accuracy,precision,recall,compute_time

File diff suppressed because it is too large Load diff

View file

@ -5,8 +5,6 @@ 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
@ -19,47 +17,5 @@ En gros, vous allez :
"""
# 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)
# Ce fichier est créé en exportant mon rapport Jupyter Notebook en .py

View file

@ -37,22 +37,31 @@ def prediction_metrics(cm,obs_labels,pred_labels):
recall=[]
for label_num in np.unique(obs_labels):
try:
precision.append(cm[label_num,label_num] / sum(cm[:,label_num]))
myPrecision = cm[label_num,label_num] / sum(cm[:,label_num])
if (not np.any(np.isnan(myPrecision))):
precision.append(myPrecision)
except:
print(str(Exception))
recall.append(cm[label_num,label_num] / sum(cm[label_num,:]))
raise
try:
myRecall = cm[label_num,label_num] / sum(cm[label_num,:])
if (not np.any(np.isnan(myRecall))):
recall.append(myRecall)
except:
raise
return accuracy, precision, recall
def print_prediction_metrics(cm,accuracy,precision,recall):
def print_prediction_metrics(cm,accuracy,precision,recall,compute_time):
"""
Cette fonction imprime la matrice de confusion et les métriques
"""
print("Matrice de confusion:")
print(cm)
print("\nAccuracy:")
print("\nExactitude:")
print(accuracy)
print("\nPrecision:")
print("\nPrécision:")
print(precision)
print("\nRecall")
print(recall)
print("\nRappel:")
print(recall)
print("\nCalculé en:")
print(str(compute_time)+"s")