version avant compilation finale
This commit is contained in:
parent
db371fdcd7
commit
05bc54001f
5 changed files with 704 additions and 530 deletions
|
@ -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.
|
||||
|
|
24
Code/Knn.py
24
Code/Knn.py
|
@ -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
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
Loading…
Add table
Reference in a new issue