从零实现C#神经网络遇异常:输出恒为0或无因变化求助
问题分析与修复方案
你的神经网络代码存在几个关键问题,导致输出异常:
1. 神经元状态未重置,多次预测结果累加
Prediction方法中,后续层的神经元值是直接累加的,没有在每次预测前重置为0。第一次预测后神经元保留了计算值,第二次预测会基于旧值继续计算,导致结果每次不同。
修复代码:
public float[] Prediction(float[] inputs) { int biasIndex = 0; neurons[0] = inputs; for (int i = 1; i < layers; i++) { // 重置当前层神经元为0 Array.Clear(neurons[i], 0, neurons[i].Length); for (int j = 0; j < neurons[i].Length; j++) { for (int k = 0; k < weights[i - 1][j].Length; k++) { neurons[i][j] += neurons[i - 1][k] * weights[i - 1][j][k]; } neurons[i][j] += bias[biasIndex]; // 应用激活函数 neurons[i][j] = ActivationFunction(neurons[i][j]); biasIndex++; } } return neurons[neurons.Length - 1]; }
2. 未调用激活函数
你定义了sigmoid激活函数,但在预测过程中完全没有使用,导致输出只是输入与权重的线性组合,无法体现神经网络的非线性能力,甚至在权重偏置未初始化时输出全0。
修复:在每个神经元计算完加权和与偏置后,调用ActivationFunction,如上面代码所示。
3. Mathf依赖问题(非Unity环境)
如果不是在Unity中运行,Mathf类不存在,需要替换为System.Math,同时注意整数除法问题:1 / (1 + ...)中1是整数,会导致结果为0,要改为1f。
修复激活函数:
private float ActivationFunction(float prediction) { return 1f / (1f + (float)Math.Exp(-prediction)); }
4. 权重与偏置未初始化时输出全0
如果没有调用GiveRandomNumbers方法,权重和偏置数组默认初始化为0,此时所有神经元的计算结果都是0,输出自然全0。确保在使用网络前调用GiveRandomNumbers初始化参数:
// 使用示例 var nn = new NeuralNetwork(3, new int[] {2,3,1}); nn.GiveRandomNumbers(); // 必须调用初始化权重偏置 var output = nn.Prediction(new float[] {0.5f, 0.8f});
5. Evaluation方法逻辑错误
原方法只预测了testingDataSet[0](第一个输入),没有遍历所有测试数据,而且判断预测是否正确的阈值(0.0001)对于sigmoid输出(0-1之间)来说过于严格,实际应该根据任务调整。
修复后的Evaluation方法:
public float Evaluation(float[][] testingInputs, float[][] testingOutputs) { int correctCount = 0; int totalPredictions = 0; for (int i = 0; i < testingInputs.Length; i++) { float[] prediction = Prediction(testingInputs[i]); float[] correctOutput = testingOutputs[i]; for (int j = 0; j < prediction.Length; j++) { totalPredictions++; // 调整阈值,比如允许0.1的误差 if (Math.Abs(prediction[j] - correctOutput[j]) < 0.1f) { correctCount++; } } } return (float)correctCount / totalPredictions * 100f; }
其他潜在问题
bias数组的计算可以简化:bias的长度应该是所有隐藏层和输出层的神经元总数,即layerSize.Skip(1).Sum(),原代码的biasLength - layerSize[0]逻辑正确,但可以更直观。TrainingAlgorithm和TrainingLoop未实现,网络无法训练,当前只能用随机初始化的参数预测。
内容的提问来源于stack exchange,提问作者Olivier
相关产品推荐
相关产品推荐

