-
Backpropagation and C++
Posted on May 30th, 2009 No commentsOn recommendation form a fellow coder, I’m reposting this question here.
I can never seem to get backpropagation right, and every time I ask for help, noone seems to be able to answer or their suggestions don’t solve the problem. So, I thought I might ask for help from a different point — my classes without the backprop algorithm.
Can anyone tell me the procedure for backpropagating, based on the source below? I merely need to know how the backpropagation algorithm would work for my class setup (I’ve been trying to get the darned thing for 2 years now — clearly I’m using the wrong approach).#include
#include
#includeclass neuron
{
public:
float ** input;
float * weight;
unsigned numInputs;
float output;
float dummy; // for returning bad referencesneuron(unsigned input_numInputs);
neuron();
void rebuild(unsigned input_numInputs);
~neuron();
void setInput(neuron& n, unsigned inputIndex);
void setInput(float& floatInput, unsigned inputIndex);
float& getInput(unsigned inputIndex);
void recalc();
void setWeight(unsigned inputIndex, float value);
};class neuralNetwork
{
public:
unsigned numInputLayer;
unsigned numHiddenLayer;
unsigned numInputs;
float * input;
neuron * inputLayer;
neuron * hiddenLayer;
neuron outputLayer;neuralNetwork(unsigned input_numInputs, unsigned input_numInputLayer, unsigned input_numHiddenLayer);
~neuralNetwork();
};float XOR(float input1, float input2, float biasLower = 0.0f, float biasUpper = 1.0f);
void neuron::setWeight(unsigned inputIndex, float value)
{
if (inputIndex >= numInputs)
return;
weight[inputIndex] = value;
}
void neuron::recalc()
{
if (numInputs <= 0)
return;
float weightedInput = 0.0f;
for (unsigned i = 0 ; i = numInputs)
return;
else
input[inputIndex] = &floatInput;
}
float& neuron::getInput(unsigned inputIndex)
{
if (inputIndex >= numInputs)
return(dummy);
else
return(input[inputIndex][0]);
}
neuron::neuron()
{
numInputs = 0;
}
neuron::neuron(unsigned input_numInputs)
{
numInputs = 0;
rebuild(input_numInputs);
}
void neuron::rebuild(unsigned input_numInputs)
{
if (numInputs > 0)
{
delete[] input;
delete[] weight;
}
numInputs = input_numInputs;
input = new float*[numInputs];
weight = new float[numInputs];
}
neuron::~neuron()
{
if (numInputs >= 0)
{
delete input;
delete weight;
}
}
void neuron::setInput(neuron& n, unsigned inputIndex)
{
if (inputIndex >= numInputs)
return;
input[inputIndex] = &n.output;
}neuralNetwork::neuralNetwork(unsigned input_numInputs, unsigned input_numInputLayer, unsigned input_numHiddenLayer)
{
unsigned i,j;
numInputs = input_numInputs;
numHiddenLayer = input_numHiddenLayer;
numInputLayer = input_numInputLayer;
input = new float[numInputs];
inputLayer = new neuron[numInputLayer];hiddenLayer = new neuron[numHiddenLayer];
outputLayer.rebuild(numHiddenLayer);
for (i = 0 ; i < numHiddenLayer ; i++)
{
hiddenLayer[i].rebuild(numInputLayer);
outputLayer.setInput(hiddenLayer[i],i);
}
for (i = 0 ; i < numInputLayer ; i++)
{
inputLayer[i].rebuild(numInputs);
for (j = 0 ; j < numHiddenLayer ; j++)
hiddenLayer[j].setInput(inputLayer[i],i);
}
for (i = 0 ; i < numInputs ; i++)
for (j = 0 ; j 0)
delete input;
if (numInputLayer > 0)
delete[] inputLayer;
if (numHiddenLayer > 0)
delete[] hiddenLayer;}
float XOR(float input1, float input2, float biasLower, float biasUpper)
{
float correctedInput1, correctedInput2;
if (input1 < ((biasLower + biasUpper)/2.0f))
correctedInput1 = biasLower;
else
correctedInput1 = biasUpper;
if (input2 < ((biasLower + biasUpper)/2.0f))
correctedInput2 = biasLower;
else
correctedInput2 = biasUpper;
if (correctedInput1 == correctedInput2)
{
return(biasLower);
}
else
{
return(biasUpper);
}
}int main(int argc, char* argv[])
{
neuralNetwork nn(2,2,1);
cout << “Done!” << endl;
getch();
return 0;
}– Crash Matrix
Followup: Following is the backpropagation code I use (which, btw, doesn’t work).
void neuralNetwork::backpropagate(float target)
{
if (numInputs == 0 || numInputLayer == 0 || numHiddenLayer == 0)
return;
float deltaOutput;
float * deltaHidden = new float[numHiddenLayer];
unsigned i,j;
/*
Note that there are two outputs used here:
1) The output of the current layer determines the delta value,
2) The output of the neuron connected to the input of the current neuron is used in
readjustment of the weight.
*/
// Do the output layer first
deltaOutput = (target - outputLayer.output) * outputLayer.output * (1.0f - outputLayer.output);
for (i = 0 ; i < numHiddenLayer ; i++)
outputLayer.weight[i] += learnRate * deltaOutput * hiddenLayer[i].output;
// Now do the hidden layer
for (j = 0 ; j < numHiddenLayer ; j++)
{
deltaHidden[j] = outputLayer.weight[j] * deltaOutput *
hiddenLayer[j].output * (1.0f - hiddenLayer[j].output);
for (i = 0 ; i < numInputLayer ; i++)
{
hiddenLayer[j].weight[i] += deltaHidden[j] * learnRate * inputLayer[i].output;
}
}
}And the way I run it is as follows:
unsigned i,j,k;
neuralNetwork nn(2,2,1);
for (k = 0 ; k < 100000 ; k++)
{
for (i = 0 ; i < 2 ; i++)
for (j = 0 ; j < 2 ; j++)
{
nn.input[0] = (float)i;
nn.input[1] = (float)j;
nn.recalc();
nn.backpropagate(XOR((float)i,(float)j));
if (k == 0 || k == 99999)
{
nn.recalc();
cout << i << ” XOR ” << j < ” << nn.outputLayer.output << ” SHOULD BE ” << XOR((float)i,(float)j) << endl;
}
}
if (k == 0 || k == 99999)
cout << endl;
}I know; I don’t set a precision limiter on it. But, the outputs never come any closer than 0.4 out of 1.0 (The low and high are 0.0 and 1.0 respectively and the outputs never go outside of 0.45 and 0.55). The outputs should move toward 1.0 and 0.0 (obviously), but they don’t.
Any ideas what’s wrong?Sorry, I actually had another change so that the hidden weight adjustments aren’t always exactly the same,
(which would be like having only one hidden weight)
so I also changed
hiddenLayer[j].setInput(inputLayer[i],i);
to
{
hiddenLayer[j].setInput(inputLayer[i],i);
hiddenLayer[j].setWeight(i,2.0*rand()/RAND_MAX-1);
}




Recent Comments