On 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 <iostream.h>
#include <conio.h>
#include <math.h>
class neuron
{
public:
float ** input;
float * weight;
unsigned numInputs;
float output;
float dummy; // for returning bad references
neuron(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 ; i++)
weightedInput += weight[i] * input[i][0];
output = 1.0f/ (1.0f + expf(0.0f-weightedInput));
}
void neuron::setInput(float& floatInput, unsigned inputIndex)
{
if (inputIndex >= 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::neuralNetwo
rk(unsigne
d 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(numHid
denLayer);
for (i = 0 ; i < numHiddenLayer ; i++)
{
hiddenLayer[i].rebuild(num
InputLayer
);
outputLayer.setInput(hidde
nLayer[i],
i);
}
for (i = 0 ; i < numInputLayer ; i++)
{
inputLayer[i].rebuild(numI
nputs);
for (j = 0 ; j < numHiddenLayer ; j++)
hiddenLayer[j].setInput(in
putLayer[i
],i);
}
for (i = 0 ; i < numInputs ; i++)
for (j = 0 ; j < numInputLayer ; j++)
inputLayer[j].setInput(inp
ut[i],i);
}
neuralNetwork::~neuralNetw
ork()
{
if (numInputs > 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::backpropaga
te(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((floa
t)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?
-- CM
Start Free Trial