【发布时间】:2012-08-13 01:37:08
【问题描述】:
目前,我遇到了反向传播算法的问题。 我正在尝试实现它并用它来识别人脸的方向(左、右、下、直)。 基本上,我有 N 个图像,读取像素并将其值(0 到 255)更改为从 0.0 到 1.0 的值。所有图像均为 32*30。 我有一个 960 个神经元的输入层、一个 3 个神经元的隐藏层和一个 4 个神经元的输出层。例如,输出 表示该人向右看。 我遵循了伪代码。但是,它不能正常工作 - 它没有计算正确的权重,因此它无法处理训练和测试示例。 以下是部分代码:
// main function - it runs the algorithm
private void runBackpropagationAlgorithm() {
for (int i = 0; i < 900; ++i) {
for (ImageUnit iu : images) {
double [] error = calcOutputError(iu.getRatioMatrix(), iu.getClassification());
changeHiddenUnitsOutWeights(error);
error = calcHiddenError(error);
changeHiddenUnitsInWeights(error,iu.getRatioMatrix());
}
}
}
// it creates the neural network
private void createNeuroneNetwork() {
Random generator = new Random();
for (int i = 0; i < inHiddenUnitsWeights.length; ++i) {
for (int j = 0; j < hiddenUnits; ++j) {
inHiddenUnitsWeights[i][j] = generator.nextDouble();
}
}
for (int i = 0; i < hiddenUnits; ++i) {
for (int j = 0; j < 4; ++j) {
outHddenUnitsWeights[i][j] = generator.nextDouble();
}
}
}
// Calculates the error in the network. It runs through the whole network.
private double [] calcOutputError(double[][] input, double [] expectedOutput) {
int currentEdge = 0;
Arrays.fill(hiddenUnitNodeValue, 0.0);
for (int i = 0; i < input.length; ++i) {
for (int j = 0; j < input[0].length; ++j) {
for (int k = 0; k < hiddenUnits; ++k) {
hiddenUnitNodeValue[k] += input[i][j] * inHiddenUnitsWeights[currentEdge][k];
}
++currentEdge;
}
}
double[] out = new double[4];
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < hiddenUnits; ++i) {
out[j] += outHddenUnitsWeights[i][j] * hiddenUnitNodeValue[i];
}
}
double [] error = new double [4];
Arrays.fill(error, 4);
for (int i = 0; i < 4; ++i) {
error[i] = ((expectedOutput[i] - out[i])*(1.0-out[i])*out[i]);
//System.out.println((expectedOutput[i] - out[i]) + " " + expectedOutput[i] + " " + out[i]);
}
return error;
}
// Changes the weights of the outgoing edges of the hidden neurons
private void changeHiddenUnitsOutWeights(double [] error) {
for (int i = 0; i < hiddenUnits; ++i) {
for (int j = 0; j < 4; ++j) {
outHddenUnitsWeights[i][j] += learningRate*error[j]*hiddenUnitNodeValue[i];
}
}
}
// goes back to the hidden units to calculate their error.
private double [] calcHiddenError(double [] outputError) {
double [] error = new double[hiddenUnits];
for (int i = 0; i < hiddenUnits; ++i) {
double currentHiddenUnitErrorSum = 0.0;
for (int j = 0; j < 4; ++j) {
currentHiddenUnitErrorSum += outputError[j]*outHddenUnitsWeights[i][j];
}
error[i] = hiddenUnitNodeValue[i] * (1.0 - hiddenUnitNodeValue[i]) * currentHiddenUnitErrorSum;
}
return error;
}
// changes the weights of the incomming edges to the hidden neurons. input is the matrix of ratios
private void changeHiddenUnitsInWeights(double [] error, double[][] input) {
int currentEdge = 0;
for (int i = 0; i < input.length; ++i) {
for (int j = 0; j < input[0].length; ++j) {
for (int k = 0; k < hiddenUnits; ++k) {
inHiddenUnitsWeights[currentEdge][k] += learningRate*error[k]*input[i][j];
}
++currentEdge;
}
}
}
随着算法的工作,它计算越来越大的权重,最终接近无穷大(NaN 值)。我检查了代码。唉,我没有设法解决我的问题。 我会非常感谢任何愿意帮助我的人。
【问题讨论】:
-
您排除了“精度”问题吗?我的意思是,你确定这不仅仅是一个浮点问题吗?除此之外,我猜你的反向传播或隐藏的超重计算不正确。除非您在较小的样本上测试此 NN 并证明它有效。
-
我认为这不是浮点问题。我尝试了一个示例并运行了该算法 9000 次。输出仍然是一个数组 NaN 值。就在第 5 次迭代之后,值变得无限。我不明白为什么会这样。
-
它是否正确学习了 XOR 问题?调试这样的东西非常整洁。
-
我试过了,但权重仍然上升到无穷大......我明天去尝试调试它
-
你应该减去梯度以达到最小值。
标签: java machine-learning neural-network backpropagation