Exemplo n.º 1
0
        /// <summary>
        /// This function tests to make sure that the sum of the stochastic calculated gradients is equal to the
        /// full gradient.
        /// </summary>
        /// <remarks>
        /// This function tests to make sure that the sum of the stochastic calculated gradients is equal to the
        /// full gradient.  This requires using ordered sampling, so if the ObjectiveFunction itself randomizes
        /// the inputs this function will likely fail.
        /// </remarks>
        /// <param name="x">is the point to evaluate the function at</param>
        /// <param name="functionTolerance">is the tolerance to place on the infinity norm of the gradient and value</param>
        /// <returns>boolean indicating success or failure.</returns>
        public virtual bool TestDerivatives(double[] x, double functionTolerance)
        {
            bool ret         = false;
            bool compareHess = true;

            log.Info("Making sure that the stochastic derivatives are ok.");
            AbstractStochasticCachingDiffFunction.SamplingMethod tmpSampleMethod = thisFunc.sampleMethod;
            StochasticCalculateMethods tmpMethod = thisFunc.method;

            //Make sure that our function is using ordered sampling.  Otherwise we have no gaurentees.
            thisFunc.sampleMethod = AbstractStochasticCachingDiffFunction.SamplingMethod.Ordered;
            if (thisFunc.method == StochasticCalculateMethods.NoneSpecified)
            {
                log.Info("No calculate method has been specified");
            }
            else
            {
                if (!thisFunc.method.CalculatesHessianVectorProduct())
                {
                    compareHess = false;
                }
            }
            approxValue = 0;
            approxGrad  = new double[x.Length];
            curGrad     = new double[x.Length];
            Hv          = new double[x.Length];
            double percent = 0.0;

            //This loop runs through all the batches and sums of the calculations to compare against the full gradient
            for (int i = 0; i < numBatches; i++)
            {
                percent = 100 * ((double)i) / (numBatches);
                //Can't figure out how to get a carriage return???  ohh well
                System.Console.Error.Printf("%5.1f percent complete\n", percent);
                //  update the "hopefully" correct Hessian
                thisFunc.method = tmpMethod;
                System.Array.Copy(thisFunc.HdotVAt(x, v, testBatchSize), 0, Hv, 0, Hv.Length);
                //  Now get the hessian through finite difference
                thisFunc.method = StochasticCalculateMethods.ExternalFiniteDifference;
                System.Array.Copy(thisFunc.DerivativeAt(x, v, testBatchSize), 0, gradFD, 0, gradFD.Length);
                thisFunc.recalculatePrevBatch = true;
                System.Array.Copy(thisFunc.HdotVAt(x, v, gradFD, testBatchSize), 0, HvFD, 0, HvFD.Length);
                //Compare the difference
                double DiffHv = ArrayMath.Norm_inf(ArrayMath.PairwiseSubtract(Hv, HvFD));
                //Keep track of the biggest H.v error
                if (DiffHv > maxHvDiff)
                {
                    maxHvDiff = DiffHv;
                }
            }
            if (maxHvDiff < functionTolerance)
            {
                Sayln(string.Empty);
                Sayln("Success: Hessian approximations lined up");
                ret = true;
            }
            else
            {
                Sayln(string.Empty);
                Sayln("Failure: Hessian approximation at somepoint was off by " + maxHvDiff);
                ret = false;
            }
            thisFunc.sampleMethod = tmpSampleMethod;
            thisFunc.method       = tmpMethod;
            return(ret);
        }
Exemplo n.º 2
0
        /// <summary>
        /// This function tests to make sure that the sum of the stochastic calculated gradients is equal to the
        /// full gradient.
        /// </summary>
        /// <remarks>
        /// This function tests to make sure that the sum of the stochastic calculated gradients is equal to the
        /// full gradient.  This requires using ordered sampling, so if the ObjectiveFunction itself randomizes
        /// the inputs this function will likely fail.
        /// </remarks>
        /// <param name="x">is the point to evaluate the function at</param>
        /// <param name="functionTolerance">is the tolerance to place on the infinity norm of the gradient and value</param>
        /// <returns>boolean indicating success or failure.</returns>
        public virtual bool TestSumOfBatches(double[] x, double functionTolerance)
        {
            bool ret = false;

            log.Info("Making sure that the sum of stochastic gradients equals the full gradient");
            AbstractStochasticCachingDiffFunction.SamplingMethod tmpSampleMethod = thisFunc.sampleMethod;
            StochasticCalculateMethods tmpMethod = thisFunc.method;

            //Make sure that our function is using ordered sampling.  Otherwise we have no gaurentees.
            thisFunc.sampleMethod = AbstractStochasticCachingDiffFunction.SamplingMethod.Ordered;
            if (thisFunc.method == StochasticCalculateMethods.NoneSpecified)
            {
                log.Info("No calculate method has been specified");
            }
            approxValue = 0;
            approxGrad  = new double[x.Length];
            curGrad     = new double[x.Length];
            fullGrad    = new double[x.Length];
            double percent = 0.0;

            //This loop runs through all the batches and sums of the calculations to compare against the full gradient
            for (int i = 0; i < numBatches; i++)
            {
                percent = 100 * ((double)i) / (numBatches);
                //  update the value
                approxValue += thisFunc.ValueAt(x, v, testBatchSize);
                //  update the gradient
                thisFunc.returnPreviousValues = true;
                System.Array.Copy(thisFunc.DerivativeAt(x, v, testBatchSize), 0, curGrad, 0, curGrad.Length);
                //Update Approximate
                approxGrad = ArrayMath.PairwiseAdd(approxGrad, curGrad);
                double norm = ArrayMath.Norm(approxGrad);
                System.Console.Error.Printf("%5.1f percent complete  %6.2f \n", percent, norm);
            }
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // Get the full gradient and value, these should equal the approximates
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            log.Info("About to calculate the full derivative and value");
            System.Array.Copy(thisFunc.DerivativeAt(x), 0, fullGrad, 0, fullGrad.Length);
            thisFunc.returnPreviousValues = true;
            fullValue = thisFunc.ValueAt(x);
            diff      = new double[x.Length];
            if ((ArrayMath.Norm_inf(diff = ArrayMath.PairwiseSubtract(fullGrad, approxGrad))) < functionTolerance)
            {
                Sayln(string.Empty);
                Sayln("Success: sum of batch gradients equals full gradient");
                ret = true;
            }
            else
            {
                diffNorm = ArrayMath.Norm(diff);
                Sayln(string.Empty);
                Sayln("Failure: sum of batch gradients minus full gradient has norm " + diffNorm);
                ret = false;
            }
            if (System.Math.Abs(approxValue - fullValue) < functionTolerance)
            {
                Sayln(string.Empty);
                Sayln("Success: sum of batch values equals full value");
                ret = true;
            }
            else
            {
                Sayln(string.Empty);
                Sayln("Failure: sum of batch values minus full value has norm " + System.Math.Abs(approxValue - fullValue));
                ret = false;
            }
            thisFunc.sampleMethod = tmpSampleMethod;
            thisFunc.method       = tmpMethod;
            return(ret);
        }