double = NAN, obwohl ich nirgends durch NULL teilen kann?!



  • ich bekomme ein ganz merkwürdige ausgabe im programm, und frage mich wie dieser fehler auftreten kann, wenn eine division ausgeschlossen ist.
    außerdem verschwindet der fehler wenn ich die ausgabe wiederhole... mir fällt irgendwie nicht ein, warum sowas auftreten könnte!

    TEST-Ausgabe: 0
    Ausgabeneuron 0 = 9.55705e-05
    Ausgabeneuron 1 = 4.47981e-07
    Ausgabeneuron 2 = 0.0245569
    Ausgabeneuron 3 = 2.88943e-09
    Ausgabeneuron 4 = 4.79755e-10
    Ausgabeneuron 5 = 8.67928e-05
    Ausgabeneuron 6 = 1.489e-05
    Ausgabeneuron 7 = 0.0321845
    Ausgabeneuron 8 = 1.11353e-05
    Ausgabeneuron 9 = 0.994252
    TEST-Ausgabe: 1
    Ausgabeneuron 0 = nan
    Ausgabeneuron 1 = nan
    Ausgabeneuron 2 = nan
    Ausgabeneuron 3 = nan
    Ausgabeneuron 4 = nan
    Ausgabeneuron 5 = nan
    Ausgabeneuron 6 = nan
    Ausgabeneuron 7 = nan
    Ausgabeneuron 8 = nan
    Ausgabeneuron 9 = nan
    
    Wiederholung:
    TEST-Ausgabe: 0
    Ausgabeneuron 0 = 9.77298e-05
    Ausgabeneuron 1 = 4.36772e-07
    Ausgabeneuron 2 = 0.0251543
    Ausgabeneuron 3 = 2.83783e-09
    Ausgabeneuron 4 = 4.69154e-10
    Ausgabeneuron 5 = 8.5453e-05
    Ausgabeneuron 6 = 1.51131e-05
    Ausgabeneuron 7 = 0.0315974
    Ausgabeneuron 8 = 1.09645e-05
    Ausgabeneuron 9 = 0.994419
    TEST-Ausgabe: 1
    Ausgabeneuron 0 = 0.989671
    Ausgabeneuron 1 = 7.99327e-06
    Ausgabeneuron 2 = 0.000325618
    Ausgabeneuron 3 = 0.000418063
    Ausgabeneuron 4 = 0.00302999
    Ausgabeneuron 5 = 0.000308444
    Ausgabeneuron 6 = 2.53812e-05
    Ausgabeneuron 7 = 5.20772e-10
    Ausgabeneuron 8 = 2.95479e-10
    Ausgabeneuron 9 = 0.000717555
    


  • ich denke mal es wird dort Indizies uberschreitungen geben oder sowas.



  • ich werde das mal überprüfen, aber theoretisch dürfte es keine geben...



  • ich glaube, NAN tritt auch auf, wenn die Zahl zu groß wird (also 1/0.0000000000001) oder so was. Bin mir aber nicht sicher.

    Dass sich die Ausgabe jedesmal ändert, könnte an einer nicht initialisierten Variablen liegen (9.55705e-05 --> 9.77298e-05).



  • es gibt keine zugriffe auf nicht allokierte indices!

    BERECHNUNG von NEURON in Schicht: 2; Pos=8 aus:
            Neuron: Schicht=1; Pos=0 ;Wert=0.853248
            Axon: Schicht=1; Neuron=0 ;Pos=8 ;Wert=-2.55708
    WERT: nan
    

    der fehler tritt zb beim multiplizieren der beiden werte auf... das kann doch nicht sein!!

    ich habe hier mal nen testfall geschaffen..



  • ja zeich mal den testfall, oder sollen wir hier raten?
    oder hoffst du auf hellsichtige?



  • Gugi schrieb:

    ich glaube, NAN tritt auch auf, wenn die Zahl zu groß wird (also 1/0.0000000000001) oder so was. Bin mir aber nicht sicher.

    Dass sich die Ausgabe jedesmal ändert, könnte an einer nicht initialisierten Variablen liegen (9.55705e-05 --> 9.77298e-05).

    Ne, das gibt höchstens Inf. NaN gibts bei 0/0 oder wenn Müll im Speicher steht der keinem gültigen IEEE-Float/Double-Wert entspricht, z.B. durch nicht initialisierte Variablen. Außerdem gibts immer wieder NaN, wenn man mathematische Operationen mit NaN durchführt. Also z.B. NaN * Zahl.



  • ok, ich versuche mal möglichst ordentlich den code zu posten:

    hier wird speicher angefordert...

    n_of_layers = nmb_of_layers;
    	n_of_neurons = nmb_of_neurons;
    	n_of_axons = nmb_of_axons;
    
    	//! erzeuge Layer
    	n_annet = new layer* [nmb_of_layers];
    	for(int i = 0; i < nmb_of_layers; i++) {
    		n_annet[i] = new layer(i, nmb_of_neurons[i], nmb_of_axons[i] );
    	}
    
    	//! Verknüpfe die Layer untereinander UND
    	//! fülle Layer mit Zufallszahlen
    	for(int i = 0; i < nmb_of_layers; i++) {
    
    		//! fülle neurone mit zufallszahlen
    		for(int j = 0; j < n_annet[i]->size_of_layer(); j++) {
    			n_annet[i]->getNeuAt(j)->setNeuVal(get_rand_nmb(1, 4));
    
    			//! fülle axone mit zufallszahlen
    			for(int k = 0; k < n_annet[i]->getNeuAt(j)->nmb_of_axons(); k++) {
    				n_annet[i]->getNeuAt(j)->setAxVal(get_rand_nmb(1, 4), k);
    
    				//! Verknüpfung
    				axon *curAxon = n_annet[i]->getNeuAt(j)->getAxon(k);
    				curAxon->setOwner(n_annet[i]->getNeuAt(j) );
    				// bin noch im vorlestzen Layer, 
    				// damit verknüpfung zum nächsten Layer noch möglich ist
    				if(i < nmb_of_layers - 1)
    					// i + 1 ist der nächste Layer und k entspricht dem k'ten Neuron
    					curAxon->setDest(n_annet[i+1]->getNeuAt(k) );
    			}
    		}
    	}
    

    das ist die lauffunktion mit ausgabe:

    float *annet::run_annet(float *eingabe, bool ausgabe) {
    	float *nextLayerNeurVal;
    
    	if(eingabe != NULL)
    		for(int j = 0; j < n_annet[0]->size_of_layer(); j++) {
    			n_annet[0]->getNeuAt(j)->setNeuVal(eingabe[j]);
    		}
    
    	/*! durchlaufe das netz*/
    	for(int i = 0; i < n_of_layers; i++) {
    		//! Anzahl der Axone pro Neuron entspr. der Neuronzahl im nächsten Layer
    		int neurNextLayer = n_annet[i]->getAxonPNeu();
    
    		//! array mit den errechneten werten der neurone für die nächste schicht
    		nextLayerNeurVal = new float[neurNextLayer];
    
    		/*!
    			Durchlaufe die einzelnen Schichten nacheinander und ausgehend von der Ersten.
    			Erste Schicht ist die Eingabeschicht (immer).
    		*/
    
    		/*!
    			Lauffunktion:
    			=SUMME(Neuron*Axon_i) = Neuron_i; 
    
    			i = schicht im netz
    			j = neuron in schicht i
    			k = axon von neuron j in schicht i
    		*/
    		for(int k = 0; k < neurNextLayer; k++) {
    			memset(nextLayerNeurVal, 0, neurNextLayer);
    			for(int j = 0; j < n_annet[i]->size_of_layer(); j++) {
    // 				std::cout<<i<<" - "<<j<<" - "<<k<<std::endl;
    
    				// val_cur_neur ist das aktuelle neuron
    				long double val_cur_neur = n_annet[i]->getNeuAt(j)->getNeuVal();
    				// axon nr. k von neuron: val_cur_neur
    				long double axon_cur_neur = n_annet[i]->getNeuAt(j)->getAxVal(k);
    
    				// Berechnung
    				nextLayerNeurVal[k] += val_cur_neur * axon_cur_neur;
    
    				/*!
    					ausgabe-test
    				*/
    				if(ausgabe) {
    					std::cout<<"BERECHNUNG von NEURON in Schicht: "<<i+1<<"; Pos="<<k<<" aus:"<<std::endl<<
    					"	Neuron: Schicht="<<i<<"; Pos="<<j<<" ;Wert="<<val_cur_neur<<std::endl<<
    					"	Axon: Schicht="<<i<<"; Neuron="<<j<<" ;Pos="<<k<<" ;Wert="<<axon_cur_neur<<std::endl<<
    					"WERT: "<<nextLayerNeurVal[k]<<std::endl<<std::endl;
    				}
    
    			}
    // 			if(i+1 <= n_of_layers-1)
    				n_annet[i+1]->getNeuAt(k)->setNeuVal(sigmoid_biasFkt(nextLayerNeurVal[k]) );
    		}
    	}
    	delete [] nextLayerNeurVal;
    	// Ausgabe
    	if(ausgabe) {
    		for(int k = 0; k < n_annet[n_of_layers-1]->size_of_layer(); k++)
    			std::cout<<"Ausgabeneuron "<<k<<" = "<<n_annet[n_of_layers-1]->getNeuAt(k)->getNeuVal()<<std::endl;
    	}
    }
    

    das sind dann ein paar funkionen in der klasse neuron:

    long double neuron::getNeuVal() {
    	return val;
    }
    
    void neuron::setAxVal(long double v, unsigned short pos) {
    	axone[pos]->setValue(v);
    }
    
    long double neuron::getAxVal(unsigned short pos) {
    	return axone[pos]->getValue();
    }
    
    axon *neuron::getAxon(unsigned short pos) {
    	return axone[pos];
    }
    

    WICHTIG: die ausgabe ändert sich nicht immer!!! lediglich das neuronen welche den wert NAN annehmnen, haben nach einen neuen durchlauf die richtigen werte... auch die speichern und laden funktion aus ner datei funktioniert....

    ich spiele auch mit dem gedanken, das irgendwo eine zahl auf glatt 0 gerundet wird, aber ich dividiere ja nirgends...

    wollt ihr evtl. noch die trainingsfunktion?



  • das wichtsigste vergessen:
    wo der speicher schließlich allokiert wurde:

    layer::layer(unsigned short nmb, unsigned short nmb_of_neurons, unsigned short nmb_of_axons) {
    	layerNmb = nmb;
    
    	std::cout<<"create layer with "<<nmb_of_neurons<<" neurons"<<std::endl;
    	l_dim = nmb_of_neurons;
    	l_axon = nmb_of_axons;
    
    	/*! erzeuge neuronen und fülle diese mit zufallszahlen*/
    	l_layer = new neuron* [l_dim];
    	for(int i = 0; i < l_dim; i++) {
    		l_layer[i] = new neuron(this, nmb_of_axons);
    	}
    }
    

    in der layer-klasse...


Anmelden zum Antworten