I wrote a neural network in C. There is a neuron model structure and input, hidden then output layer structures. This code was actually written in Python but I transformed it to C. After the debugging or running there is a error like that "Run-Time Check Failure #2 - Stack around the variable 'outputLayer' was corrupted." The predicton output is correct but in the end the error occurred. Here is the code below.
#include<stdio.h>
#include<math.h>
#define INPUT_SIZE 3
#define HIDDEN_SIZE 8
#define OUTPUT_SIZE 1
#define LEARNING_RATE 0.09
#define EPOCHS 20000
struct Neuron {
double weights[INPUT_SIZE];
double bias;
};
double relu(double x) {
return fmax(0, x);
}
double sigmoid(double x) {
return 1.0 / (1.0 + exp(-x));
}
double sigmoid_derivative(double x) {
return x * (1 - x);
}
double calculateNeuronOutput(struct Neuron *neuron, double inputs[], int use_relu) {
double sum = neuron->bias;
for (int i = 0; i < INPUT_SIZE; i++) {
sum += inputs[i] * neuron->weights[i];
}
if (use_relu){
return relu(sum);
}
else {
return sigmoid(sum);
}
}
void backPropagation(struct Neuron inputLayer[], struct Neuron hiddenLayer[],
struct Neuron outputLayer[], double inputVector[], double target) {
double hiddenLayerOutput[HIDDEN_SIZE];
for (int i = 0; i < HIDDEN_SIZE; i++) {
hiddenLayerOutput[i] = calculateNeuronOutput(&hiddenLayer[i], inputVector, 1);
}
double output = calculateNeuronOutput(&outputLayer[0], hiddenLayerOutput, 0);
double error = 0.5 * pow(target - output, 2);
double output_error = target - output;
double output_delta = output_error * sigmoid_derivative(output);
double hiddenLayer_error[HIDDEN_SIZE];
for (int i = 0; i < HIDDEN_SIZE; i++) {
hiddenLayer_error[i] = output_delta * outputLayer[0].weights[i];
}
for (int i = 0; i < HIDDEN_SIZE; i++) {
for (int j = 0; j < INPUT_SIZE; j++) {
hiddenLayer[i].weights[j] += LEARNING_RATE * hiddenLayer_error[i] * inputVector[j];
}
hiddenLayer[i].bias += LEARNING_RATE * hiddenLayer_error[i];
}
for (int i = 0; i < OUTPUT_SIZE; i++) {
for (int j = 0; j < HIDDEN_SIZE; j++) {
outputLayer[i].weights[j] += LEARNING_RATE * output_delta * hiddenLayerOutput[j];
}
outputLayer[i].bias += LEARNING_RATE * output_delta;
}
}
int main() {
struct Neuron inputLayer[INPUT_SIZE] = {
{{0.1, -0.2, 0.3}, 0.1},
{{0.2, -0.1, -0.3}, 0.2},
{{0.3, 0.4, -0.1}, 0.2},
};
struct Neuron hiddenLayer[HIDDEN_SIZE] = {
{{0.1, 0.2, 0.3}, 0.1},
{{0.2, 0.1, -0.3}, 0.2},
{{0.3, 0.4, 0.1}, 0.3},
{{0.2, 0.1, 0.4}, -0.4},
{{0.5, 0.2, -0.3}, -0.1},
{{0.1, 0.3, 0.2}, 0.4},
{{0.3, -0.4, 0.1}, 0.2},
{{0.4, 0.2, -0.1}, -0.3}
};
struct Neuron outputLayer[OUTPUT_SIZE] = {
{{0.1, -0.2, 0.3}, 0.2}
};
double inputVector[4][INPUT_SIZE] = { { 0.0, 0.0, 1.0 },{0.0, 1.0, 0.0},{0.0, 1.0, 1.0},{1.0, 1.0, 1.0 } };
double targetOutput[4] = { {0.0},{1.0},{1.0},{0.0} };
for (int epoch = 0; epoch < EPOCHS; epoch++) {
for(int i=0; i< 4; i++){
backPropagation(inputLayer, hiddenLayer, outputLayer, inputVector[i], targetOutput[i]);
}
if (epoch % 1000 == 0) {
double totalError = 0.0;
for (int i = 0; i < 4; i++) {
double hiddenLayerOutput[HIDDEN_SIZE];
for (int j = 0; j < HIDDEN_SIZE; j++) {
hiddenLayerOutput[j] = calculateNeuronOutput(&hiddenLayer[j], inputVector[i], 1);
}
double output = calculateNeuronOutput(&outputLayer[0], hiddenLayerOutput, 0);
double error = 0.5 * pow(targetOutput[i] - output, 2);
totalError += error;
}
printf("Epoch: %d, Loss: %f\n", epoch, totalError);
}
}
// Tahmin
double predictionInput[4][INPUT_SIZE] = { { 0.0, 0.0, 1.0 },{0.0, 0.0, 1.0},{0.0, 1.0, 1.0},{0.0, 1.0, 1.0 } };
for (int i = 0; i < 4; ++i) {
double hiddenLayerOutput[HIDDEN_SIZE];
for (int j = 0; j < HIDDEN_SIZE; ++j) {
hiddenLayerOutput[j] = calculateNeuronOutput(&hiddenLayer[j], predictionInput[i], 1);
}
double finalOutput = calculateNeuronOutput(&outputLayer[0],hiddenLayerOutput, 0);
printf("Input: (%f, %f, %f), Exact Output: %f, Predicton: %f\n",
predictionInput[i][0], predictionInput[i][1], predictionInput[i][2], targetOutput[i], finalOutput);
}
return 0;
}
I can get a output which is below but in the last line I got this error.
{Epoch: 0, Loss: 0.526654
Epoch: 1000, Loss: 0.003173
Epoch: 2000, Loss: 0.001147
Epoch: 3000, Loss: 0.000665
Epoch: 4000, Loss: 0.000458
Epoch: 5000, Loss: 0.000346
Epoch: 6000, Loss: 0.000275
Epoch: 7000, Loss: 0.000228
Epoch: 8000, Loss: 0.000194
Epoch: 9000, Loss: 0.000168
Epoch: 10000, Loss: 0.000148
Epoch: 11000, Loss: 0.000132
Epoch: 12000, Loss: 0.000119
Epoch: 13000, Loss: 0.000108
Epoch: 14000, Loss: 0.000099
Epoch: 15000, Loss: 0.000091
Epoch: 16000, Loss: 0.000085
Epoch: 17000, Loss: 0.000079
Epoch: 18000, Loss: 0.000074
Epoch: 19000, Loss: 0.000069
Input: (0.000000, 0.000000, 1.000000), Act Output: 0.000000, Prediction: 0.006382
Input: (0.000000, 1.000000, 0.000000), Act Output: 1.000000, Prediction: 0.999901
Input: (0.000000, 1.000000, 1.000000), Act Output: 1.000000, Prediction: 0.992201
Input: (1.000000, 1.000000, 1.000000), Act Output: 0.000000, Prediction: 0.005400 }
And this is the error: {Run-Time Check Failure #2 - Stack around the variable 'outputLayer' was corrupted.}
At least this, in backPropagation()
:
double hiddenLayer_error[HIDDEN_SIZE];
for (int i = 0; i < HIDDEN_SIZE; i++) {
hiddenLayer_error[i] = output_delta * outputLayer[0].weights[i];
}
outputLayer[0].weights[]
is an array of size 3.
Your loop indexes that array from 0 to 7, which will cause undefined behaviour.
You have the same problem in this code:
for (int i = 0; i < OUTPUT_SIZE; i++) {
for (int j = 0; j < HIDDEN_SIZE; j++) {
outputLayer[i].weights[j] += LEARNING_RATE * output_delta * hiddenLayerOutput[j];
}
outputLayer[i].bias += LEARNING_RATE * output_delta;
}