diff options
Diffstat (limited to 'Neurone')
| -rw-r--r-- | Neurone/FonctionActivation.cpp | 107 | ||||
| -rw-r--r-- | Neurone/FonctionActivation.h | 34 | ||||
| -rw-r--r-- | Neurone/Neurone.cpp | 131 | ||||
| -rw-r--r-- | Neurone/Neurone.h | 28 | ||||
| -rw-r--r-- | Neurone/NeuroneB.cpp | 85 | ||||
| -rw-r--r-- | Neurone/NeuroneB.h | 35 |
6 files changed, 420 insertions, 0 deletions
diff --git a/Neurone/FonctionActivation.cpp b/Neurone/FonctionActivation.cpp new file mode 100644 index 0000000..4697ca2 --- /dev/null +++ b/Neurone/FonctionActivation.cpp @@ -0,0 +1,107 @@ +#include"./FonctionActivation.h" +#include <stdlib.h> +/** + * Constructeur par défauts + * @method FonctionActivation + * @param fonctionActivation Fonction activation à utiliser parmis l'enumération + */ +FonctionActivation::FonctionActivation(){ + this->fonctionActivation = SIGMOID; +} +/** + * @method FonctionActivation::setFonctionActivation + * @param fonctionActivation Fonction activation à utiliser parmis l'enumération + */ +void FonctionActivation::setFonctionActivation(EnumFonctionActivation fonctionActivation){ + this->fonctionActivation = fonctionActivation; +} + +/** + * Constructeur + * @method FonctionActivation + * @param fonctionActivation Fonction activation à utiliser parmis l'enumération + */ +FonctionActivation::FonctionActivation(EnumFonctionActivation fonctionActivation){ + this->fonctionActivation = fonctionActivation; +} + +/** + * @method getValeurActivation + * @param x Valeur de la variable + * @param k Constante de changement + * @return Valeur d'activation + */ +double FonctionActivation::getValeurActivation(double x, double k) const{ + switch (fonctionActivation) { + case IDENTITY: + return x; + break; + case BINARYSTEP: + return x>=0; + break; + case SIGMOID: + return (1/(1+exp(-k*x))); + break; + case TAN: + return ( (exp(x)-exp(-x)) / (exp(x)+exp(-x))); + break; + case SIN: + return sin(x); + break; + case RELU: + return x<0? 0 : x; + break; + case LRELU: + return x<0? 0.01*x : x; + break; + case PRELU: + return x<0? k*x : x; + break; + case ELU: + return x<0? (k*(exp(x)-1)) : x;; + break; + default: + return 0; + break; + } +} +/** + * @method getValeurDerive + * @param x Valeur de la variable + * @param k Constante de changement + * @return Valeur de la derivée + */ +double FonctionActivation::getValeurDerivee(double x, double k) const{ + switch (fonctionActivation) { + case IDENTITY: + return 1; + break; + case BINARYSTEP: + return 0; + break; + case SIGMOID: + return (k*exp(-k*x))* (1/(1+exp(-k*x)*(1+exp(-k*x)))); + break; + case TAN: + return 1 - pow(((exp(x)-exp(-x))/(exp(x)+exp(-x))),2); + break; + case SIN: + return cos(x); + break; + case RELU: + return x<0? 0 : 1; + break; + case LRELU: + return x<0? 0.01 : 1; + break; + case PRELU: + return x<0? k : 1; + break; + case ELU: + return x<0? (k*(exp(x)-1)) + k : 1; + break; + default: + return 0; + break; + } +} diff --git a/Neurone/FonctionActivation.h b/Neurone/FonctionActivation.h new file mode 100644 index 0000000..ccd1119 --- /dev/null +++ b/Neurone/FonctionActivation.h @@ -0,0 +1,34 @@ +#ifndef _FONCTIONACTIVATION_H_ +#define _FONCTIONACTIVATION_H_ +#include<math.h> +/** + * L'objectif ce cette classe et d'être appeller pour l'activation + * et donc changer plus facilement la fonction d'activation pour le test. + */ +class FonctionActivation { +public: + typedef enum { + IDENTITY, + BINARYSTEP, + SIGMOID, // : Hyperparameter k + TAN, + SIN, + /* Rectifier */ + RELU, // Basic : ramp function + LRELU, // Leaky function : 0.01 + PRELU, // Hyperparameter : Hyperparameter k + ELU // Exponential and ramp + } EnumFonctionActivation; + +private: + EnumFonctionActivation fonctionActivation; + +public: + FonctionActivation(); + FonctionActivation(EnumFonctionActivation fonctionActivation); + + void setFonctionActivation(EnumFonctionActivation fonctionActivation); + double getValeurActivation(double sum, double k = 0) const; + double getValeurDerivee(double sum, double k = 0) const; +}; +#endif diff --git a/Neurone/Neurone.cpp b/Neurone/Neurone.cpp new file mode 100644 index 0000000..0f08602 --- /dev/null +++ b/Neurone/Neurone.cpp @@ -0,0 +1,131 @@ +#include"./Neurone.h" + +/** +* Constructeur par defauts +* @method Neurone::Neurone +*/ +Neurone::Neurone(){ + n = 0; +} +/** + * Constructeur par nombre d'entrées + * @method Neurone::Neurone + * @param n Nombre d'entrées + * @param n Fonction d'Activation + */ +Neurone::Neurone(int n,FonctionActivation::EnumFonctionActivation fct){ + this->n = n; + fonctionActivation.setFonctionActivation(fct); + aleaWeights(); +} +/** + * Constructeur par arguments + * @method Neurone::Neurone + * @param taille Nombre d'entrées + * @param x Vecteur de poids + */ +Neurone::Neurone(int n, std::vector<double> * x,FonctionActivation::EnumFonctionActivation fct){ + w = x; + fonctionActivation.setFonctionActivation(fct); + this->n = n; +} + +/** + * Méthode de propagation en avant + * @method Neurone::fire + * @param in Vecteur d'entrées + * @param k Coefficient de sigmoid k + * @return Valeur d'activation + */ +double Neurone::fire(std::vector<double> in, double k)const{ + return fw_activate(fw_sum(in),k); +} + +/** + * Méthode de somme des valeurs du vecteur + * @method Neurone::fw_sum + * @param x Vecteur + * @return Somme + */ +double Neurone::fw_sum(std::vector<double> x)const{ + double res=0; + for(int i=0; i<n; i++){ + res += (x[i]) * (*w)[i]; + } + return res; +} + +/** + * Méthode d'activation + * @method Neurone::fw_activate + * @param sum Valeur de la somme du vecteur (cf Neurone::fw_sum) + * @param k Valeur du biais + * @return Valeur d'activation + */ +double Neurone::fw_activate(double sum, double k)const{ + return fonctionActivation.getValeurActivation(sum,k); +} +/** + * Méthode de dérivation + * @method Neurone::derive_activate + * @param sum Valeur de la somme du vecteur (cf Neurone::fw_sum) + * @param k Valeur du coefficient de sigmoid k + * @return Valeur de dérivation + */ +double Neurone::derive_activate(double sum, double k)const{ + return fonctionActivation.getValeurDerivee(sum,k); +} + +/** + * Méthode d'apprentissage (cf Neurone::fw_sum, cf Neurone::fw_activate, cf Neurone::derive_activate) + * @method Neurone::learn + * @param x Vecteur de poids + * @param o Valeur attendue + * @param k Valeur de l'hyperparamètre + * @param mu Taux d'apprentissage | Learning rate + */ +void Neurone::learn(std::vector<double> x,double o,double k, double mu){ + double sum = fw_sum(x); + double res = fw_activate(sum,k); + double derive = derive_activate(sum,k); + for(int i=0; i<n; i++){ + (*w)[i]= (*w)[i]- mu * (x[i]*derive*((o-res)*(-2))); + } +} + +/** + * Affichage des poids + * @method Neurone::printWeight + */ +void Neurone::printWeight(){ + for(int i=0; i<n; i++){ + std::cout << "w" << i << " = " << (*w)[i] << std::endl; + } +} + +/** + * Méthode de génération de poids aléatoire selon une loi normale centrée réduite + * @method Neurone::aleaWeights + */ +void Neurone::aleaWeights(){ + w = new std::vector<double> (n,0.8); + std::default_random_engine generator(std::random_device{}()); + std::normal_distribution<double> distribution(0,1); + for (int i=0; i<n; i++) { + (*w)[i] = distribution(generator); + } +} +/** + * @method Neurone::getWeight + * @return Vecteur de poids + */ +std::vector<double> * Neurone::getWeight(){ + return w; +} +/** + * @method Neurone::getNbPoids + * @return Nombre de poids + */ +int Neurone::getNbPoids(){ + return n; +} diff --git a/Neurone/Neurone.h b/Neurone/Neurone.h new file mode 100644 index 0000000..3fc6dd5 --- /dev/null +++ b/Neurone/Neurone.h @@ -0,0 +1,28 @@ +#ifndef _NEURONE_H_ +#define _NEURONE_H_ +#include<iostream> +#include<math.h> +#include<vector> +#include<random> +#include "FonctionActivation.h" + +class Neurone { +protected: + std::vector<double> * w; + int n; + FonctionActivation fonctionActivation; +public: + Neurone(); + Neurone(int taille,FonctionActivation::EnumFonctionActivation fct); + Neurone(int taille, std::vector<double> * x,FonctionActivation::EnumFonctionActivation fct); + virtual double fw_sum(std::vector<double> x)const; + double fw_activate(double sum, double k)const; + double derive_activate(double sum, double k)const; + virtual double fire(std::vector<double> x, double k) const; + virtual void learn(std::vector<double> x,double o,double k, double mu); + virtual void printWeight(); + virtual void aleaWeights(); + std::vector<double> * getWeight(); + virtual int getNbPoids(); +}; +#endif diff --git a/Neurone/NeuroneB.cpp b/Neurone/NeuroneB.cpp new file mode 100644 index 0000000..4556f8e --- /dev/null +++ b/Neurone/NeuroneB.cpp @@ -0,0 +1,85 @@ +#include"./NeuroneB.h"
+/**
+ * Constructeur du Neurone avec biais
+ * @method NeuroneB::NeuroneB
+ * @param taille Taille du neurone
+ * @param x Vecteur de poids
+ * @param biais_w Valeur du biais
+ */
+NeuroneB::NeuroneB(int taille,std::vector<double> * x, double biais_w){
+ n = taille;
+ w = x;
+ w->push_back(biais_w);
+}
+
+/**
+ * Constructeur du Neurone avec biais
+ * @method NeuroneB::NeuroneB
+ * @param taille Taille du neurone
+ */
+NeuroneB::NeuroneB(int taille,FonctionActivation::EnumFonctionActivation fct) {
+ n = taille;
+ fonctionActivation.setFonctionActivation(fct);
+ aleaWeights();
+}
+
+/**
+ * Affichage des poids
+ * @method NeuroneB::printWeight
+ */
+void NeuroneB::printWeight(){
+ Neurone::printWeight();
+ std::cout << "biais = " << (*w)[n] << std::endl;
+}
+
+/**
+ * Génération aléatoire des poids
+ * @method NeuroneB::aleaWeights
+ */
+void NeuroneB::aleaWeights(){
+ w = new std::vector<double> (n,0.8);
+ std::default_random_engine generator(std::random_device{}());
+ std::normal_distribution<double> distribution(0,1);
+ for (int i=0; i<n; i++) {
+ (*w)[i] = distribution(generator);
+ }
+ w->push_back(distribution(generator));
+}
+
+/**
+ * Méthode d'apprentissage (cf Neurone::fw_sum, cf Neurone::fw_activate, cf Neurone::derive_activate)
+ * @method Neurone::learn
+ * @param x Vecteur de poids
+ * @param o Valeur attendue
+ * @param k Valeur du biais
+ * @param mu Taux d'apprentissage | Learning rate
+ */
+void NeuroneB::learn(std::vector<double> x,double o,double k, double mu){
+ double sum = fw_sum(x);
+ double res = fw_activate(sum,k);
+ double derive = derive_activate(sum,k);
+ for(int i=0; i<n; i++){
+ (*w)[i]= (*w)[i]- mu * (x[i]*derive*((o-res)*(-2)));
+ }
+ (*w)[n] = (*w)[n]- mu * (1*derive*((o-res)*(-2)));
+}
+
+/**
+ * Méthode de somme du vecteur de poids
+ * @method NeuroneB::fw_sum
+ * @param x Vecteur de poids
+ * @return Somme des poids
+ */
+double NeuroneB::fw_sum(std::vector<double> x)const{
+ double res = Neurone::fw_sum(x);
+ res += (*w)[n];
+ return res;
+}
+
+/**
+ * @method NeuroneB::getNbPoids
+ * @return Nombre de poids
+ */
+int NeuroneB::getNbPoids(){
+ return n+1;
+}
diff --git a/Neurone/NeuroneB.h b/Neurone/NeuroneB.h new file mode 100644 index 0000000..fb54ccd --- /dev/null +++ b/Neurone/NeuroneB.h @@ -0,0 +1,35 @@ +#ifndef _NEURONEB_H_
+#define _NEURONEB_H_
+#include"./Neurone.h"
+
+class NeuroneB : public Neurone {
+public:
+ NeuroneB(int taille,FonctionActivation::EnumFonctionActivation fct); // Poids et biais random
+ NeuroneB(int taille,std::vector<double> * x,double biais_w);
+ void printWeight();
+ void aleaWeights();
+ void learn(std::vector<double> x,double o,double k, double mu);
+ double fw_sum(std::vector<double> x)const;
+ int getNbPoids();
+};
+#endif
+
+/**
+ * La classe NeuroneB est represente des neurones particuliers
+ * dotés d'un biais, elle redefinie les fonctions ou le comportement
+ * est different a cause du biais,
+ * petit point sur les methodes "virtual" dans Neurone.h :
+ * Le mot clé virtual permet de declarer une fonction virtuelle
+ * en clair, quand on fait un heritage, on peut faire rentrer un Pointeur
+ * sur un objt fils dans un pointeur sur un objet pere, or, en faisant
+ * cela, on perd la vrai nature de l'objet, exemple si on cree un
+ * NeuroneB dans un pointeur Neurone, et que l'on appelle sa methode getWeight
+ * ce sera la methode de Neurone qui sera appellé, car pour le compilateur, on a un objet
+ * En mentionant que la methode de l'ojet pere est virtuelle, on dit au
+ * "Hey poto, je risque d'appeller cette methode depuis un objet qui semble etre
+ * Neurone, mais qui sera ptet un NeuroneB, donc attend de voir, et appelle la methode de la classe correspondante
+ * A terme ce sera super pratique : exemple
+ * On est dans Layer, on cree un pack de Neurone, a la creation, on choisit si ce sont des Neurone, ou des
+ * on les stocke quoi qu'il arrive dans un vector<Neurone*> et on pourra ensuite travailler de la meme maniere, qu'
+ * s'agisse de NeuroneB ou non.
+ */
|
