【问题标题】:Passing member functions as arguments to optimizer (passing member functions to a function)将成员函数作为参数传递给优化器(将成员函数传递给函数)
【发布时间】:2026-02-08 22:30:02
【问题描述】:

我正在尝试使用 dlib 来最小化一个函数,我可以使用find_min 计算该函数及其在给定参数值下的梯度。

由于函数根据输入而变化,因此我定义了一个类,其中输入作为该类的成员,以及两个公共函数,用于在当前解的猜测下计算函数及其梯度:

#include <dlib/matrix.h>
typedef dlib::matrix<double,0,1> column_vector;
class Link
{
   public:
      // Initialisation
      Link(const column_vector& predictors, const column_vector& responses)
         : _predictors(predictors), _responses(responses)
      {
      }

      // Likelihood and first derivative
      double likelihood(const column_vector& b) const;
      column_vector gradient(const column_vector& b) const;

   protected:
      column_vector _predictors;
      column_vector _responses;
};

(为简单起见,省略了计算这些函数的代码)。

然后我遍历预测变量和响应的循环,最小化每个案例:

column_vector starting_point(2);
Link linear(x, y);

dlib::find_min(dlib::bfgs_search_strategy(),
               dlib::objective_delta_stop_strategy(1e-7),
               linear.likelihood,
               linear.gradient,
               starting_point);

但是,我尝试从Link 提供非静态成员函数linear.likelihoodlinear.gradient 时出现编译器错误:“必须调用对非静态成员函数的引用”。

我之前在仅使用可能性时通过重载operator() 来实现这一点,但不能使用两个函数(可能性和梯度)来做到这一点。将它们转换为函数指针会产生同样的错误。

搜索其他答案我发现了尝试将非静态成员函数作为参数传递的类似问题,但无法让它们在这里工作。是否有使用模板参数的标准解决方案,我应该使用它来解决这个问题?

或者我是否完全以错误的方式解决这个问题,我不应该使用这样的类?

【问题讨论】:

    标签: c++ parameters arguments functor dlib


    【解决方案1】:

    dlib::find_min() 的参数必须是可以通过函数调用operator() 调用的对象。 linear.likelihood() 调用似然函数并返回结果,但 linear.likelihood 本身不是格式良好的 C++。

    一个简单的解决方案是使用lambda expressions 并通过引用捕获对象linear。 lambda 表达式是一个可调用的临时对象。

    dlib::find_min(dlib::bfgs_search_strategy(),
                   dlib::objective_delta_stop_strategy(1e-7),
                   [&linear](const column_vector& a) {
                       return linear.likelihood(a);
                   },
                   [&linear](const column_vector& b) {
                       return linear.gradient(b);
                   },
                   starting_point);
    

    【讨论】:

    • 效果很好,谢谢!我还发现使用std::bind 会起作用,但我认为您的解决方案更清晰(更快?)