ift7025-projet/Code/NeuralNet.py
2019-05-02 22:25:24 -04:00

173 lines
No EOL
7.2 KiB
Python

# -*- 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 train, predict et test de votre code.
"""
import numpy as np
import time
import NeuralNode
import metrics
import random
# le nom de votre classe
# NeuralNet pour le modèle Réseaux de Neurones
# DecisionTree le modèle des arbres de decision
class NeuralNet: #nom de la class à changer
def __init__(self, layers_size, all_labels, **kwargs):
"""
c'est un Initializer.
Vous pouvez passer d'autre paramètres au besoin,
c'est à vous d'utiliser vos propres notations
"""
self.layers_size = layers_size
self.n_hidden_layers = len(layers_size) - 2
self.layers = [[] for i in range(self.n_hidden_layers+1)]
self.all_labels = all_labels
# Couches cachées
for j in range(self.n_hidden_layers):
for i in range(self.layers_size[j+1]):
self.layers[j].append(NeuralNode.NeuralNode(layers_size[j]))
# Couche de sortie
for i in range(layers_size[-1]):
self.layers[-1].append(NeuralNode.NeuralNode(layers_size[-2]))
def __str__(self):
outstr = ""
for layer in self.layers:
for node in layer:
outstr+"\n"+str(node.input_weights)
return outstr
def one_hot_encoder(self,labels):
nb_labels = len(self.all_labels)
one_hot_matrix = []
for label in labels:
one_rank = np.where(np.array(self.all_labels)==label)
one_hot = np.zeros(nb_labels,dtype=np.int64)
one_hot[one_rank] = 1
one_hot_matrix.append(one_hot)
return np.array(one_hot_matrix)
def feed_forward(self,input_values):
all_input_values = []
current_input_values = input_values
all_input_values.append(current_input_values)
for layer in self.layers:
activation_values = []
for node in layer:
activation_values.append(node.activation(current_input_values))
current_input_values = activation_values
all_input_values.append(current_input_values)
return all_input_values
def train(self, train, train_labels, alpha, nb_epoch, 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 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 de taille nx1
alpha: learning rate
vous pouvez rajouter d'autres arguments, il suffit juste de
les expliquer en commentaire
------------
"""
train_labels_enc = self.one_hot_encoder(train_labels)
learning_curve = []
for epoch in range(nb_epoch):
# print("epoch"+str(epoch))
for i in range(len(train)):
deltas = []
output = self.feed_forward(train[i])
# print("Les valeurs des sorties sont: "+str(output)+"\nLabel:"+str(train_labels_enc[i]))
deltas.append(train_labels_enc[i]-output[-1])
# On recule dans les couches cachées j
for j in reversed(range(self.n_hidden_layers)):
#print("la couche "+str(j))
layerError = []
# Pour chaque neurone k de la couche cachée courante
for k in range(len(self.layers[j])):
#print("le neurone "+str(k)+" de la couche "+str(j))
average_error = 0
# Pour chaque neurone l de la couche j+1
for l in range(len(self.layers[j+1])):
#print("la "+str(l)+"e entrée dans le neurone "+str(k)+" de la couche "+str(j+1))
current_delta = deltas[0][l]
average_error += current_delta * self.layers[j+1][l].input_weights[k+1]
layerError.append(average_error * self.layers[j][k].activation_derivative(output[j]))
# Vu qu'on recule, on insère au début au lieu de la fin
deltas.insert(0,layerError)
# Mise à jour des poids
# print("Mise à jour des poids. Les deltas sont: "+str(deltas))
for j in range(len(self.layers)):
# Pour chaque neurone k
for k in range(len(self.layers[j])):
self.layers[j][k].update_weights(output[j],alpha,deltas[j][k])
learning_curve.append(self.test(train, train_labels, verbose)[1])
return learning_curve
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
"""
return np.argmax(self.feed_forward(exemple)[-1])
def score(self, test, test_labels):
return [self.predict(exemple,label) for exemple,label in zip(test,test_labels)]
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 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 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 (ou le taux d'erreur)
Bien entendu ces tests doivent etre faits sur les données de test seulement
"""
start_time = time.time()
prediction_test = self.score(test,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.