Implemented a stopping criterion.
git-svn-id: file:///home/svnrepos/software/liblbfgs/trunk@21 ecf4c44f-38d1-4fa4-9757-a0b4dd0349fc
This commit is contained in:
parent
a8edbfe8b9
commit
7eb418b805
@ -74,6 +74,8 @@ typedef double lbfgsfloatval_t;
|
|||||||
enum {
|
enum {
|
||||||
/** L-BFGS reaches convergence. */
|
/** L-BFGS reaches convergence. */
|
||||||
LBFGS_SUCCESS = 0,
|
LBFGS_SUCCESS = 0,
|
||||||
|
LBFGS_CONVERGENCE = 0,
|
||||||
|
LBFGS_STOP,
|
||||||
/** The initial variables already minimize the objective function. */
|
/** The initial variables already minimize the objective function. */
|
||||||
LBFGS_ALREADY_MINIMIZED,
|
LBFGS_ALREADY_MINIMIZED,
|
||||||
|
|
||||||
@ -91,6 +93,12 @@ enum {
|
|||||||
LBFGSERR_INVALID_N_SSE,
|
LBFGSERR_INVALID_N_SSE,
|
||||||
/** The array x must be aligned to 16 (for SSE). */
|
/** The array x must be aligned to 16 (for SSE). */
|
||||||
LBFGSERR_INVALID_X_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. */
|
/** Invalid parameter lbfgs_parameter_t::linesearch specified. */
|
||||||
LBFGSERR_INVALID_LINESEARCH,
|
LBFGSERR_INVALID_LINESEARCH,
|
||||||
/** Invalid parameter lbfgs_parameter_t::max_step specified. */
|
/** Invalid parameter lbfgs_parameter_t::max_step specified. */
|
||||||
@ -172,6 +180,9 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
lbfgsfloatval_t epsilon;
|
lbfgsfloatval_t epsilon;
|
||||||
|
|
||||||
|
int past;
|
||||||
|
lbfgsfloatval_t delta;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of iterations.
|
* The maximum number of iterations.
|
||||||
* The lbfgs() function terminates an optimization process with
|
* The lbfgs() function terminates an optimization process with
|
||||||
|
53
lib/lbfgs.c
53
lib/lbfgs.c
@ -111,7 +111,8 @@ struct tag_iteration_data {
|
|||||||
typedef struct tag_iteration_data iteration_data_t;
|
typedef struct tag_iteration_data iteration_data_t;
|
||||||
|
|
||||||
static const lbfgs_parameter_t _defparam = {
|
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,
|
1e-20, 1e20, 1e-4, 0.9, 1.0e-16,
|
||||||
0.0, 0,
|
0.0, 0,
|
||||||
};
|
};
|
||||||
@ -255,11 +256,12 @@ int lbfgs(
|
|||||||
const lbfgs_parameter_t* param = (_param != NULL) ? _param : &_defparam;
|
const lbfgs_parameter_t* param = (_param != NULL) ? _param : &_defparam;
|
||||||
const int m = param->m;
|
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;
|
iteration_data_t *lm = NULL, *it = NULL;
|
||||||
lbfgsfloatval_t ys, yy;
|
lbfgsfloatval_t ys, yy;
|
||||||
lbfgsfloatval_t xnorm, gnorm, beta;
|
lbfgsfloatval_t xnorm, gnorm, beta;
|
||||||
lbfgsfloatval_t fx = 0.;
|
lbfgsfloatval_t fx = 0.;
|
||||||
|
lbfgsfloatval_t rate = 0.;
|
||||||
line_search_proc linesearch = line_search_morethuente;
|
line_search_proc linesearch = line_search_morethuente;
|
||||||
|
|
||||||
/* Construct a callback data. */
|
/* Construct a callback data. */
|
||||||
@ -286,6 +288,15 @@ int lbfgs(
|
|||||||
return LBFGSERR_INVALID_X_SSE;
|
return LBFGSERR_INVALID_X_SSE;
|
||||||
}
|
}
|
||||||
#endif/*defined(USE_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.) {
|
if (param->min_step < 0.) {
|
||||||
return LBFGSERR_INVALID_MINSTEP;
|
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. */
|
/* Evaluate the function value and its gradient. */
|
||||||
fx = cd.proc_evaluate(cd.instance, x, g, cd.n, 0);
|
fx = cd.proc_evaluate(cd.instance, x, g, cd.n, 0);
|
||||||
if (0. != param->orthantwise_c) {
|
if (0. != param->orthantwise_c) {
|
||||||
@ -360,6 +376,11 @@ int lbfgs(
|
|||||||
fx += xnorm * param->orthantwise_c;
|
fx += xnorm * param->orthantwise_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the initial value of the objective function. */
|
||||||
|
if (pf != NULL) {
|
||||||
|
pf[0] = fx;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compute the direction;
|
Compute the direction;
|
||||||
we assume the initial hessian matrix H_0 as the identity matrix.
|
we assume the initial hessian matrix H_0 as the identity matrix.
|
||||||
@ -431,6 +452,28 @@ int lbfgs(
|
|||||||
break;
|
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) {
|
if (param->max_iterations != 0 && param->max_iterations < k+1) {
|
||||||
/* Maximum number of iterations. */
|
/* Maximum number of iterations. */
|
||||||
ret = LBFGSERR_MAXIMUMITERATION;
|
ret = LBFGSERR_MAXIMUMITERATION;
|
||||||
@ -524,6 +567,8 @@ lbfgs_exit:
|
|||||||
*ptr_fx = fx;
|
*ptr_fx = fx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vecfree(pf);
|
||||||
|
|
||||||
/* Free memory blocks used by this function. */
|
/* Free memory blocks used by this function. */
|
||||||
if (lm != NULL) {
|
if (lm != NULL) {
|
||||||
for (i = 0;i < m;++i) {
|
for (i = 0;i < m;++i) {
|
||||||
@ -555,7 +600,7 @@ static int line_search_backtracking(
|
|||||||
const lbfgs_parameter_t *param
|
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 width = 0.5, norm = 0.;
|
||||||
lbfgsfloatval_t finit, dginit = 0., dgtest;
|
lbfgsfloatval_t finit, dginit = 0., dgtest;
|
||||||
|
|
||||||
@ -639,7 +684,7 @@ static int line_search_morethuente(
|
|||||||
const lbfgs_parameter_t *param
|
const lbfgs_parameter_t *param
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i, count = 0;
|
int count = 0;
|
||||||
int brackt, stage1, uinfo = 0;
|
int brackt, stage1, uinfo = 0;
|
||||||
lbfgsfloatval_t dg, norm;
|
lbfgsfloatval_t dg, norm;
|
||||||
lbfgsfloatval_t stx, fx, dgx;
|
lbfgsfloatval_t stx, fx, dgx;
|
||||||
|
Loading…
Reference in New Issue
Block a user