所以,我尝试创建自己的神经网络。真的很简单。
我的输入是手写数字的MNIST数据库。 输入:28 * 28个神经元(图像)。 输出:10个神经元(0/1/2/3/4/5/6/7/8/9)。 所以我的网络如下:28 * 28 - > 15 - > 10。
问题仍然存在于我估计的输出中。实际上,我似乎有一个梯度爆炸。
我的网络提供的输出在这里:https://pastebin.com/EFpBGAZd
如您所见,第一次估算的输出是错误的。所以我的网络由于反向传播而调整了权重。但它似乎没有正确更新权重。实际上,与第二高值相比,估计的输出太高。 因此,第一次估算的输出仍然是以下培训的最佳估计输出(在我的示例中为13)。
我的反向传播代码:
VOID BP(NETWORK &Network, double Target[OUTPUT_NEURONS]) {
double DeltaETotalOut = 0;
double DeltaOutNet = 0;
double DeltaErrorNet = 0;
double DeltaETotalWeight = 0;
double Error = 0;
double ErrorTotal = 0;
double OutputUpdatedWeights[OUTPUT_NEURONS*HIDDEN_NEURONS] = { 0 };
unsigned int _indexOutput = 0;
double fNetworkError = 0;
//Calculate Error
for (int i = 0; i < OUTPUT_NEURONS; i++) {
fNetworkError += 0.5*pow(Target[i] - Network.OLayer.Cell[i].Output, 2);
}
Network.Error = fNetworkError;
//Output Neurons
for (int i = 0; i < OUTPUT_NEURONS; i++) {
DeltaETotalOut = -(Target[i] - Network.OLayer.Cell[i].Output);
DeltaOutNet = ActivateSigmoidPrime(Network.OLayer.Cell[i].Output);
for (int j = 0; j < HIDDEN_NEURONS; j++) {
OutputUpdatedWeights[_indexOutput] = Network.OLayer.Cell[i].Weight[j] - 0.5 * DeltaOutNet*DeltaETotalOut* Network.HLayer.Cell[j].Output;
_indexOutput++;
}
}
//Hidden Neurons
for (int i = 0; i < HIDDEN_NEURONS; i++) {
ErrorTotal = 0;
for (int k = 0; k < OUTPUT_NEURONS; k++) {
DeltaETotalOut = -(Target[k] - Network.OLayer.Cell[k].Output);
DeltaOutNet = ActivateSigmoidPrime(Network.OLayer.Cell[k].Output);
DeltaErrorNet = DeltaETotalOut * DeltaOutNet;
Error = DeltaErrorNet * Network.OLayer.Cell[k].Weight[i];
ErrorTotal += Error;
}
DeltaOutNet = ActivateSigmoidPrime(Network.HLayer.Cell[i].Output);
for (int j = 0; j < INPUT_NEURONS; j++) {
DeltaETotalWeight = ErrorTotal * DeltaOutNet*Network.ILayer.Image[j];
Network.HLayer.Cell[i].Weight[j] -= 0.5 * DeltaETotalWeight;
}
}
//Update Weights
_indexOutput = 0;
for (int i = 0; i < OUTPUT_NEURONS; i++) {
for (int j = 0; j < HIDDEN_NEURONS; j++) {
Network.OLayer.Cell[i].Weight[j] = OutputUpdatedWeights[_indexOutput];
_indexOutput++;
}
}}
我该如何解决这个问题? 我没有在隐藏层上工作也没有偏见,是不是因为它? 感谢
答案 0 :(得分:0)
好吧,因为Backpropagation很难实现,尤其是调试(我想每个人都可以联系),调试其他人编写的代码要困难得多。
快速查看代码后,我很惊讶您计算了负delta项?您使用的是ReLU还是任何S形函数?我很确定还有更多。但我建议你远离MNIST,直到你的网络解决XOR。
我在伪代码中写了一个关于如何在伪代码中实现Backpropagation的摘要。我相信你很容易将它翻译成C ++。
答案 1 :(得分:0)
根据我的经验,神经网络应该真正用矩阵运算来实现。这将使您的代码更快,更容易调试。
调试反向传播的方法是使用有限差分。对于损失函数J(theta)
,我们可以使用(J(theta + epsilon*d) - J(theta))/epsilon
近似每个维度的梯度,d
表示一维的单热矢量(注意与导数的相似性)。