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
|
2019-03-23 04:15:16 +00:00
|
|
|
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
|
|
|
|
2019-03-23 04:15:16 +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
|
|
|
|
|
|
|
|
"""
|
2019-03-23 04:15:16 +00:00
|
|
|
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.
|