目前,我遇到Backpropagation算法問題。 我試圖實現它並使用它來識別面孔的方向(左,右,下,直)。 基本上,我有N個圖像,讀取像素並將其值(0到255)更改爲從0.0到1.0的值。所有圖像都是32 * 30。 我有960神經元的輸入層,3神經元的隱藏層和4神經元的輸出層。例如,輸出< 0.1,0.9,0.1,0.1>表示該人向右看。 我遵循了pseudy-code。但是,它不能正確工作 - 它不會計算正確的權重,因此無法處理培訓和測試示例。 下面是代碼的部分:神經網絡反向傳播不能正確計算權重
// 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並證明它工作正常。 – Shark 2012-08-16 16:33:58
我認爲這不是浮點問題。我嘗試了一個例子,運行9000次的算法。輸出仍然是一個數組NaN值。在第5次迭代之後,值變得無限。我無法理解爲什麼會發生這種情況。 – 2012-08-16 16:58:09
它是否正確地學習XOR問題?調試這樣的東西非常簡單。 – 2012-08-16 17:51:55