0
$\begingroup$

I have some doubt because I incurred in different papers proposing different implementations. Also implementations on opensource projects looks different. In example there is a C++ library that computes different Adam members also for Bias vector.

My Implementation:

Of course before running the optimization I do backward pass, where derivates is the derivate of the activation function computed on the weighted sum of inputs.

    public void Backward(IBackwardOutputLayer<double> iLayer, IBackwardInputLayer<double> iPlusOneLayer, double[] target)
    {
        Parallel.For(0, iLayer.Gradients.Length, i =>
        {
            double sum = 0;
            for (int j = 0; j < iPlusOneLayer.Gradients.Length; j++)
                sum += iPlusOneLayer.Gradients[j] * iPlusOneLayer.Weights[j][i];

            iLayer.Gradients[i] = sum * iLayer.Derivates[i];
        });
    }

Here's my Adam algorithm implementation that is runned after th backward pass.

    public void Optimize(IGradientsLayer<double> layer, ILayerAllocatedVariables<double> variables)
    {
        var m = variables.GetArrayVariable(Params.Momentum);
        var v = variables.GetArrayVariable(Params.Velocity);
        var mt = variables.GetArrayVariable(Params.DeBiasedMomentum);
        var vt = variables.GetArrayVariable(Params.DeBiasedVelocity);

        Parallel.For(0, layerSize , i =>
        {
            var grad = layer.Gradients[i];
            m[i] = B1 * m[i] + (1.0 - B1) * grad;
            v[i] = B2 * v[i] + (1.0 - B2) * grad * grad;

            mt[i] = m[i] / (1.0 - Pow(B1, currentStep));
            vt[i] = v[i] / (1.0 - Pow(B2, currentStep));

            layer.Gradients[i] = mt[i] / Sqrt(vt[i] + Epsilon);  
        });
    }

after each Adam step I accumulate the total gradient for the current batch

    private void AccumulateTotalGradients()
    {
        for (int l = 0; l < layers.Length; l++)
            for (int i = 0; i < layers[l].Outputs.Length; i++)
                layers[l].TotalGradients[i] += layers[l].Gradients[i];
    }

and after a small batch finally I do the propagation using the totale gradient average (mean gradient for a whole batch of inputs).

    private void Propagation()
    {
        double scaleFactor = learningRate / batchSize;

        Parallel.For(0, layers.Length, l => 
        {
            for (int i = 0; i < layers[l].Outputs.Length; i++)
            {
                layers[l].Biases[i] -= scaleFactor * layers[l].TotalGradients[i];

                for (int z = 0; z < layers[l].Weights[i].Length; z++)
                {
                    layers[l].Weights[i][z] -= scaleFactor * layers[l].Weights[i][z]* layers[l].TotalGradients[i];
                }
            }
        });
    }

Then I reset the total gradients:

    private void ResetTotalGradients()
    {
        for (int l = 0; l < layers.Length; l++) 
            for (int i = 0; i < layers[l].Outputs.Length; i++)
                layers[l].TotalGradients[i] = 0;
    }
$\endgroup$

0

You must log in to answer this question.

Browse other questions tagged .