为什么 scipy.optimize.minimize 试图将奇怪的参数传递给我的 objective 函数?

Why is scipy.optimize.minimize trying to pass in weird arguments to my objective function?

我有一个 class 可以帮助实例化统计模型。它的一些数据成员是参数。我正在尝试编写一种优化这些参数的方法。反对函数基于似然函数的负数。此似然函数本身作为 class 方法实现,该方法在其计算中使用 class 数据成员的值。

我知道这是不好的风格,但每次 objective 函数被 scipy.optimize.minimize() 调用时,它都会将对象数据成员更改为更好的数据成员。我不太关心为什么这不好,而更关心为什么这不起作用。代码下方是完整的回溯。

似乎部分有效。它在测试数据上运行了几秒钟,但随后触发了我的断言。似乎 minimize() 在接近优化结束时做了一些奇怪的事情。为什么它会尝试将不同类型的参数传递给 objective 函数 obj_fun()?在我的 IPython 解释器中,我随后检查了对象的参数,它似乎达到了预期的结果。

我尝试查看 scipy 的一些来源。不过,这非常令人困惑。有很多模棱两可的变量命名和函数包装。任何人都可以告诉我为什么会发生这种情况以及如何解决它吗?我想再次将这些优化内容保留在我的 class.

class MyThing(object):
    .
    .
    .
    def mle_fit(self, y, inpt, optim_these):
        #step 1: figure out what you want to optimize
        self.optimize_these = optim_these
        #step 2: get inital flat parameter vector 
        self._make_list_optimizable_hyp_pars()
        init_guess = self.flat_hyper_params
        #step 3: run minimize
        def obj_fun(pars):
            # returns negative log likelihood 
            assert len(pars) == len(init_guess) # HERE #
            self.flat_hyper_params = pars
            self._unflatten_new_hps()
            self.like(y, inpt)
            return .5 * self.neg_2_log_like

        res = minimize(obj_fun, init_guess, method = 'BFGS')

回溯:

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/_minimize.py", line 419, in minimize
    return _minimize_bfgs(fun, x0, args, jac, callback, **options)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/optimize.py", line 850, in _minimize_bfgs
    old_fval, old_old_fval)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/optimize.py", line 690, in _line_search_wolfe12
    old_fval, old_old_fval)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/linesearch.py", line 263, in line_search_wolfe2
    derphi0, c1, c2, amax)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/linesearch.py", line 363, in scalar_search_wolfe2
    phi0, derphi0, c1, c2)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/linesearch.py", line 498, in _zoom
    phi_aj = phi(a_j)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/linesearch.py", line 239, in phi
    return f(xk + alpha * pk, *args)

  File "/home/taylor/anaconda/lib/python2.7/site-packages/scipy/optimize/optimize.py", line 281, in function_wrapper
    return function(*(wrapper_args + args))

  File "MyThing.py", line 222, in obj_fun
    assert len(pars) == len(init_guess)

如果我没记错的话,SciPy在优化时,可以将标量和数组都发送到要最小化的函数。因此,如果您优化 f(x),您将得到 x = 3.14x = array([1, 4])。 (这将用于加速计算,对于使用 NumPy 数组函数的 objective 函数 f。) 如果确实是这种情况,让您的代码处理这将解决问题。

现在,您可以通过 obj_fun() 中的 print pars, type(pars), len(pars) 这样的检查轻松检查情况。