public abstract class LevenbergMarquardt extends Object implements Serializable, Cloneable, Optimizer
The solver minimizes \( || f ||_{L_{2}} \) for a function \( f:\mathbb{R}^n \rightarrow \mathbb{R}^m \).
The solver requires the calculation of a Jacobi-matrix \( J = \frac{\mathrm{d}f}{\mathrm{d}x} \). The iteration steps
are then defined by
\[
\Delta x = H_{\lambda}^{-1} J^T f
\]
where \( H_{\lambda} \) is a regularized approximation of the Hessian matrix.
The solver supports two different regularizations. For RegularizationMethod.LEVENBERG the solver uses
\( H_{\lambda} = J^T J + \lambda I \). For RegularizationMethod.LEVENBERG_MARQUARDT the solver uses
\( H_{\lambda} = J^T J + \lambda \text{diag}(J^T J) \).
The design avoids the need to define the objective function as a separate class. The objective function is defined by overriding a class method, see the sample code below.
The Levenberg-Marquardt solver is implemented in using multi-threading.
The calculation of the derivatives (in case a specific implementation of
setDerivatives(double[] parameters, double[][] derivatives) is not
provided) may be performed in parallel by setting the parameter numberOfThreads.
To use the solver inherit from it and implement the objective function as
setValues(double[] parameters, double[] values) where values has
to be set to the value of the objective functions for the given parameters.
You may also provide an a derivative for your objective function by
additionally overriding the function setDerivatives(double[] parameters, double[][] derivatives),
otherwise the solver will calculate the derivative via finite differences.
To reject a point, it is allowed to set an element of values to Double.NaN
in the implementation of setValues(double[] parameters, double[] values).
Put differently: The solver handles NaN values in values as an error larger than
the current one (regardless of the current error) and rejects the point.
Note, however, that is is an error if the initial parameter guess results in an NaN value.
That is, the solver should be initialized with an initial parameter in an admissible region.
| 0.0 * x1 + 1.0 * x2 = 5.0 |
| 2.0 * x1 + 1.0 * x2 = 10.0 |
LevenbergMarquardt optimizer = new LevenbergMarquardt() {
// Override your objective function here
public void setValues(double[] parameters, double[] values) {
values[0] = parameters[0] * 0.0 + parameters[1];
values[1] = parameters[0] * 2.0 + parameters[1];
}
};
// Set solver parameters
optimizer.setInitialParameters(new double[] { 0, 0 });
optimizer.setWeights(new double[] { 1, 1 });
optimizer.setMaxIteration(100);
optimizer.setTargetValues(new double[] { 5, 10 });
optimizer.run();
double[] bestParameters = optimizer.getBestFitParameters();
See the example in the main method below.
The class can be initialized to use a multi-threaded valuation. If initialized
this way the implementation of setValues must be thread-safe.
The solver will evaluate the gradient of the value vector in parallel, i.e.,
use as many threads as the number of parameters.
| Modifier and Type | Class and Description |
|---|---|
static class |
LevenbergMarquardt.RegularizationMethod
The regularization method used to invert the approximation of the
Hessian matrix.
|
Optimizer.ObjectiveFunction| Constructor and Description |
|---|
LevenbergMarquardt()
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(double[] initialParameters,
double[] targetValues,
int maxIteration,
ExecutorService executorService)
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(double[] initialParameters,
double[] targetValues,
int maxIteration,
int numberOfThreads)
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(int numberOfThreads)
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(LevenbergMarquardt.RegularizationMethod regularizationMethod,
double[] initialParameters,
double[] targetValues,
int maxIteration,
ExecutorService executorService)
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(LevenbergMarquardt.RegularizationMethod regularizationMethod,
double[] initialParameters,
double[] targetValues,
int maxIteration,
int numberOfThreads)
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(List<Number> initialParameters,
List<Number> targetValues,
int maxIteration,
ExecutorService executorService)
Create a Levenberg-Marquardt solver.
|
LevenbergMarquardt(List<Number> initialParameters,
List<Number> targetValues,
int maxIteration,
int numberOfThreads)
Create a Levenberg-Marquardt solver.
|
| Modifier and Type | Method and Description |
|---|---|
LevenbergMarquardt |
clone()
Create a clone of this LevenbergMarquardt optimizer.
|
double[] |
getBestFitParameters()
Get the best fit parameter vector.
|
LevenbergMarquardt |
getCloneWithModifiedTargetValues(double[] newTargetVaues,
double[] newWeights,
boolean isUseBestParametersAsInitialParameters)
Create a clone of this LevenbergMarquardt optimizer with a new vector for the
target values and weights.
|
LevenbergMarquardt |
getCloneWithModifiedTargetValues(List<Number> newTargetVaues,
List<Number> newWeights,
boolean isUseBestParametersAsInitialParameters)
Create a clone of this LevenbergMarquardt optimizer with a new vector for the
target values and weights.
|
int |
getIterations()
Get the number of iterations.
|
double |
getLambda()
Get the parameter λ used in the Tikhonov-like regularization of the Hessian matrix,
that is the \( \lambda \) in \( H + \lambda \diag H \).
|
double |
getLambdaDivisor()
Get the divisor applied to lambda (for the next iteration) if the inversion of regularized
Hessian succeeds, that is, if \( H + \lambda \diag H \) is invertable.
|
double |
getLambdaMultiplicator()
Get the multiplicator applied to lambda if the inversion of regularized
Hessian fails, that is, if \( H + \lambda \diag H \) is not invertable.
|
double |
getMeanSquaredError(double[] value) |
double |
getRootMeanSquaredError() |
static void |
main(String[] args) |
void |
run()
Runs the optimization.
|
void |
setDerivatives(double[] parameters,
double[][] derivatives)
The derivative of the objective function.
|
LevenbergMarquardt |
setErrorTolerance(double errorTolerance)
Set the error tolerance.
|
LevenbergMarquardt |
setInitialParameters(double[] initialParameters)
Set the initial parameters for the solver.
|
void |
setLambda(double lambda)
Set the parameter λ used in the Tikhonov-like regularization of the Hessian matrix,
that is the \( \lambda \) in \( H + \lambda \diag H \).
|
void |
setLambdaDivisor(double lambdaDivisor)
Set the divisor applied to lambda (for the next iteration) if the inversion of regularized
Hessian succeeds, that is, if \( H + \lambda \diag H \) is invertable.
|
void |
setLambdaMultiplicator(double lambdaMultiplicator)
Set the multiplicator applied to lambda if the inversion of regularized
Hessian fails, that is, if \( H + \lambda \diag H \) is not invertable.
|
LevenbergMarquardt |
setMaxIteration(int maxIteration)
Set the maximum number of iterations to be performed until the solver
gives up.
|
LevenbergMarquardt |
setParameterSteps(double[] parameterSteps)
Set the parameter step for the solver.
|
LevenbergMarquardt |
setTargetValues(double[] targetValues)
Set the target values for the solver.
|
abstract void |
setValues(double[] parameters,
double[] values)
The objective function.
|
LevenbergMarquardt |
setWeights(double[] weights)
Set the weight for the objective function.
|
public LevenbergMarquardt(LevenbergMarquardt.RegularizationMethod regularizationMethod, double[] initialParameters, double[] targetValues, int maxIteration, ExecutorService executorService)
regularizationMethod - The regularization method to use. See LevenbergMarquardt.RegularizationMethod.initialParameters - Initial value for the parameters where the solver starts its search.targetValues - Target values to achieve.maxIteration - Maximum number of iterations.executorService - Executor to be used for concurrent valuation of the derivatives. This is only performed if setDerivative is not overwritten. Warning: The implementation of setValues has to be thread safe!public LevenbergMarquardt(double[] initialParameters,
double[] targetValues,
int maxIteration,
ExecutorService executorService)
initialParameters - Initial value for the parameters where the solver starts its search.targetValues - Target values to achieve.maxIteration - Maximum number of iterations.executorService - Executor to be used for concurrent valuation of the derivatives. This is only performed if setDerivative is not overwritten. Warning: The implementation of setValues has to be thread safe!public LevenbergMarquardt(LevenbergMarquardt.RegularizationMethod regularizationMethod, double[] initialParameters, double[] targetValues, int maxIteration, int numberOfThreads)
regularizationMethod - The regularization method to use. See LevenbergMarquardt.RegularizationMethod.initialParameters - Initial value for the parameters where the solver starts its search.targetValues - Target values to achieve.maxIteration - Maximum number of iterations.numberOfThreads - Maximum number of threads. Warning: If this number is larger than one, the implementation of setValues has to be thread safe!public LevenbergMarquardt(double[] initialParameters,
double[] targetValues,
int maxIteration,
int numberOfThreads)
initialParameters - Initial value for the parameters where the solver starts its search.targetValues - Target values to achieve.maxIteration - Maximum number of iterations.numberOfThreads - Maximum number of threads. Warning: If this number is larger than one, the implementation of setValues has to be thread safe!public LevenbergMarquardt(List<Number> initialParameters, List<Number> targetValues, int maxIteration, ExecutorService executorService)
initialParameters - List of initial values for the parameters where the solver starts its search.targetValues - List of target values to achieve.maxIteration - Maximum number of iterations.executorService - Executor to be used for concurrent valuation of the derivatives. This is only performed if setDerivative is not overwritten. Warning: The implementation of setValues has to be thread safe!public LevenbergMarquardt(List<Number> initialParameters, List<Number> targetValues, int maxIteration, int numberOfThreads)
initialParameters - Initial value for the parameters where the solver starts its search.targetValues - Target values to achieve.maxIteration - Maximum number of iterations.numberOfThreads - Maximum number of threads. Warning: If this number is larger than one, the implementation of setValues has to be thread safe!public LevenbergMarquardt()
public LevenbergMarquardt(int numberOfThreads)
numberOfThreads - Maximum number of threads. Warning: If this number is larger than one, the implementation of setValues has to be thread safe!public static void main(String[] args) throws SolverException, CloneNotSupportedException
public LevenbergMarquardt setInitialParameters(double[] initialParameters)
initialParameters - The initial parameters.public LevenbergMarquardt setParameterSteps(double[] parameterSteps)
parameterSteps - The parameter step.public LevenbergMarquardt setTargetValues(double[] targetValues)
targetValues - The target values.public LevenbergMarquardt setMaxIteration(int maxIteration)
maxIteration - The maximum number of iterations.public LevenbergMarquardt setWeights(double[] weights)
weights - The weights for the objective function.public LevenbergMarquardt setErrorTolerance(double errorTolerance)
errorTolerance - The error tolerance.public double getLambda()
public void setLambda(double lambda)
lambda - the lambda to setpublic double getLambdaMultiplicator()
public void setLambdaMultiplicator(double lambdaMultiplicator)
lambdaMultiplicator - the lambdaMultiplicator to set. Should be > 1.public double getLambdaDivisor()
public void setLambdaDivisor(double lambdaDivisor)
lambdaDivisor - the lambdaDivisor to set. Should be > 1.public double[] getBestFitParameters()
OptimizergetBestFitParameters in interface Optimizerpublic double getRootMeanSquaredError()
getRootMeanSquaredError in interface Optimizerpublic int getIterations()
OptimizergetIterations in interface Optimizerpublic abstract void setValues(double[] parameters,
double[] values)
throws SolverException
parameters - Input value. The parameter vector.values - Output value. The vector of values f(i,parameters), i=1,...,nSolverException - Thrown if the valuation fails, specific cause may be available via the cause() method.public void setDerivatives(double[] parameters,
double[][] derivatives)
throws SolverException
parameters - Input value. The parameter vector.derivatives - Output value, where derivatives[i][j] is d(value(j)) / d(parameters(i)SolverException - Thrown if the valuation fails, specific cause may be available via the cause() method.public void run()
throws SolverException
Optimizerrun in interface OptimizerSolverException - Thrown if the valuation fails, specific cause may be available via the cause() method.public double getMeanSquaredError(double[] value)
public LevenbergMarquardt clone() throws CloneNotSupportedException
setValues(double[], double[]) and
that of setDerivatives(double[], double[][]) is reused.clone in class ObjectCloneNotSupportedExceptionpublic LevenbergMarquardt getCloneWithModifiedTargetValues(double[] newTargetVaues, double[] newWeights, boolean isUseBestParametersAsInitialParameters) throws CloneNotSupportedException
setValues(double[], double[]) and
that of setDerivatives(double[], double[][]) is reused.
The initial values of the cloned optimizer will either be the original
initial values of this object or the best parameters obtained by this
optimizer, the latter is used only if this optimized signals a done().newTargetVaues - New array of target values.newWeights - New array of weights.isUseBestParametersAsInitialParameters - If true and this optimizer is done(), then the clone will use this.getBestFitParameters() as initial parameters.CloneNotSupportedException - Thrown if this optimizer cannot be cloned.public LevenbergMarquardt getCloneWithModifiedTargetValues(List<Number> newTargetVaues, List<Number> newWeights, boolean isUseBestParametersAsInitialParameters) throws CloneNotSupportedException
setValues(double[], double[]) and
that of setDerivatives(double[], double[][]) is reused.
The initial values of the cloned optimizer will either be the original
initial values of this object or the best parameters obtained by this
optimizer, the latter is used only if this optimized signals a done().newTargetVaues - New list of target values.newWeights - New list of weights.isUseBestParametersAsInitialParameters - If true and this optimizer is done(), then the clone will use this.getBestFitParameters() as initial parameters.CloneNotSupportedException - Thrown if this optimizer cannot be cloned.Copyright © 2019. All rights reserved.