gpt4 book ai didi

java - 使用 SGD 微调神经网络进行数字识别时遇到问题。测试数据上我似乎无法获得超过 87% 的成绩

转载 作者:行者123 更新时间:2023-11-30 06:12:41 24 4
gpt4 key购买 nike

我可以可靠地在 10,000 张 MNIST 图像的测试数据上获得约 87% 的准确度,在训练数据上获得约 98% 的准确度。我从头开始开发神经网络,同时开发了一个 Matrix 类来配合它。目前,我使用学习率为 0.6 的小批量随机梯度下降(大小为 64 的小批量)。我正在使用固定的学习率,我听说这很糟糕,但我有点不确定如何最好地结合不断变化的学习率。这是一个输入 -> 隐藏 -> 输出分层 MLP NN。

目前,5000 次迭代足以让我获得大约 70% 的准确度(也需要大约 6 秒),但如果我想要更好的东西,我必须迭代 400k 左右。我跟踪输出的平均误差,并在 Excel 上绘制每个参数变化的图表,它总是遵循这样的模型:一开始下降得非常快,然后趋于稳定,并以更大的间隔发生变化。

我想实现动量和不断变化的学习率,但不幸的是我对反向传播的数学符号有点生疏。我已经看过 20 多个关于实现动量的答案,但他们都使用符号来描述它,如果我 100% 理解它就很好了。我明白使用过去的权重矩阵来更新当前的权重矩阵背后的想法,但是当我查看在我的特定代码中实现它的位置时,我的困惑开始发挥作用。

这是我的前向和反向传播的代码,我希望有任何关于实现动量或改变学习率的指示(或者根据我提供的信息,关于如何更好地改进我的神经网络的任何建议)。前向传播中的所有变量都是矩阵(显而易见,但我只是想清楚)

    /**
* forward propagate through the network
*/
private void forwardPropagation(Matrix inputBatch, Matrix outputBatch, boolean training) {

hiddenActivation = inputBatch.mult(inputToHiddenWeights);

hiddenActivation = hiddenActivation.sigmoidify();

outputActivation = hiddenActivation.mult(this.hiddenToOutputWeights);

outputActivation = outputActivation.sigmoidify();

if(training) {
backPropagation(inputBatch, outputBatch);

}
}

/**
* Perform backpropagation algorithm to update the weights
* and train the NN.
*/
private void backPropagation(Matrix inputBatch, Matrix outputBatch) {

// Compute gradient at output layer
outputErrorMatrix = outputBatch.sub(outputActivation);

// to keep track of the average error on every iteration (the data I plot)
this.avgErrorPerIteration[iterationToEpsilon] = outputErrorMatrix.averageValue();

// if the current error is less than a certain given error, exit and save weights
if(this.avgErrorPerIteration[iterationToEpsilon] < this.epsilon) {
this.lessThanEpsilon = true;
return;
}

// to print out the initial error value (I compare it to the end value)
if(iterationToEpsilon==0) {
System.out.println("Average error after first propagation: " + outputErrorMatrix.averageValue());
}

// compute slope at output and hidden layers
Matrix slopeOutput = outputActivation.sigmoidifyPrime();
Matrix slopeHiddenLayer = hiddenActivation.sigmoidifyPrime();

// compute delta at output layer
Matrix deltaOutput = (outputErrorMatrix.multAcross(slopeOutput)).mult(LEARNING_RATE);

// calculate error at hidden layer
Matrix hiddenError = deltaOutput.mult(hiddenToOutputWeights.transpose());

// compute delta at hidden layer
Matrix deltaHidden = hiddenError.multAcross(slopeHiddenLayer);

// update weight at both output and hidden layers
hiddenToOutputWeights = hiddenToOutputWeights.add(((hiddenActivation.transpose()).mult(deltaOutput)).mult(LEARNING_RATE));
inputToHiddenWeights = inputToHiddenWeights.add(((inputBatch.transpose()).mult(deltaHidden)).mult(LEARNING_RATE));

iterationToEpsilon++;
}

最佳答案

我不认为动量或改变学习率会帮助你获得更好的测试精度,因为这两种技术只会帮助优化算法,而你的优化算法已经做得很好了(因为它只是试图减少训练集上的误差,而且这个误差很低)。

显然你的神经网络过度拟合训练集,所以你可以尝试的一件事是 Dropout 。您可以尝试的一个更简单的方法是 Weight decay 。关键是,您需要对网络进行正则化,因为您过度拟合了,这两种是正则化技术,而其他两种通常不是。

关于java - 使用 SGD 微调神经网络进行数字识别时遇到问题。测试数据上我似乎无法获得超过 87% 的成绩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49887855/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com