我用C语言写的一个神经网络,有一个神经元模型 struct 和输入层,隐层和输出层 struct .这段代码实际上是用Python语言编写的,但我将其转换为C语言.在调试或运行后,出现了类似"Run-Time Check Failure #2 - Stack around the variable 'outputLayer' was corrupted."的错误,预测输出是正确的,但最终出现了错误.下面是代码.

#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;

}

我可以得到下面的输出,但在最后一行我得到了这个错误.

{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 }

这就是错误:{Run-Time Check Failure #2 - Stack around the variable 'outputLayer' was corrupted.}

推荐答案

至少是这样,在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[]是大小为3的array.

您的循环索引从0到7的数组,这将导致未定义的行为.

您在下面的代码中遇到了相同的问题:

    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;
    }

C++相关问答推荐

错误:C中需要参数声明符

POSIX文件描述符位置

如果实际的syscall是CLONE(),那么为什么strace接受fork()呢?

如何正确地索引C中的 struct 指针数组?

C:scanf(%d&q;,...)输入只有一个减号

__VA_OPT__(,)是否可以检测后面没有任何内容的尾随逗号?

难以理解Makefile隐含规则

如何将字符**传递给需要常量字符指针的常量数组的函数

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

对重叠字符串使用MemMove

在C中包装两个数组?

无法访问共享目标文件内的共享指针

试图创建一个基本的Word克隆,但遇到了障碍

C语言中神秘的(我认为)缓冲区溢出

将复合文字数组用作临时字符串缓冲区是否合理?

函数指针作为函数参数 - 应该使用 const 吗?

为什么 Linux 共享库 .so 在内存中可能比在磁盘上大?

C Makefile - 如何避免重复提及文件名

C99 的 %zu 格式说明符不起作用

将帧从相机 (/dev/video0) 复制到帧缓冲区 (/dev/fb0) 会产生意外结果