IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Erreur d'mplémentation sur RDN simple


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut Erreur d'mplémentation sur RDN simple
    Bonjour à tous,

    J'essaye depuis peu de monter un RDN simple, sans prétention, mais paramétrable afin de mieu comprendre le sujet et de développer par la même mes compétences en C. Si j'ai choisi ce langage, c'est parce-que je suis familier avec lui et que je ne suis pas fan des langages haut niveau et/ou interprétés. Mon but étant de comprendre, je fais le choix de ne pas utiliser de librairies "clik and play" qui existent sûrement un peu partout.

    J'ai donc procédé par étape : Neurone simple, couche, et réseau ; chacune étant représentée par une structure, une fonction d'initialisation et une fonction de calcul.

    Je fais fonctionner un neurone simple sans soucis, de même, j'arrive à initialiser une couche. Cependant, lors du calcul d'une couche, j'ai une belle erreur de segmentation.

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    void layer_compute(layer_t *lay, double *u_ent)
    {
    	for(int i = 0; i < lay->layer_nb_ker; i++)
    	{
    		kernel_compute(&(lay->layer_ker[i]), u_ent);
    		lay->layer_out[i]=lay->layer_ker[i].kor_out;
    	}	
     
    }
     
    double kernel_compute(kernel_t *kor, double *u_ent)
    {
    	kor->kor_int[0] = kor->kor_zint;
    	for(int i = 0; i < kor->kor_nb_int; i++)
    	{
    		kor->kor_int[i+1] = u_ent[i];
     
    		kor->kor_sum += (kor->kor_int[i+1] * kor->kor_win[i+1]);
    	}
    	kor->kor_sum += (kor->kor_int[0] * kor->kor_win[0]);
     
     
    	kor->kor_out = heaviside(kor->kor_sum);
     
    	return kor->kor_out;
     
    }
    J'ai supprimé le code "superflu", et, pour aider à la compréhension, les structures ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    typedef struct layer layer_t;
    typedef struct kernel kernel_t;
     
    struct layer {
    	int layer_nb_int;		// size of layer input vector
    	int layer_nb_ker;		// size of kernel vector
    	short int layer_func;	// layer function
     
    	double *layer_int;		// layer input vector
    	double *layer_out;		// layer output vector
    	double *layer_win;		// layer input weights
     
    	kernel_t *layer_ker;	// kernel vector
    };
     
    struct kernel {
    	short int kor_func;
    	int kor_nb_int;		// size of kernel input vector
    	double kor_zint;	// the 0 input value (default = -1)
     
    	double *kor_int;	// kernel input vector
    	double *kor_win;	// kernel input weights vector
    	double kor_sum;		// main kernel function result (sum)
    	double kor_out;		// kernel final computing result
    };
    Le code me retourne donc bien une valeur pour le premier neurone, mais après, c'est "erreur de segmentation".

    Les initialisations sont réalisée avec des tableaux dynamiques, cependant, lorsque je by-pass le layer et que je fais le calcul sur un simple neurone (initialisation et calcul), tout se déroule bien...
    J'ai essayé de reprendre plusieurs fois mon code, mais je me retrouve toujours face à cette situation : dès que j'essaie de passer l'objet d'un objet, ça foire....

    Quelqu'un saurait m'indiquer mon erreur ? Merci d'avance !!

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par BioKore Voir le message
    Quelqu'un saurait m'indiquer mon erreur ?
    Bonjour

    Il faudrait qu'on voit comment ont été alloués tes tableaux parce que c'est certainement là que ça cafouille. Toutefois je suis dubitatif sur ce passage for (int i = 0; i < kor->kor_nb_int; i++) kor->kor_int[i+1] = u_ent[i]. C'est ce "+1" qui m'embête parce que si kor_nb_int est bien corrélé à kor_int alors tu dépasses ton tableau.
    Exemple (selon ma compréhension): kor_int est alloué à 5, donc ses indices vont de 0 à 4. De son côté kor_nb_int vaut 5 (puisque d'après ce que je comprends, le nb de int correspond à la taille allouée).
    Quand i va de 0 à 4 et que tu tapes dans kor_int[i+1] alors tu tapes dans des indices allant de 1 à 5 or l'indice "kor_int[5]" est interdit !!!

    PS: tu n'es pas obligé de donner un nom à ta structure quand 1) elle n'est pas référencée dans sa définition (comme dans les listes) et 2) tu lui donnes un nom de type. Ce qui est tout à fait le cas ici.
    Exemple

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct {
    	short int kor_func;
    	int kor_nb_int;		// size of kernel input vector
    	double kor_zint;	// the 0 input value (default = -1)
     
    	double *kor_int;	// kernel input vector
    	double *kor_win;	// kernel input weights vector
    	double kor_sum;		// main kernel function result (sum)
    	double kor_out;		// kernel final computing result
    } kernel_t;
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Bonjour, et merci pour ce retour. Comme pour hier, c'et un problème d'initialisation en fait, effectivement. Je n'ai plus le soucis de débordement de mémoire, mais les poids de chaque neurone, initialisés via le layer se comportent bizarrement. Je pense que j'essaie de faire un truc très simple mais via un chemin très compliqué.... Bref.

    En ce qui concerne le kor_int[i+1], c'est normal. En fait, ce dernier est initialisé à taille_entrée +1 afin de pouvoir paramétrer l'entrée supplémentaire nécessaire (-1).
    Ainsi, si *u_ent = {1, 2, 4, 5, 8}, alors kor->kor_int = {-1, 1, 2, 4, 5, 8}. C'est normal et prévu. Cependant, j'ai décidé de simplifier encore donc cette partie est devenue :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    kor->kor_sum = kor->kor_zint * kor->kor_win[0];
    	for(int i = 0; i < kor->kor_nb_int; i++)
    	{
    		kor->kor_sum += u_ent[i] * kor->kor_win[i+1];
    	}
    Ce qui fonctionne correctement.

    Maintenant, mon soucis lors de l'initialisation est le suivant :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
     
    void une_fonction ( layer_t *lay, double *tab)
    {
    	for(int i = 0; i < 5; i++)
    	{
    		autre_fonction(&(lay->kern[i]), tab);
    		printf("value : %f\n", lay->kern[i].var);	// ok, ici lay->kern[i].var = 0.8;
    	}
    }
     
    void autre_fonction (kernel_t *kor, double *tab)
    {
    	kor->var = 0.8;
    }
     
     
    layer_t *ulay = malloc(sizeof(layer_t));
    if(ulay == NULL)
    	exit(EXIT_FAILURE);
     
    une_fonction(ulay, unTab);
     
    printf("value : %f\n", ulay->kern[i].var);		// ici ça donne une valeur différente de 0.8
     
    // pourtant, 
     
    kernel_t *ukor = malloc(sizeof(kernel_t));
    if(ukor == NULL)
    	exit(EXIT_FAILURE);
     
    autre_fonction(ukor, unTab);
    printf("value : %f\n", ukor->var);		// ceci retourne bien 0.8

    Donc là, j'ai beau cherché, je ne vois pas d'où vient l'erreur. Le seul truc que je peut voir, c'est le fameux ulay->kern[i].var, mais ça me surprendrais car cela fonctionne bien dans la boucle, mais plus quand on sort de la fonction...

  4. #4
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Quelle est la dernière définition du type layer_t ? Comment est déclaré le membre kern particulièrement ?

    Parce qu'allouer la mémoire pour la structure parente, c'est bien, mais si kern n'est pas un tableau de taille fixe, il faut l'allouer séparément..

  5. #5
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Eh, oui, c'est bien ce que je pensais.... En fait, je fais un "layer_t *lay = malloc(sizeof(layer_t))", mais en fait, dans la structure "layer_t", j'ai un "kernel_t *kor = malloc(sizeof(kernel_t) * nb_ker)", donc la taille de mon objet n'est alors pas suffisante...


    La solution serai-t elle de faire : "layer_t *lay = malloc(sizeof(layer_t) + sizeof(kernel_t)*nb_ker)" ?
    Je ne vois pas comment je pourrais l'allouer séparément sachant qu'il doit faire partie de layer_t

    Je vais essayer d'implémenter ça ce soir pour tester...


    Edit : Tous les tableaux présents dans mes structures sont dynamiques, je vais essayer de faire ça pour tous ces tableaux mais il doit exister une autre solution non ?

    Merci d'avance !

  6. #6
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Citation Envoyé par BioKore Voir le message
    La solution serai-t elle de faire : "layer_t *lay = malloc(sizeof(layer_t) + sizeof(kernel_t)*nb_ker)" ?
    Ça c'est l'allocation conjointe d'une structure et d'un tableau déclaré comme un flexible array member, une particularité du C99 que je doute que tu emploies.

    Si, comme c'est le plus probable, tu as déclaré ton membre comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct {
        // ...
     
        kernel_t *kern;
    } layer_t;
    ...alors kern est un simple pointeur et ce sur quoi il pointe est décorrélé de la zone mémoire qui héberge l'instance de ta structure. Si tu veux qu'il pointe sur une zone de mémoire valide, il faut lui en donner une et donc réaliser une allocation supplémentaire.


    Avant de te lancer dans un tel projet complexe, peut-être devrais-tu consolider les bases à travers des exercices plus simple de manipulation de zones mémoire et de références ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] erreur de syntaxe sur une requête très simple
    Par Anandamine dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 01/06/2012, 09h45
  2. [e4] Erreurs sur une simple appli RCP
    Par pingoui dans le forum Eclipse Platform
    Réponses: 4
    Dernier message: 26/07/2011, 22h48
  3. Erreur de compilation sur un interpreteur de commandes simples.
    Par Tibapbedoum dans le forum Autres éditeurs
    Réponses: 0
    Dernier message: 24/11/2008, 18h07
  4. Erreur sur un simple Select
    Par defluc dans le forum SQL
    Réponses: 4
    Dernier message: 25/03/2007, 20h10
  5. Erreur ORA-01036 sur un XMLGRAM
    Par sch dans le forum XMLRAD
    Réponses: 5
    Dernier message: 07/09/2004, 14h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo