Алгоритм обратного распространения - вычисление производной от ошибки - PullRequest
1 голос
/ 27 февраля 2012

При вычислении производной от ошибки используются следующие работы, которые я использую, но не знаю точно, почему.

double errorDerivative = (-output * (1-output) *(desiredOutput - output));

Когда я удаляю минус из первого выхода, он завершается неудачей и достигает максимального предела эпохи. Я предполагаю, что так должно выглядеть, если посмотреть на этот пример http://homepages.gold.ac.uk/nikolaev/311imlti.htm, в котором не используется оператор минус.

double errorDerivative2 = (output * (1-output) *(desiredOutput - output));

В настоящее время я смотрю на модификацию существующей реализации BackPropagation, которая использует стохастический градиентный спуск, и хочу просто заставить ее использовать стандартный алгоритм обратного распространения. В настоящее время это выглядит так.

public void applyBackpropagation(double expectedOutput[]) {

        // error check, normalize value ]0;1[
        /*for (int i = 0; i < expectedOutput.length; i++) {
            double d = expectedOutput[i];
            if (d < 0 || d > 1) {
                if (d < 0)
                    expectedOutput[i] = 0 + epsilon;
                else
                    expectedOutput[i] = 1 - epsilon;
            }
        }*/

        int i = 0;
        for (Neuron n : outputLayer) {
            System.out.println("neuron");
            ArrayList<Connection> connections = n.getAllInConnections();
            for (Connection con : connections) {
                double output = n.getOutput();
                System.out.println("final output is "+output);
                double ai = con.leftNeuron.getOutput();
                System.out.println("ai output is "+ai);
                double desiredOutput = expectedOutput[i];

                double errorDerivative = (-output * (1-output) *(desiredOutput - output));
                double errorDerivative2 = (output * (1-output) *(desiredOutput - output));
                System.out.println("errorDerivative is "+errorDerivative);
                System.out.println("errorDerivative my one is "+(output * (1-output) *(desiredOutput - output)));
                double deltaWeight = -learningRate * errorDerivative2;
                double newWeight = con.getWeight() + deltaWeight;
                con.setDeltaWeight(deltaWeight);
                con.setWeight(newWeight + momentum * con.getPrevDeltaWeight());
            }
            i++;
        }

        // update weights for the hidden layer
        for (Neuron n : hiddenLayer) {
            ArrayList<Connection> connections = n.getAllInConnections();
            for (Connection con : connections) {
                double output = n.getOutput();
                double ai = con.leftNeuron.getOutput();
                double sumKoutputs = 0;
                int j = 0;
                for (Neuron out_neu : outputLayer) {
                    double wjk = out_neu.getConnection(n.id).getWeight();
                    double desiredOutput = (double) expectedOutput[j];
                    double ak = out_neu.getOutput();
                    j++;
                    sumKoutputs = sumKoutputs
                            + (-(desiredOutput - ak) * ak * (1 - ak) * wjk);
                }

                double partialDerivative = output * (1 - output) * ai * sumKoutputs;
                double deltaWeight = -learningRate * partialDerivative;
                double newWeight = con.getWeight() + deltaWeight;
                con.setDeltaWeight(deltaWeight);
                con.setWeight(newWeight + momentum * con.getPrevDeltaWeight());
            }
        }
    }

1 Ответ

2 голосов
/ 29 февраля 2012

Извините, я не буду проверять ваш код - нет времени для этого, вам придется вернуться с более конкретными вопросами, и тогда я смогу помочь вам.

Причина, по которой работает errorDerivative2, заключается, вероятно, в том, что вы используете правило обновления веса, такое как
deltaW = learningRate*errorDerivative2*input

Обычно то, что вы называете errorDerivative2, известно как delta и определяется как
-output * (1-output) *(desiredOutput - output)
для нейрона с сигмоидальной передаточной функцией

с правилом обновления веса
deltaW = -learningRate*delta*input

Так что в основном это работает для вас без знака минус на errorDerivative2, так как вы также оставили знак минус в другом месте ..

...