diff options
| author | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 | 
|---|---|---|
| committer | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 | 
| commit | 670a8f984fc6d8342180c59ae9e96b0b76f34d3d (patch) | |
| tree | 9f2ce7eec1a77e56b3bb1ad0ad40f212d7a996b0 /training/liblbfgs/lbfgs++.h | |
| parent | eb3ee28dc0eb1d3e5ed01ba0df843be329ae450d (diff) | |
| parent | 2f64af3e06a518b93f7ca2c30a9d0aeb2c947031 (diff) | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'training/liblbfgs/lbfgs++.h')
| -rw-r--r-- | training/liblbfgs/lbfgs++.h | 143 | 
1 files changed, 143 insertions, 0 deletions
| diff --git a/training/liblbfgs/lbfgs++.h b/training/liblbfgs/lbfgs++.h new file mode 100644 index 00000000..342f9b0e --- /dev/null +++ b/training/liblbfgs/lbfgs++.h @@ -0,0 +1,143 @@ +// THIS IS CDEC'S C++ WRAPPER AROUND LIBLBFGS +// liblbfgs is +//                                       Copyright (c) 1990, Jorge Nocedal +//                                 Copyright (c) 2007-2010, Naoaki Okazaki +// +// see https://github.com/chokkan/liblbfgs for more details +// +#ifndef __LBFGSPP_H__ +#define __LBFGSPP_H__ + +#include <vector> +#include <cassert> +#include "liblbfgs/lbfgs.h" + +// Function must be double f(const vector<double>& x_start, double* g_start) +template <typename Function> +class LBFGS { + public: +  LBFGS(size_t n,            // number of variables +        const Function& f,   // function to optimize +        double l1_c = 0.0,   // l1 penalty strength +        size_t m = 10        // number of memory buffers +                             // TODO should use custom allocator here: +        ) : p_x(new std::vector<lbfgsfloatval_t>(n, 0.0)), +                             owned(true), +                             m_x(*p_x), +                             func(f) { +    Init(m, l1_c); +  } + +  // constructor where external vector storage for variables is used +  LBFGS(std::vector<lbfgsfloatval_t>* px, +        const Function& f, +        double l1_c = 0.0,   // l1 penalty strength +        size_t m = 10 +        ) : p_x(px), +                             owned(false), +                             m_x(*p_x), +                             func(f) { +    Init(m, l1_c); +  } + +  ~LBFGS() { +    if (owned) delete p_x; +  } +  const lbfgsfloatval_t& operator[](size_t i) const { return m_x[i]; } +  lbfgsfloatval_t& operator[](size_t i) { return m_x[i]; } +  size_t size() const { return m_x.size(); } + +  int MinimizeFunction(bool s = false) { +    silence = s; +    ec = 0; +    lbfgsfloatval_t fx; +    int ret = lbfgs(m_x.size(), &m_x[0], &fx, _evaluate, _progress, this, ¶m); +    if (!silence) { +      std::cerr << "L-BFGS optimization terminated with status code = " << ret << std::endl; +      std::cerr << "  fx = " << fx << std::endl; +    } +    return ret; +  } + + private: +  void Init(size_t m, double l1_c) { +    lbfgs_parameter_init(¶m); +    param.m = m; +    if (l1_c > 0.0) { +      param.linesearch = LBFGS_LINESEARCH_BACKTRACKING; +      param.orthantwise_c = 1.0; +    } +    silence = false; +  } + +  static lbfgsfloatval_t _evaluate( +        void *instance, +        const lbfgsfloatval_t *x, +        lbfgsfloatval_t *g, +        const int n, +        const lbfgsfloatval_t step) { +      return reinterpret_cast<LBFGS<Function>*>(instance)->evaluate(x, g, n, step); +    } + +    lbfgsfloatval_t evaluate(const lbfgsfloatval_t *x, +                             lbfgsfloatval_t *g, +                             const int n, +                             const lbfgsfloatval_t step) { +      (void) n; +      (void) step; +      if (!silence) { ec++; std::cerr << '.'; } +      assert(x == &m_x[0]);  // sanity check, ensures pass m_x is okay +      return func(m_x, g); +    } + +    static int _progress( +        void *instance, +        const lbfgsfloatval_t *x, +        const lbfgsfloatval_t *g, +        const lbfgsfloatval_t fx, +        const lbfgsfloatval_t xnorm, +        const lbfgsfloatval_t gnorm, +        const lbfgsfloatval_t step, +        int n, +        int k, +        int ls +        ) +    { +        return reinterpret_cast<LBFGS<Function>*>(instance) +          ->progress(x, g, fx, xnorm, gnorm, step, n, k, ls); +    } + +    int progress( +        const lbfgsfloatval_t *x, +        const lbfgsfloatval_t *g, +        const lbfgsfloatval_t fx, +        const lbfgsfloatval_t xnorm, +        const lbfgsfloatval_t gnorm, +        const lbfgsfloatval_t step, +        int n, +        int k, +        int ls +        ) { +    (void) x; +    (void) g; +    (void) n; +    (void) ls; +    if (!silence) { +      if (ec < 8) std::cerr << '\t'; +      if (ec < 16) std::cerr << '\t'; +      ec = 0; +      std::cerr << "Iteration " << k << ':' << "\tfx = " << fx << "\t" +                << "  xnorm = " << xnorm << ", gnorm = " << gnorm << ", step = " << step << std::endl; +    } +    return 0; +  } +  std::vector<lbfgsfloatval_t>* p_x; +  const bool owned; +  std::vector<lbfgsfloatval_t>& m_x; +  const Function& func; +  lbfgs_parameter_t param; +  bool silence; +  int ec; +}; + +#endif | 
