des résultats, mais faux

This commit is contained in:
eynard 2021-12-16 17:06:51 +01:00
parent a8a8edac7c
commit 8189a03abf
5 changed files with 231 additions and 37 deletions

129
CahierDesCharges.md Normal file
View File

@ -0,0 +1,129 @@
# Conception dune librairie de réseaux neuronaux
## Samedi 23 Octobre 2021
**Hugo EYNARD
Thomas BLUSSON
Romain MOREAU
Gabriel CHAVANON**
Responsable référent:
Gabriel CHAVANON
Dépot GITEA:
https://dwarves.iut-fbleau.fr/gitiut/blusson/PT21-22-Reseau-Neurones
## Sommaire
- Sommaire
- Cahier des charges fonctionnelles
- Contexte
- Etudes détaillées des objectifs (analyses des besoins)
- Calendrier et priorisation des objectives
- Cahier des charges techniques et méthodologique
- Bibliographie
## Cahier des charges fonctionnelles
### Contexte
Client : Pierre VALARCHER (tuteur)
Description:
Nous comptons concevoir notre propre librairie de réseaux neuronaux et loptimiser
par la suite à travers différents tests (reconnaître des caractères manuscrites). Pour
ceci nous ne comptons pas nous appuyer sur des solutions déjà existantes (comme
TensorFlow) mais bien tout réaliser de A à Z. Pour ce qui est de loptimisation (une
meilleure vitesse d'exécution et une meilleure précision des résultats) on pourra
utiliser des tests et des outils comparatifs (ancienne version de notre projet ou
encore des librairies déjà existantes).
Contraintes :
On réalisera ce projet en Python orienté objet et grâce à ses librairies, tout notre
travail sera disponible surnotre dépôt GITEA.
Existant :
Nous avons à notre disposition un jeu de données contenant des images de chiffres
annotés avec le chiffre correspondant. Ilnous permettra d'entraînernotre réseau
neuronal pour le tester.
### Etudes détaillées des objectifs (analyses des besoins)
Fonctionnalités :
-Choix de la fonction dactivation pour chaque couche de neurones
-Choix du nombre de couches de neurones
-Choix du type de neurones pour chaque couche
-Choix du nombre de neurones dans chaque couche
-Faire une prédiction à partir dun réseau de neurone
-Entraîner le réseau de neurones
-Exporter et importer létat (modèle, biais et poids) dun réseau de neurones
-Visualiser l'entraînement dun réseau de neurone à deux entrées
Bob le développeur possède un jeu de données comportant des images de chats et
de chiens annotés. Il commence par importer Sobek. Ilchoisit ensuitepour son
modèlederéseauneuronaldavoirunematrice 360 par 360 pourentrée.Ildécidede
mettre 2 premières couches de 180 neurones convolutifs,puis 2 couchesde 64
neuronesdenses(ouclassiques)etenfinunesortiede 2 neuronesdenses(Unpour
chienet un pourchat). Il sépareson jeude donnéesen 2 parties:ilutiliseles 3
premiers quarts pour entraîner son réseau neuronal et après quelques minutes
d'attente, il utilise le dernier quart pour estimer sa précision. Après quelques
modifications et tests de l'architecture de son réseaupour obtenir une meilleure
précision, Bob est satisfait et peut maintenant utiliserson réseaupour faire des
prédictions.
### Calendrier et priorisation des objectives
Jalon 0 : Cahier des charges (à signer) début novembre
Jalon 1 : Perceptron multicouche (première itération du projet), mi décembre M
1.1 : Partie prédiction du perceptron multicouche M
1.2 : Partie apprentissage du perceptron multicouche M
1.3 : Estimation de la précision du perceptron multicouche S
1.4 : Exportation et importation de létat du réseau neuronal M
Jalon 2 : Utilisation concrète du réseau neuronal, fin décembre M
Jalon 3 : Visualisation 2D de lentraînement du réseau neuronal M
Jalon 4 : Réseau de neurones convolutif (version optimisée du perceptron multicouche), fin janvier S
4.1 : Création dun système de choix de type de couche M
4.2 : Implémentation du neurone convolutif M
Jalon 5 : Utilisation concrète du réseau convolutif, fin février C
## Cahier des charges techniques et méthodologique
Nous avons choisi dutiliser le Python car cest un langage plutôt abordable qui est
communément utilisé pour le machine learning. On compte également utiliser Scipy
(NumPy (gestion des tableaux), Matplotlib (visualisation de données sous forme
graphique).
Méthodologie de travail :
On envisage dutiliser la méthode agile (1 sprint correspond à 1 jalon) ainsi que le
pair programming.
On compte utiliser très fréquemment GIT, et faire des tests unitaires dès que
possible. On utilisera make pour lexécution des tests et des mises en application.
### Bibliographie
https://en.wikipedia.org/wiki/Types_of_artificial_neural_networks
https://youtu.be/bVQUSndDllU
https://youtu.be/aircAruvnKk
https://www.mygreatlearning.com/blog/open-source-python-libraries/
https://fr.wikipedia.org/wiki/Matplotlib
https://brilliant.org/wiki/backpropagation/
_Apprentissage machine Clé de lintelligence artificielle_ - Rémi Gilleron, 2019
_Deep Learning with Python, 2nd Edition_ - FrançoisChollet, 2021

View File

@ -1,4 +1,5 @@
import numpy as np
import math
class network:
@ -10,7 +11,7 @@ class network:
self.__inputLayerSize = inputLayerSize
oldLayerSize = inputLayerSize
for layerSize in layerSizes:
self.__weights.append( np.random.default_rng(42).random((oldLayerSize, layerSize)) )
self.__weights.append( np.random.random((layerSize, oldLayerSize)) )
oldLayerSize = layerSize
self.__biases = [[0]*layerSize for layerSize in layerSizes]
self.__weights = np.array(self.__weights, dtype=object)
@ -24,7 +25,7 @@ class network:
def __sigmoid(value, derivative=False):
if (derivative):
return network.__sigmoid(value) * (1 - network.__sigmoid(value))
return 1/(1+np.exp(-value))
return 1/(1+math.exp(-value))
def process(self, _input, __storeValues=False):
if type(_input) != np.ndarray:
@ -35,61 +36,70 @@ class network:
# raise TypeError("The input vector must contain floats!")
if (__storeValues):
self.activations = np.array([])
self.outputs = np.array([])
self.activations = []
self.outputs = []
for layerWeights, bias in zip(self.__weights, self.__biases):
_input = np.matmul(_input, layerWeights)
_input = np.matmul(layerWeights, _input)
_input = np.add(_input, bias)
if (__storeValues):
print("-------------------")
print(bias)
print("-------------------")
self.activations = np.append(self.activations, _input)
self.activations[len(self.activations)-1] = np.insert(self.activations[len(self.activations)-1], 0, bias)
self.activations.append(_input.copy())
#reLu application
with np.nditer(_input, op_flags=['readwrite'], flags=['refs_ok']) as layer:
for neuron in layer:
neuron = network.__reLu(neuron)
for neuron in range(len(_input)):
_input[neuron] = network.__sigmoid(_input[neuron])
#On peut comparer la performance si on recalcul plus tard
if (__storeValues):
self.outputs = np.append(self.outputs, _input)
self.outputs[len(self.outputs)-1] = np.insert(self.outputs[len(self.outputs)-1], 0, 1)
self.outputs.append(_input.copy())
self.activations = np.array(self.activations, dtype=object)
self.outputs = np.array(self.outputs, dtype=object)
return _input
def train(self, inputs, desiredOutputs, learningRate):
ErrorSums = [[0]*(len(layer)+1) for layer in self.__biases]
errorSums = [[[0]*(len(neuron)) for neuron in layer] for layer in self.__weights]
self.__errors = [[0]*(len(layer)) for layer in self.__weights]
for _input, desiredOutput in zip(inputs, desiredOutputs):
self.__output = self.process(_input, True)
self.__desiredOutput = desiredOutput
for layerNumber in range(len(ErrorSums)-1, -1, -1):
ErrorSums[layerNumber][0] += self.__partialDerivative(layerNumber, 0)
for neuronNumber in range(1, len(ErrorSums[layerNumber])):
print("layer : " + str(layerNumber) + " neuron : " + str(neuronNumber))
ErrorSums[layerNumber][neuronNumber] += self.__partialDerivative(layerNumber, neuronNumber)
for i in range(len(ErrorSums)):
for j in range(len(ErrorSums[i])):
ErrorSums[i][j] = 1 / ErrorSums[i][j]
self.__biases[i, j] -= learningRate * ErrorSums[i][j]
for layerNumber in range(len(errorSums)-1, -1, -1):
for neuronNumber in range(len(errorSums[layerNumber])):
for weightNumber in range(len(errorSums[layerNumber][neuronNumber])):
#print("layer : " + str(layerNumber) + " neuron : " + str(neuronNumber) + " weight : " + str(weightNumber))
errorSums[layerNumber][neuronNumber][weightNumber] += self.__partialDerivative(layerNumber, neuronNumber, weightNumber)
total = 0
for i in range(len(errorSums)):
for j in range(len(errorSums[i])):
for k in range(len(errorSums[i][j])):
errorSums[i][j][k] = errorSums[i][j][k] / len(inputs)
total += errorSums[i][j][k]
self.__weights[i][j][k] -= learningRate * errorSums[i][j][k]
print("Error : " + str(total))
def __Error(self, layer, neuron):
return self.__ErrorFinalLayer(neuron) if (layer == len(self.__weights)-1) else self.__ErrorHiddenLayer(layer, neuron)
if (self.__errors[layer][neuron] == 0 ):
self.__errors[layer][neuron] = self.__ErrorFinalLayer(neuron) if (layer == len(self.__weights)-1) else self.__ErrorHiddenLayer(layer, neuron)
return self.__errors[layer][neuron]
def __ErrorFinalLayer(self, neuron):
print(self.activations)
return network.__reLu(self.activations[len(self.activations)-1][neuron], True) * (self.__output[neuron] - self.__desiredOutput[neuron])
return network.__sigmoid(self.activations[len(self.activations)-1][neuron], True) * (self.__output[neuron] - self.__desiredOutput[neuron])
def __ErrorHiddenLayer(self, layer, neuron):
upperLayerLinksSum = 0
for upperLayerNeuron in range(len(self.__weights[layer+1]-1)):
#A comparer avec un acces direct au erreurs precalcules
upperLayerLinksSum += self.__weights[layer+1][upperLayerNeuron][neuron] * self.__Error(layer+1, neuron)
return network.__reLu(self.activations[layer][neuron], True) * upperLayerLinksSum
return network.__sigmoid(self.activations[layer][neuron], True) * upperLayerLinksSum
def __partialDerivative(self, layer, neuron):
return self.__Error(layer, neuron) * self.outputs[layer][neuron]
def __partialDerivative(self, layer, neuron, weight):
return self.__Error(layer, neuron) * self.outputs[layer-1][weight]

View File

@ -6,20 +6,23 @@ random.seed()
myNetwork = network(1, 8, 8, 10)
for j in range(5):
for j in range(3000):
inputs = []
desiredOutputs = []
for i in range(1000):
if (j%50 == 0):
print(j)
for i in range(200):
inputs.append([random.randrange(10)])
inputs = np.array(inputs, dtype=object)
for i in range(1000):
for i in range(200):
desiredOutputs.append([0]*10)
desiredOutputs[i][9 - inputs[i][0]] = 1
desiredOutputs = np.array(desiredOutputs, dtype=object)
myNetwork.train(inputs, desiredOutputs, 0.1)
myNetwork.train(inputs, desiredOutputs, 0.01)
print(myNetwork.process(np.array([8.0], dtype=object)))
print(myNetwork.process(np.array([7.0], dtype=object)))
print(myNetwork.process(np.array([1.0], dtype=object)))

12
timeTest.py Normal file
View File

@ -0,0 +1,12 @@
import random
import numpy as np
inputs = []
for i in range(10000000):
inputs.append([random.randrange(10)])
inputs = np.array(inputs, dtype=object)
inputs = np.insert(inputs, 0, 1, axis=1)
print(inputs)

40
timeTest2.py Normal file
View File

@ -0,0 +1,40 @@
import random
import numpy as np
import time
weights = np.random.default_rng(42).random((10, 10))
biases = np.random.default_rng(42).random(10)
biases = np.array(biases, dtype=object)
time1 = time.perf_counter()
for k in range(1000):
_input = []
for i in range(10):
_input.append(random.randrange(10))
_input = np.array(_input, dtype=object)
for f in range(100):
_input = np.matmul(_input, weights)
_input = np.add(_input, biases)
time2 = time.perf_counter()
weights = np.random.default_rng(42).random((11, 10))
time3 = time.perf_counter()
for k in range(1000):
_input = []
for i in range(10):
_input.append(random.randrange(10))
_input = np.array(_input, dtype=object)
for f in range(100):
_input = np.insert(_input, 0, 1, axis=0)
_input = np.matmul(_input, weights)
time4 = time.perf_counter()
print("Multiplication et addition : " + str(time2-time1) + " secondes")
print("Insertion puis multiplication : " + str(time4-time3) + " secondes")