Ich habe die letzten zwei Wochen über Backpropagation gelernt, habe die Mathematik dahinter gemacht und dachte, dass ich das Thema gut genug für meine eigene Implementierung verstehe (ohne irgendwelche linearen Algebra-Pakete usw.). Anscheinend lag ich falsch. Im Folgenden finden Sie das einfachste Beispiel Netzwerk, das ich mir vorstellen kann: 2 versteckte Einheiten und 1 Ausgabeeinheit. Ich versuche die XOR-Funktion zu lernen. Das funktioniert aber überhaupt nicht. Die Vorhersage ist immer um 0.5
. Ich bin mir nicht sicher, wo ich versagt habe. Vielleicht könnte jemand helfen?Backpropagation funktioniert nicht für XOR
float sigmoid(float pX) {
return 1.0f/(1.0f+exp(-1.0f*pX));
}
int main(int argc, char const *argv[]) {
// DEFINE XOR problem
float examples[4][2] = { {0,0} , {0,1}, {1,0}, {1,1}};
float labels[4] = {0, 1, 1, 0};
/* I want to use a network with two hidden neurons and 1 output neuron
*/
// Weights from input to hidden neurons
float WInput[2][2];
float WInputBias[2];
// Weights from hidden to output neuron
float WOutput[2];
float WOutputBias;
// output of hidden layer to output neuron
float hidden[2];
// error for hidden layer
float error[2];
//output of network
float yPred;
// randomly init weights
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<float> d(0, 0.1);
WInput[0][0] = d(gen); WInput[0][1] = d(gen);
WInput[1][0] = d(gen); WInput[1][1] = d(gen);
WInputBias[0] = d(gen); WInputBias[1] = d(gen);
WOutput[0] = d(gen); WOutput[1] = d(gen); WOutputBias = d(gen);
// do the learning
for(unsigned int i = 0; i < 1000; ++i) {
for (unsigned int k = 0; k < 4; ++k) {
float * input = &examples[k][0];
float label = labels[k];
// Compute forward pass
hidden[0] = sigmoid(WInput[0][0]*input[0] + WInput[1][0]*input[1] + WInputBias[0]);
hidden[1] = sigmoid(WInput[0][1]*input[0] + WInput[1][1]*input[1] + WInputBias[1]);
yPred = sigmoid(WOutput[0]*hidden[0] + WOutput[1]*hidden[1] + WOutputBias);
std :: cout << "Target/Prediction: " << label << "/" << yPred << std :: endl;
// Backward pass with alpha = 0.1
float outputError = -(label - yPred)*yPred*(1-yPred);
WOutput[0] = WOutput[0] - 0.1f*outputError*hidden[0]; //hidden equals input from this layer
WOutput[1] = WOutput[1] - 0.1f*outputError*hidden[1];
WOutputBias = WOutputBias - 0.1f*outputError;
error[0] = (WOutput[0]*outputError)*hidden[0]*(1-hidden[0]);
error[1] = (WOutput[1]*outputError)*hidden[1]*(1-hidden[1]);
WInput[0][0] = WInput[0][0] - 0.1f*error[0]*input[0];
WInput[1][0] = WInput[1][0] - 0.1f*error[0]*input[1];
WInput[0][1] = WInput[0][1] - 0.1f*error[1]*input[0];
WInput[1][1] = WInput[1][1] - 0.1f*error[1]*input[1];
WInputBias[0] = WInputBias[0] - 0.1f*error[0];
WInputBias[1] = WInputBias[1] - 0.1f*error[1];
}
std :: cout << std :: endl;
// getch();
}
}
Ich fürchte, das ist zu breit. Hast du es debuggen? Kannst du ein [MCVE] zeigen? Hier ist eine ehrfürchtige und sehr einfache XOR Neural Network Implementation, die die BackPropagation-Methode verwendet, und viel Glück: https://vimeo.com/19569529 –
Ich weiß, dass dies eine Art von breiter Frage ist, aber das ist die minimale und vollständiges Beispiel, an das ich denken könnte. Ich mache gerade einen Kalkül auf Papier (wieder), aber bisher scheint der Vorwärtsdurchlauf korrekt berechnet worden zu sein. Es muss ein Problem mit dem Backprop-Schritt geben. Danke für das Video, das habe ich heute schon gefunden. Ich habe gerade den Quellcode in den Kommentaren gefunden. Vielleicht hilft das. – user1228633
In deiner '// mach die Lern'-Schleife machst du das:' float * input = & examples [k] [0] 'und versuche es später als Array zu verwenden. 'Examples [i] [j]' ist jedoch ein float, kein Zeiger auf einen float (read: kein Array). Es sieht so aus, als ob Sie in Ihrer '// Lernschleife 'stattdessen folgendes möchten:' float * input = & examples [k] '. Sie erhalten wahrscheinlich falsche Eingaben, die mit Ihren erwarteten Ausgaben nicht übereinstimmen, da Sie über das Ende eines Arrays hinaus gelesen haben (und höchstwahrscheinlich in das nächste). Das ist alles zu sagen, es sei denn, ich verpasse etwas ... – Altainia