private double[] computeDirection(DifferentiableFunction monitor, LineSearchResult lsr) { // implemented two-loop hessian update method. double[] direction = lsr.GradAtNext.Clone() as double[]; double[] @as = new double[m]; // first loop for (int i = updateInfo.kCounter - 1; i >= 0; i--) { @as[i] = updateInfo.getRho(i) * ArrayMath.innerProduct(updateInfo.getS(i), direction); for (int ii = 0; ii < dimension; ii++) { direction[ii] = direction[ii] - @as[i] * updateInfo.getY(i)[ii]; } } // second loop for (int i = 0; i < updateInfo.kCounter; i++) { double b = updateInfo.getRho(i) * ArrayMath.innerProduct(updateInfo.getY(i), direction); for (int ii = 0; ii < dimension; ii++) { direction[ii] = direction[ii] + (@as[i] - b) * updateInfo.getS(i)[ii]; } } for (int i = 0; i < dimension; i++) { direction[i] *= -1.0; } return(direction); }
public virtual void updateInfo(LineSearchResult lsr) { double[] s_k = new double[outerInstance.dimension]; double[] y_k = new double[outerInstance.dimension]; for (int i = 0; i < outerInstance.dimension; i++) { s_k[i] = lsr.NextPoint[i] - lsr.CurrPoint[i]; y_k[i] = lsr.GradAtNext[i] - lsr.GradAtCurr[i]; } this.updateSYRoh(s_k, y_k); kCounter = kCounter < m ? kCounter + 1 : kCounter; }
public virtual QNModel trainModel(DataIndexer indexer) { LogLikelihoodFunction objectiveFunction = generateFunction(indexer); this.dimension = objectiveFunction.DomainDimension; this.updateInfo = new QNInfo(this, this.m, this.dimension); double[] initialPoint = objectiveFunction.InitialPoint; double initialValue = objectiveFunction.valueAt(initialPoint); double[] initialGrad = objectiveFunction.gradientAt(initialPoint); LineSearchResult lsr = LineSearchResult.getInitialObject(initialValue, initialGrad, initialPoint, 0); int z = 0; while (true) { if (verbose) { Console.Write(z++); } double[] direction = null; direction = computeDirection(objectiveFunction, lsr); lsr = LineSearch.doLineSearch(objectiveFunction, direction, lsr, verbose); updateInfo.updateInfo(lsr); if (isConverged(lsr)) { break; } } return(new QNModel(objectiveFunction, lsr.NextPoint)); }
// FIXME need an improvement in convergence condition private bool isConverged(LineSearchResult lsr) { return(CONVERGE_TOLERANCE > Math.Abs(lsr.ValueAtNext - lsr.ValueAtCurr) || lsr.FctEvalCount > this.maxFctEval); }
public static LineSearchResult doLineSearch(DifferentiableFunction function, double[] direction, LineSearchResult lsr, bool verbose) { int currFctEvalCount = lsr.FctEvalCount; double stepSize = INITIAL_STEP_SIZE; double[] x = lsr.NextPoint; double valueAtX = lsr.ValueAtNext; double[] gradAtX = lsr.GradAtNext; double[] nextPoint = null; double[] gradAtNextPoint = null; double valueAtNextPoint = 0.0; double mu = 0; double upsilon = double.PositiveInfinity; long startTime = DateTimeHelperClass.CurrentUnixTimeMillis(); while (true) { nextPoint = ArrayMath.updatePoint(x, direction, stepSize); valueAtNextPoint = function.valueAt(nextPoint); currFctEvalCount++; gradAtNextPoint = function.gradientAt(nextPoint); if (!checkArmijoCond(valueAtX, valueAtNextPoint, gradAtX, direction, stepSize, true)) { upsilon = stepSize; } else if (!checkCurvature(gradAtNextPoint, gradAtX, direction, x.Length, true)) { mu = stepSize; } else { break; } if (upsilon < double.PositiveInfinity) { stepSize = (mu + upsilon) / TT; } else { stepSize *= TT; } if (stepSize < MIN_STEP_SIZE + mu) { stepSize = 0.0; break; } } long endTime = DateTimeHelperClass.CurrentUnixTimeMillis(); long duration = endTime - startTime; if (verbose) { Console.Write("\t" + valueAtX); Console.Write("\t" + (valueAtNextPoint - valueAtX)); Console.Write("\t" + (duration / 1000.0) + "\n"); } LineSearchResult result = new LineSearchResult(stepSize, valueAtX, valueAtNextPoint, gradAtX, gradAtNextPoint, x, nextPoint, currFctEvalCount); return(result); }
public static LineSearchResult doLineSearch(DifferentiableFunction function, double[] direction, LineSearchResult lsr) { return(doLineSearch(function, direction, lsr, false)); }