1 pièce(s) jointe(s)
Algorithme de descente du gradient, PMC
Bonjour a vous amis du clavier,et de la souris
alors voila,je suis sur un projet ou il faut developper un perceptron multicouche...j'ai codé ce dernier sous java,mais étant donné que j'ai des doutes sur la source du probleme,qu'il soit lié au langage,ou qu'il soit algorithmique,je me permet de poster ici.
En fait,le perceptron tel que je l'ai codé est sous forme d'un ensemble de vecteurs:le premier vecteur est un tableau de taille 256 accueillant un ensemble de valeurs a classifier de taille 256 aussi,et le deuxieme est de taille 10 et renvois un ensemble de 10 valeurs auxquelles il faut prendre le maximum qui sera donc la classe des données a analyser.
ces deux vecteurs sont au debut initialisés avec des valeurs aleatoires qui seront donc les poids de neurones,valeurs entre 0 et 1.
voici donc la classe "Reseau" que j'utilise afin de modeliser le pmc:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
public class Reseau {
private double[] couche_interne;
private double[] couche_interne2;
private double[] couche_sortie;
private double[] tabb;//tableau servant a des calculs intermediaires entre la couche interne et la couche de sortie
private double[] tabb_add;
public Reseau(){
couche_interne2=new double[256];
couche_interne=new double[256];
couche_sortie=new double[10];
for(int i=0;i<256;i++){
getCouche_interne()[i]=Math.random();
couche_interne2[i]=Math.random();
}
for(int j=0;j<10;j++){
getCouche_sortie()[j]=Math.random();
}
}
public double[] Calcul_Val2(double[] val) throws ErreurReseauException{//calcule les valeurs de la matrice representant le reseau de neuronnes.renvoie un tableau a une dimension qui est la sortie du reseau de neuronnes,prend en argument un tableau a une dimension
double[] tab2=new double[256];
double[] tab2_add=new double[256];
double[]tab3=new double[10];
if(getCouche_interne()==null){
throw new ErreurReseauException("Couche interne non initialisée");
}
else if(getCouche_sortie()==null){
throw new ErreurReseauException("Couche de sortie non initialisée");
}
else{
double x=1;//on regle le biais ici
for(int i=0;i<256;i++){
for(int j=0;j<256;j++){
x=x+(getCouche_interne()[i]*val[j]); //calcule les valeurs du vecteur de la couche interne du reseau.Chaque valeurs de la matrice ainsi obtenue est donc le vecteur passé a la couche de sortie.
}
tab2[i]=1/(1+Math.exp(-x));
x=0;
}
setTabb(tab2.clone());
x=1;
for(int i=0;i<10;i++){
for(int j=0;j<256;j++)
x=x+(getCouche_sortie()[i]*tab2[j]);
tab3[i]=1/(1+Math.exp(-x));
x=0;
}
}
return tab3;
} |
jusqu'ici,rien de bien plus compliqué que de vulgaires produits matriciels et vectoriels...
but,je galère avec l'apprentissage,qui est donc codé sous cette classe:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
public class Apprentissage extends Reseau {
private double seuil_erreur;// seuil d'erreur constituant le critere de convergence de l'algorithme de descente du gradient*/
private ArrayList <double[]> List;//examples utilisés afin d'apprendre au PMC*/
private int seuil_iterations;//iterations max du reseau*/
private double pas_param_appr;//parametre du pas d'apprentissage
public Apprentissage(double[] couche_interne,double[] couche_sortie,double seuil_erreur,ArrayList<double[]> List){
super(couche_interne,couche_sortie);
this.seuil_erreur=seuil_erreur;
this.List=List;
}
public Apprentissage(int it,double pas,ArrayList<double[]> List){
super();
this.seuil_iterations=it;
this.List=List;
this.pas_param_appr=pas;
}
public void Apprendre1(double[] val) throws ErreurReseauException{
while(seuil_iterations>=0){//convergence du PMC
Iterator T=List.iterator();//on parcours tous les échantillons de données permettant l'apprentissage
while(T.hasNext()){
double[] tab_pixels=(double[]) T.next();//j'utilise une arrayList,dans laquelle il y'a des tableaux double[] de dimension 256 qui constituent les données d'apprentissage
double[] vecteur_sortie_PMC=super.Calcul_Val2(tab_pixels);//propagation de l'information a travers le pmc:on recupere un vecteur de taille 10 en sortie
int classe=(int)tab_pixels[tab_pixels.length-1];//valeur de la classe de l'objet
double[] dk=new double[10];//tableau du gradient de chaques cellules de la couche de sortie
double[] dj=new double[256];//tableau du gradient de chaques cellules de la couche interne
double[] vecteur_ccaché=super.getTabb();
for(int i=0;i<dk.length;i++){//a mon avis,l'erreur est dans cette boucle
if(i==classe)
dk[i]=vecteur_sortie_PMC[i]*(1-vecteur_sortie_PMC[i])*(1-vecteur_sortie_PMC[i]);
else
dk[i]=vecteur_sortie_PMC[i]*(1-vecteur_sortie_PMC[i])*(0-vecteur_sortie_PMC[i]);
}
double somme_Dk_Wkj=0;
for(int i=0;i<10;i++) somme_Dk_Wkj=somme_Dk_Wkj+dk[i]*super.getCouche_sortie()[i];
for(int j=0;j<256;j++)
dj[j]=vecteur_ccaché[j]*(1-vecteur_ccaché[j])*somme_Dk_Wkj;
// calcul du pas et mise a jour des poids
double Dw_ji=0,Dw_kj=0;
for(int i=0;i<10;i++){
Dw_kj=pas_param_appr*dk[i]*super.getCouche_sortie()[i];
super.setCouche_sortie(super.getCouche_sortie()[i]+Dw_kj,i);
}
for(int i=0;i<256;i++){
Dw_ji=pas_param_appr*dj[i]*super.getCouche_interne()[i];
super.setCouche_interne(super.getCouche_interne()[i]+Dw_ji,i);
}
}
seuil_iterations--;
}
} |
Et donc,avec ceci je veux que ce pmc prenne en entrée pour l'entrainement,256 données+ 1 chiffre qui est la classe de ces données
et me renvoit un vecteur de taille 10(representant 10 neurones)...la valeur maximale de ce vecteur doit etre donc la classe des 256 valeurs en entrée
voila...le probleme,c'est que lorsque je lui fait apprendre un seul tableau,il arrive a modifier correctement les poids pour reconnaitre la classe des données de ce tableau...
par contre,lorsque j'essaye de l'entrainer avec toutes les données d'entrainement(donc a partir de 2 tableaux et plus),la sortie finale du pmc est un vecteur qui ressemble la plupart du temps a :
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 :aie:
ou bien
0.73.... 0.1 0.1 0.1 0.1 etc :aie:
et je note que la valeur 0.73 revient tres tres tres souvent en 1ere position.
j'espere avoir bien exposé le problème et m'en remet a votre sagesse et votre experience ;)
edit:j'ai mis en piece jointe le sujet du projet en lui meme,qui contient l'algorithme d'apprentissage...
en fait,dans la ligne dk<-ak(1-ak)(ypk-ak),ce que j'ai fait,c'est que lorsque pour dk[i],i egale la classe de l'objet,je fais dk<-ak(1-ak)(1-ak) (car on veux obtenir 1 pour la neurone de sortie i) et
dk<-ak(1-ak)(0-ak) lorsque i est different de la classe de l'objet
je ne sais pas si c'est ceci qu'il faut faire ou autre chose...