From 47b3e01cfb097cc12da7bd67a1b5a3f8aa8243b9 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Tue, 15 Feb 2022 15:27:22 +0800 Subject: [PATCH] tmp update --- src/lib/lbfgs.c | 26 +++++++++++++++++++++----- src/lib/lbfgs.h | 12 +++++++++++- src/sample/sample.c | 2 +- src/sample/sample2.cpp | 2 +- src/sample/sample3.cpp | 2 +- 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/lib/lbfgs.c b/src/lib/lbfgs.c index 61a8b89..2bd885d 100644 --- a/src/lib/lbfgs.c +++ b/src/lib/lbfgs.c @@ -99,6 +99,7 @@ struct tag_callback_data { void *instance; // 用户给出的运行实例 lbfgs_evaluate_t proc_evaluate; // 目标函数与模型梯度计算函数指针 lbfgs_progress_t proc_progress; // 迭代过程监控函数指针 + lbfgs_precondition_t proc_precondition; // 预优函数指针 }; typedef struct tag_callback_data callback_data_t; @@ -250,7 +251,8 @@ int lbfgs( lbfgs_evaluate_t proc_evaluate, lbfgs_progress_t proc_progress, void *instance, - lbfgs_parameter_t *_param + lbfgs_parameter_t *_param, + lbfgs_precondition_t proc_precondition ) { int ret; @@ -264,7 +266,7 @@ int lbfgs( const int m = param.m; lbfgsfloatval_t *xp = NULL; - lbfgsfloatval_t *g = NULL, *gp = NULL, *pg = NULL; + lbfgsfloatval_t *g = NULL, *gp = NULL, *pg = NULL; // gp (p for previous) pg (p for pesudo) lbfgsfloatval_t *d = NULL, *w = NULL, *pf = NULL; iteration_data_t *lm = NULL, *it = NULL; lbfgsfloatval_t ys, yy; @@ -280,6 +282,7 @@ int lbfgs( cd.instance = instance; cd.proc_evaluate = proc_evaluate; cd.proc_progress = proc_progress; + cd.proc_precondition = proc_precondition; #if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__)) /* Round out the number of variables. */ @@ -379,6 +382,7 @@ int lbfgs( ret = LBFGSERR_OUTOFMEMORY; goto lbfgs_exit; } + // 初始化计算L1模的数组 if (param.orthantwise_c != 0.) { /* Allocate working space for OW-LQN. */ @@ -455,6 +459,7 @@ int lbfgs( vec2norm(&gnorm, pg, n); } // 为啥要保证xnorm大于等于1?不明白 + // 答 参考头文件中的注释 如果模型参数的模长小于1则使用梯度的模长作为收敛性的测试指标 if (xnorm < 1.0) xnorm = 1.0; // 如果输入x即为最优化的解 则退出 if (gnorm / xnorm <= param.epsilon) { @@ -465,14 +470,14 @@ int lbfgs( /* Compute the initial step: step = 1.0 / sqrt(vecdot(d, d, n)) */ - // 计算估算的初始步长 + // 计算估算的初始步长 这一步在实际应用中重要 在相似代码编写中需参考 vec2norminv(&step, d, n); // 计算数组L2模的倒数,与注释的内容等效 k = 1; end = 0; for (;;) { /* Store the current position and gradient vectors. */ - veccpy(xp, x, n); + veccpy(xp, x, n); // p for previous veccpy(gp, g, n); /* Search for an optimal step. */ @@ -485,7 +490,8 @@ int lbfgs( param.orthantwise_c, param.orthantwise_start, param.orthantwise_end ); } - // 线性搜索错误 此时则退回到上一次迭代的位置并退出 + + // 返回值小于0则表示线性搜索错误 此时则退回到上一次迭代的位置并退出 if (ls < 0) { /* Revert to the previous point. */ veccpy(x, xp, n); @@ -560,6 +566,7 @@ int lbfgs( s_{k+1} = x_{k+1} - x_{k} = \step * d_{k}. y_{k+1} = g_{k+1} - g_{k}. */ + // 计算最新保存的s和y it = &lm[end]; vecdiff(it->s, x, xp, n); // 计算两个数组的差 it->s = x - xp vecdiff(it->y, g, gp, n); @@ -582,8 +589,12 @@ int lbfgs( Mathematics of Computation, Vol. 35, No. 151, pp. 773--782, 1980. */ + + // m小于迭代次数 bound = (m <= k) ? m : k; ++k; + + // end+1等于m则将其重置为0 循环保存 end = (end + 1) % m; /* Compute the steepest direction. */ @@ -607,6 +618,11 @@ int lbfgs( vecscale(d, ys / yy, n); // 适当缩放d的大小 + // 我们在这里提供一个预优函数的接口 返回 d = H0^-1 * d + if (cd.proc_precondition) { + cd.proc_precondition(cd.instance, x, d, n); + } + for (i = 0;i < bound;++i) { it = &lm[j]; /* \beta_{j} = \rho_{j} y^t_{j} \cdot \gamma_{i}. */ diff --git a/src/lib/lbfgs.h b/src/lib/lbfgs.h index 38d3897..18070c8 100644 --- a/src/lib/lbfgs.h +++ b/src/lib/lbfgs.h @@ -463,6 +463,15 @@ typedef int (*lbfgs_progress_t)( int ls ); + + +typedef void (*lbfgs_precondition_t)( + void *instance, + const lbfgsfloatval_t *x, + lbfgsfloatval_t *d, + const int n + ); + /* A user must implement a function compatible with ::lbfgs_evaluate_t (evaluation callback) and pass the pointer to the callback function to lbfgs() arguments. @@ -550,7 +559,8 @@ int lbfgs( lbfgs_evaluate_t proc_evaluate, lbfgs_progress_t proc_progress, void *instance, - lbfgs_parameter_t *param + lbfgs_parameter_t *param, + lbfgs_precondition_t proc_precondition ); // 将一个参数类型内的全部变量值重置为默认值 diff --git a/src/sample/sample.c b/src/sample/sample.c index 1eb0dec..830ca07 100644 --- a/src/sample/sample.c +++ b/src/sample/sample.c @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) Start the L-BFGS optimization; this will invoke the callback functions evaluate() and progress() when necessary. */ - ret = lbfgs(N, x, &fx, evaluate, progress, NULL, ¶m); + ret = lbfgs(N, x, &fx, evaluate, progress, NULL, ¶m, NULL); /* Report the result. */ printf("L-BFGS optimization terminated with status code = %d\n", ret); diff --git a/src/sample/sample2.cpp b/src/sample/sample2.cpp index 6a411ad..e0ccc6b 100644 --- a/src/sample/sample2.cpp +++ b/src/sample/sample2.cpp @@ -39,7 +39,7 @@ public: Start the L-BFGS optimization; this will invoke the callback functions evaluate() and progress() when necessary. */ - int ret = lbfgs(N, m_x, &fx, _evaluate, _progress, this, NULL); + int ret = lbfgs(N, m_x, &fx, _evaluate, _progress, this, NULL, NULL); /* Report the result. */ printf("L-BFGS optimization terminated with status code = %d\n", ret); diff --git a/src/sample/sample3.cpp b/src/sample/sample3.cpp index 8b61149..eff0506 100644 --- a/src/sample/sample3.cpp +++ b/src/sample/sample3.cpp @@ -88,7 +88,7 @@ int TEST_FUNC::Routine() //self_para.max_linesearch = 40; //self_para.linesearch = LBFGS_LINESEARCH_BACKTRACKING_WOLFE; - int ret = lbfgs(3, m_x, &fx, _Func, _Progress, this, &self_para); + int ret = lbfgs(3, m_x, &fx, _Func, _Progress, this, &self_para, NULL); clog << "L-BFGS optimization terminated with status: " << endl << lbfgs_strerror(ret) << endl; clog << m_x[0] << " " << m_x[1] << " " << m_x[2] << endl;