Hallo Leute,
ich habe meine ersten Versuche mit neuronalen Netzen gestartet und wollte dazu ein Programm schreiben, welches das XOR Problem lösen soll. (Also für Input 0|0 und 1|1 soll der Output 0 sein und für 0|1 und 1|0 soll der Output 1 sein.)
Ich verwende ein neuronales Netz mit 3 Neuronen. 2 im 0. Layer und 1 Neuron im 1. (Output-) Layer.
Als Aktivierungsfunktion verwende ich die sigmoide Funktion sig(z) = 1/(1+e^-z).
Als Loss Funktion verwende ich die Root-Mean Squared Error Funktion.
Leider habe ich das Problem, dass der Output meines Programms immer gegen 1 konvergiert und dadurch eine Accuracy von ≈ 50% erreicht wird.
Ich habe schon sehr lange versucht den Fehler zu finden, aber leider finde ich den Fehler nicht. Ich vermute, aber dass es sich eher um einen Denk-/Verständnisfehler handelt als um einen Programmierfehler, weil ich Programm und Funktionen mehrfach abgeglichen habe und ich den Programmierstil möglichst schlicht gehalten habe. (Kein besonders schöner Stil, weil ich nur versucht habe dieses eine Problem mit einem hardcoded Netzwerk zu lösen)
Ich würde mich sehr freuen, wenn jemand eine Idee hat woran das Problem liegen könnte oder jemand einen Tipp hat welche Dinge ich überprüfen sollte.
Hier mein Programm:
ich habe meine ersten Versuche mit neuronalen Netzen gestartet und wollte dazu ein Programm schreiben, welches das XOR Problem lösen soll. (Also für Input 0|0 und 1|1 soll der Output 0 sein und für 0|1 und 1|0 soll der Output 1 sein.)
Ich verwende ein neuronales Netz mit 3 Neuronen. 2 im 0. Layer und 1 Neuron im 1. (Output-) Layer.
Als Aktivierungsfunktion verwende ich die sigmoide Funktion sig(z) = 1/(1+e^-z).
Als Loss Funktion verwende ich die Root-Mean Squared Error Funktion.
Leider habe ich das Problem, dass der Output meines Programms immer gegen 1 konvergiert und dadurch eine Accuracy von ≈ 50% erreicht wird.
Ich habe schon sehr lange versucht den Fehler zu finden, aber leider finde ich den Fehler nicht. Ich vermute, aber dass es sich eher um einen Denk-/Verständnisfehler handelt als um einen Programmierfehler, weil ich Programm und Funktionen mehrfach abgeglichen habe und ich den Programmierstil möglichst schlicht gehalten habe. (Kein besonders schöner Stil, weil ich nur versucht habe dieses eine Problem mit einem hardcoded Netzwerk zu lösen)
Ich würde mich sehr freuen, wenn jemand eine Idee hat woran das Problem liegen könnte oder jemand einen Tipp hat welche Dinge ich überprüfen sollte.
Hier mein Programm:
Code:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <time.h>
float sigmoid(float z);
void computeTeta(int numberNeuron);
/* Daten der 3 Neuronen
0. f input 1
1. f input 2
2. f output
3. weight input 1
4. weight input 2
5. bias
6. layer
*/
float neuron[3][8] = {{0,0,0,1,1,1,0},{0,0,0,1,1,1,0},{0,0,0,1,1,1,1}};
float alpha = 0.1; //Lernrate
float teta[3] = {0,0,0};
//berechnet Summe der gewichteten Inputs für das übergebene Neuron
float computeY(int numberNeuron){
return (neuron[numberNeuron][3]*neuron[numberNeuron][0]) + (neuron[numberNeuron][4]*neuron[numberNeuron][1]) + neuron[numberNeuron][5];
}
//berechnet den Output f für das übergebene Neuron
void computeF(int numberNeuron){
float y;
y = computeY(numberNeuron);
float f = sigmoid(y);
neuron[numberNeuron][2] = f;
}
//gradienten Schritt zur Aktualisierung der Gewichtungen und des Bias für das übergebene Neuron
void gradientStep(int numberNeuron){
computeTeta(numberNeuron);
float weight1 = neuron[numberNeuron][3];
float weight2 = neuron[numberNeuron][4];
float bias = neuron[numberNeuron][5];
weight1 = weight1 - alpha*teta[numberNeuron]*neuron[numberNeuron][0];
weight2 = weight2 - alpha*teta[numberNeuron]*neuron[numberNeuron][1];
bias = bias - alpha*teta[numberNeuron];
neuron[numberNeuron][3] = weight1;
neuron[numberNeuron][4] = weight2;
neuron[numberNeuron][5] = bias;
}
//berechnet den relativen Fehler abhängig vom Layer in dem sich das übergebene Neuron befindet
void computeTeta(int numberNeuron){
float f = neuron[numberNeuron][2];
if(neuron[numberNeuron][6] == 1){ //Berechnung für Hidden-Layer
float y = computeY(numberNeuron);
teta[numberNeuron] = -(y-f)*f*(1-f);
} else { //Berechnung für Output-Layer
teta[numberNeuron] = f*(1-f)*(teta[2]*neuron[2][3]+teta[2]*neuron[2][4]);
}
}
//Führt die gradienten Schritte für die 3 Neuronen durch
void backpropagation(){
gradientStep(2);
gradientStep(1);
gradientStep(0);
}
// Sigmoide Aktivierungs-Funktion um kontinuierliche Werte zu erhalten
float sigmoid(float z){
float value = 1 + pow(exp(1), -z);
return 1/value;
}
void trainNeurons(){
int cycles = 10000; //Anzahl der Training-Zyklen
for(int i = 0; i<cycles; i++){
int in1 = rand() % 2; //Zufällige Input Werte
int in2 = rand() % 2;
neuron[0][0] = in1; //Setzt Inputs der Neuronen im 1. Layer
neuron[0][1] = in2;
neuron[1][0] = in1;
neuron[1][1] = in2;
computeF(0); //Berechnet Outputs der Neuronen im 1. Layer
computeF(1);
neuron[2][0] = neuron[0][2]; //Setzt Inputs des Output-Neurons
neuron[2][1] = neuron[1][2];
computeF(2); //Berechnet Output des Output-Neurons
if(((in1 == 0 && in2 == 0)||(in1 == 1 && in2 == 1)) && neuron[2][2] >= 0.5){
backpropagation();
} else if(((in1 == 0 && in2 == 1)||(in1 == 1 && in2 == 0)) && neuron[2][2] < 0.5){
backpropagation();
}
}
}
void testNeurons(){
int count = 0;
int cycles = 1000;
for(int i = 0; i<cycles; i++){
int in1 = rand() % 2;
int in2 = rand() % 2;
neuron[0][0] = in1;
neuron[0][1] = in2;
neuron[1][0] = in1;
neuron[1][1] = in2;
computeF(0);
computeF(1);
neuron[2][0] = neuron[0][2];
neuron[2][1] = neuron[1][2];
computeF(2);
if(((in1 == -1 && in2 == 0)||(in1 == 1 && in2 == 1)) && neuron[2][2] < 0.5){
count++;
} else if(((in1 == 0 && in2 == 1)||(in1 == 1 && in2 == 0)) && neuron[2][2] >= 0.5){
count++;
}
}
std::cout << "Accuracy: " << (float)count/(float)cycles << std::endl;
}
int main(){
srand(time(NULL));
trainNeurons();
testNeurons();
return 0;
}