Implemented a stopping criterion.

git-svn-id: file:///home/svnrepos/software/liblbfgs/trunk@21 ecf4c44f-38d1-4fa4-9757-a0b4dd0349fc
This commit is contained in:
naoaki 2008-07-10 13:06:47 +00:00
parent a8edbfe8b9
commit 7eb418b805
2 changed files with 60 additions and 4 deletions

View File

@ -74,6 +74,8 @@ typedef double lbfgsfloatval_t;
enum {
/** L-BFGS reaches convergence. */
LBFGS_SUCCESS = 0,
LBFGS_CONVERGENCE = 0,
LBFGS_STOP,
/** The initial variables already minimize the objective function. */
LBFGS_ALREADY_MINIMIZED,
@ -91,6 +93,12 @@ enum {
LBFGSERR_INVALID_N_SSE,
/** The array x must be aligned to 16 (for SSE). */
LBFGSERR_INVALID_X_SSE,
/** Invalid parameter lbfgs_parameter_t::epsilon specified. */
LBFGSERR_INVALID_EPSILON,
/** Invalid parameter lbfgs_parameter_t::past specified. */
LBFGSERR_INVALID_TESTPERIOD,
/** Invalid parameter lbfgs_parameter_t::delta specified. */
LBFGSERR_INVALID_DELTA,
/** Invalid parameter lbfgs_parameter_t::linesearch specified. */
LBFGSERR_INVALID_LINESEARCH,
/** Invalid parameter lbfgs_parameter_t::max_step specified. */
@ -172,6 +180,9 @@ typedef struct {
*/
lbfgsfloatval_t epsilon;
int past;
lbfgsfloatval_t delta;
/**
* The maximum number of iterations.
* The lbfgs() function terminates an optimization process with

View File

@ -111,7 +111,8 @@ struct tag_iteration_data {
typedef struct tag_iteration_data iteration_data_t;
static const lbfgs_parameter_t _defparam = {
6, 1e-5, 0, LBFGS_LINESEARCH_DEFAULT, 20,
6, 1e-5, 0, 1e-5,
0, LBFGS_LINESEARCH_DEFAULT, 20,
1e-20, 1e20, 1e-4, 0.9, 1.0e-16,
0.0, 0,
};
@ -255,11 +256,12 @@ int lbfgs(
const lbfgs_parameter_t* param = (_param != NULL) ? _param : &_defparam;
const int m = param->m;
lbfgsfloatval_t *xp = NULL, *g = NULL, *gp = NULL, *d = NULL, *w = NULL;
lbfgsfloatval_t *xp = NULL, *g = NULL, *gp = NULL, *d = NULL, *w = NULL, *pf = NULL;
iteration_data_t *lm = NULL, *it = NULL;
lbfgsfloatval_t ys, yy;
lbfgsfloatval_t xnorm, gnorm, beta;
lbfgsfloatval_t fx = 0.;
lbfgsfloatval_t rate = 0.;
line_search_proc linesearch = line_search_morethuente;
/* Construct a callback data. */
@ -286,6 +288,15 @@ int lbfgs(
return LBFGSERR_INVALID_X_SSE;
}
#endif/*defined(USE_SSE)*/
if (param->epsilon < 0.) {
return LBFGSERR_INVALID_EPSILON;
}
if (param->past < 0) {
return LBFGSERR_INVALID_TESTPERIOD;
}
if (param->delta < 0.) {
return LBFGSERR_INVALID_DELTA;
}
if (param->min_step < 0.) {
return LBFGSERR_INVALID_MINSTEP;
}
@ -352,6 +363,11 @@ int lbfgs(
}
}
/* Allocate an array for storing previous values of the objective function. */
if (0 < param->past) {
pf = (lbfgsfloatval_t*)vecalloc(param->past * sizeof(lbfgsfloatval_t));
}
/* Evaluate the function value and its gradient. */
fx = cd.proc_evaluate(cd.instance, x, g, cd.n, 0);
if (0. != param->orthantwise_c) {
@ -360,6 +376,11 @@ int lbfgs(
fx += xnorm * param->orthantwise_c;
}
/* Store the initial value of the objective function. */
if (pf != NULL) {
pf[0] = fx;
}
/*
Compute the direction;
we assume the initial hessian matrix H_0 as the identity matrix.
@ -431,6 +452,28 @@ int lbfgs(
break;
}
/*
Test for stopping criterion.
The criterion is given by the following formula:
(f(past_x) - f(x)) / f(x) < \delta
*/
if (pf != NULL) {
/* We don't test the stopping criterion while k < past. */
if (param->past <= k) {
/* Compute the relative improvement from the past. */
rate = (pf[k % param->past] - fx) / fx;
/* The stopping criterion. */
if (rate < param->delta) {
ret = LBFGS_STOP;
break;
}
}
/* Store the current value of the objective function. */
pf[k % param->past] = fx;
}
if (param->max_iterations != 0 && param->max_iterations < k+1) {
/* Maximum number of iterations. */
ret = LBFGSERR_MAXIMUMITERATION;
@ -524,6 +567,8 @@ lbfgs_exit:
*ptr_fx = fx;
}
vecfree(pf);
/* Free memory blocks used by this function. */
if (lm != NULL) {
for (i = 0;i < m;++i) {
@ -555,7 +600,7 @@ static int line_search_backtracking(
const lbfgs_parameter_t *param
)
{
int i, ret = 0, count = 0;
int ret = 0, count = 0;
lbfgsfloatval_t width = 0.5, norm = 0.;
lbfgsfloatval_t finit, dginit = 0., dgtest;
@ -639,7 +684,7 @@ static int line_search_morethuente(
const lbfgs_parameter_t *param
)
{
int i, count = 0;
int count = 0;
int brackt, stage1, uinfo = 0;
lbfgsfloatval_t dg, norm;
lbfgsfloatval_t stx, fx, dgx;