protected internal override void TakeStep(AbstractStochasticCachingDiffFunction dfunction) { dfunction.returnPreviousValues = true; System.Array.Copy(dfunction.HdotVAt(x, v, grad, bSize), 0, Hv, 0, Hv.Length); //Update the weights for (int i = 0; i < x.Length; i++) { meta = 1 - mu * grad[i] * v[i]; if (0.5 > meta) { gains[i] = gains[i] * 0.5; } else { gains[i] = gains[i] * meta; } //Update gain history v[i] = lam * (1 + cPosDef * gains[i]) * v[i] - gains[i] * (grad[i] + lam * Hv[i]); //Get the next X newX[i] = x[i] - gains[i] * grad[i]; } if (printMinMax) { Say("vMin = " + ArrayMath.Min(v) + " "); Say("vMax = " + ArrayMath.Max(v) + " "); Say("gainMin = " + ArrayMath.Min(gains) + " "); Say("gainMax = " + ArrayMath.Max(gains) + " "); } }
/// <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); }