Ich habe viel über Neural Networks gelesen und sie mit Backpropagation, in erster Linie this Coursera course, mit zusätzlichen Lesen von here und here. Ich dachte, ich hätte ein ziemlich gutes Verständnis des Kernalgorithmus, aber mein Versuch, ein Backpropagation-trainiertes neuronales Netz aufzubauen, hat nicht ganz geklappt und ich bin mir nicht sicher warum.Neuronale Netzwerk Backpropagation Implementation Probleme
Der Code ist in C++ mit noch keiner Vektorisierung.
Ich wollte eine einfache 2 Eingabe Neuronen, 1 verstecktes Neuron, 1 Ausgabe Neuron, Netzwerk, um die UND-Funktion zu modellieren. Nur um zu verstehen, wie die Konzepte funktionierten, bevor Sie zu einem komplexeren Beispiel übergingen. Mein Vorwärts-Ausbreitungscode funktionierte, als ich die Werte für die Gewichte und Verzerrungen manuell codierte.
float NeuralNetwork::ForwardPropagte(const float *dataInput)
{
int number = 0; // Write the input data into the input layer
for (auto & node : m_Network[0])
{
node->input = dataInput[number++];
}
// For each layer in the network
for (auto & layer : m_Network)
{
// For each neuron in the layer
for (auto & neuron : layer)
{
float activation;
if (layerIndex != 0)
{
neuron->input += neuron->bias;
activation = Sigmoid(neuron->input);
} else {
activation = neuron->input;
}
for (auto & pair : neuron->outputNeuron)
{
pair.first->input += static_cast<float>(pair.second)*activation;
}
}
}
return Sigmoid(m_Network[m_Network.size()-1][0]->input);
}
Einige dieser Variablen sind ziemlich schlecht genannt, aber im Grunde genommen neuron-> outputNeuron ist ein Vektor von Paaren. Der erste ist ein Zeiger auf das nächste Neuron und der zweite ist der Gewichtswert. neuron -> input ist der "z" -Wert in der neuronalen Netzwerkgleichung, die Summe aller Werte * activation + bais. Sigmoid ist gegeben durch:
float NeuralNetwork::Sigmoid(float value) const
{
return 1.0f/(1.0f + exp(-value));
}
Diese beiden scheinen wie vorgesehen zu funktionieren. Nach einem Durchlauf über das Netzwerk werden alle Werte von 'z' oder 'neuron -> input' auf Null (oder nach Backpropagation) zurückgesetzt.
Ich trainiere dann das Netzwerk nach dem untenstehenden Psudo-Code. Der Trainingscode wird mehrmals ausgeführt.
for trainingExample=0 to m // m = number of training examples
perform forward propagation to calculate hyp(x)
calculate cost delta of last layer
delta = y - hyp(x)
use the delta of the output to calculate delta for all layers
move over the network adjusting the weights based on this value
reset network
Der eigentliche Code ist hier:
void NeuralNetwork::TrainNetwork(const std::vector<std::pair<std::pair<float,float>,float>> & trainingData)
{
for (int i = 0; i < 100; ++i)
{
for (auto & trainingSet : trainingData)
{
float x[2] = {trainingSet.first.first,trainingSet.first.second};
float y = trainingSet.second;
float estimatedY = ForwardPropagte(x);
m_Network[m_Network.size()-1][0]->error = estimatedY - y;
CalculateError();
RunBackpropagation();
ResetActivations();
}
}
}
Mit der Backpropagation Funktion gegeben durch:
void NeuralNetwork::RunBackpropagation()
{
for (int index = m_Network.size()-1; index >= 0; --index)
{
for(auto &node : m_Network[index])
{
// Again where the "outputNeuron" is a list of the next layer of neurons and associated weights
for (auto &weight : node->outputNeuron)
{
weight.second += weight.first->error*Sigmoid(node->input);
}
node->bias = node->error; // I'm not sure how to adjust the bias, some of the formulas seemed to point to this. Is it correct?
}
}
}
und die Kosten berechnet:
void NeuralNetwork::CalculateError()
{
for (int index = m_Network.size()-2; index > 0; --index)
{
for(auto &node : m_Network[index])
{
node->error = 0.0f;
float sigmoidPrime = Sigmoid(node->input)*(1 - Sigmoid(node->input));
for (auto &weight : node->outputNeuron)
{
node->error += (weight.first->error*weight.second)*sigmoidPrime;
}
}
}
}
ich zufällig die Gewichte und führen Sie es auf den Daten s et:
x = {0.0f,0.0f} y =0.0f
x = {1.0f,0.0f} y =0.0f
x = {0.0f,1.0f} y =0.0f
x = {1.0f,1.0f} y =1.0f
Natürlich soll ich nicht Ausbildung und Prüfung mit den gleichen Daten gesetzt, aber ich wollte nur den Grund backpropagation algortithm bis bekommen und läuft. Wenn ich diesen Code ausführen Ich sehe die Gewichte/Vorurteile sind wie folgt:
Layer 0
Bias 0.111129
NeuronWeight 0.058659
Bias -0.037814
NeuronWeight -0.018420
Layer 1
Bias 0.016230
NeuronWeight -0.104935
Layer 2
Bias 0.080982
Der Trainingssatz läuft und die mittlere quadratische Fehler von Delta [outputLayer] sieht ungefähr wie:
Error: 0.156954
Error: 0.152529
Error: 0.213887
Error: 0.305257
Error: 0.359612
Error: 0.373494
Error: 0.374910
Error: 0.374995
Error: 0.375000
... remains at this value for ever...
und die endgültige Gewichte wie folgt aussehen: (sie bei roughtly diesen Wert am Ende immer)
Layer 0
Bias 0.000000
NeuronWeight 15.385233
Bias 0.000000
NeuronWeight 16.492933
Layer 1
Bias 0.000000
NeuronWeight 293.518585
Layer 2
Bias 0.000000
ich akzeptiere, dass dies wie ein ganz Umwegen neuronale Netze des Lernens und die Umsetzung ist scheinen mag (an der m oment) sehr unoptimal. Aber kann irgendjemand irgendeinen Punkt ausmachen, an dem ich eine ungültige Annahme mache, oder ist entweder die Implementierung oder die Formel falsch?
EDIT
Danke für das Feedback für die Bias-Werte, I hielt sie auf die Schicht Eingang angelegt wird, und beendet die Eingangsschicht durch die Sigmoid-Funktion übergeben. Außerdem war meine Sigmoid Primefunktion ungültig. Aber das Netzwerk funktioniert immer noch nicht. Ich habe den Fehler aktualisiert und oben mit dem, was jetzt passiert, ausgegeben.
Warum haben Sie so viele Vorurteile? 2-1-1 Netzwerk sollte insgesamt 5 Parameter haben: 2 Gewichte zwischen Eingangsneuronen und einem versteckten; 1 Gewicht zwischen der Vorspannung in der Eingangsschicht und dem versteckten Neuron; 1 Gewicht zwischen versteckter Schicht und Ausgangsneuron; 1 Gewicht zwischen Bias in versteckter Schicht und Ausgangsneuron. Insgesamt 5 Gewichte. Sogar dein Code zeigt dir so - du und ohne diese 2 redundanten Vorurteile – lejlot
Danke für deine Hilfe bei den Voreingenommenheiten, siehe meine Antwort auf Galloguille für weitere Erklärungen. Ich habe das behoben, aber ich habe immer noch Probleme mit dem neuronalen Netzwerk, das die Gewichte immer auf die Werte w11 (15.385233), w12 (16.492933), w21 (293.518585) trainiert. Alle Verzerrungen werden Null. Offensichtlich gibt es noch ein anderes Problem mit dem Code. – Davors72