ift7025-projet/Code/BayesNaif.py

160 lines
6.1 KiB
Python
Raw Normal View History

2019-03-16 21:50:53 +00:00
#!/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,
2019-03-22 04:45:19 +00:00
* 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
2019-03-16 21:50:53 +00:00
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
2019-03-22 04:45:19 +00:00
import math
import metrics
2019-03-16 21:50:53 +00:00
# le nom de votre classe
# BayesNaif pour le modèle bayesien naif
# Knn pour le modèle des k plus proches voisins
2019-03-23 02:01:39 +00:00
def gaussian_pdf(x, param):
2019-03-22 04:45:19 +00:00
"""
Fonction de densité de probabilité de la distribution gaussienne
"""
2019-03-23 02:01:39 +00:00
mu, sigma = param
2019-03-22 04:45:19 +00:00
return math.exp(-(float(x)-float(mu))**2/(2*float(sigma)**2)) / (float(sigma)*math.sqrt(2*math.pi))
2019-03-16 21:50:53 +00:00
class BayesNaif: #nom de la class à changer
2019-03-22 04:45:19 +00:00
2019-03-16 21:50:53 +00:00
2019-03-23 02:01:39 +00:00
def __init__(self, gaussian, **kwargs):
2019-03-22 04:45:19 +00:00
"""
c'est un Initializer.
Vous pouvez passer d'autre paramètres au besoin,
c'est à vous d'utiliser vos propres notations
"""
2019-03-23 02:01:39 +00:00
self.gaussian=gaussian
2019-03-22 04:45:19 +00:00
2019-03-23 02:01:39 +00:00
def train(self, train, train_labels):#TODO A ENLEVER #vous pouvez rajouter d'autres attribus au besoin
2019-03-22 04:45:19 +00:00
"""
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
2019-03-23 02:01:39 +00:00
self.unique_labels = np.unique(train_labels)
2019-03-22 04:45:19 +00:00
2019-03-23 02:01:39 +00:00
self.labels_prob = {}
for i in self.unique_labels:
self.labels_prob.update({i:sum(train_labels == i) / n})
2019-03-22 04:45:19 +00:00
2019-03-23 02:01:39 +00:00
# Distribution des probabilités conditionnelles P(F1,F2,...|C)
2019-03-22 04:45:19 +00:00
2019-03-23 02:01:39 +00:00
self.features_cond = {}
self.unique_values_cond = {}
2019-03-22 04:45:19 +00:00
# on itère sur les labels, les colonnes et les valeurs uniques des colonnes (si discret)
2019-03-23 02:01:39 +00:00
for l in self.unique_labels:
subset = train[np.where(train_labels==self.unique_labels[l])[0]]
2019-03-22 04:45:19 +00:00
n_subset, m_subset = subset.shape
for c in range(m_subset):
2019-03-23 02:01:39 +00:00
current_column = subset[:,c]
if (self.gaussian):
self.features_cond.update({(l,c):(np.mean(current_column),np.std(current_column))})
2019-03-22 04:45:19 +00:00
else:
2019-03-23 02:01:39 +00:00
unique_values = np.unique(current_column)
self.unique_values_cond.update({(l,c):unique_values})
2019-03-22 04:45:19 +00:00
for v in unique_values:
2019-03-23 02:01:39 +00:00
self.features_cond.update({(l,c,v):sum(current_column==v)/n_subset})
2019-03-22 04:45:19 +00:00
2019-03-16 21:50:53 +00:00
2019-03-22 04:45:19 +00:00
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
2019-03-16 21:50:53 +00:00
2019-03-22 04:45:19 +00:00
"""
2019-03-23 02:01:39 +00:00
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)
2019-03-16 21:50:53 +00:00
def test(self, test, test_labels, verbose=True):
2019-03-22 04:45:19 +00:00
"""
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
2019-03-22 04:45:19 +00:00
# Vous pouvez rajouter d'autres méthodes et fonctions,
# il suffit juste de les commenter.