具有约束约束的scipy.optimize.leastsq

use*_*231 24 python optimization mathematical-optimization scipy

我正在寻找scipy/numpy中的优化例程,它可以解决非线性最小二乘类型问题(例如,将参数函数拟合到大数据集),但包括边界和约束(例如参数的最小值和最大值)优化).目前我使用的是pyfit版本的mpfit(从idl翻译过来......):虽然效果很好,但显然不是最佳选择.

python/scipy/etc中的高效例程可能很棒!这里非常欢迎任何输入:-)

谢谢!

den*_*nis 22

scipy 0.17(2016年1月)中的scipy.optimize.least_squares处理边界; 使用它,而不是这个黑客.


绑定约束可以很容易地成为二次约束,并且最小化最小化以及其余约束.
假设你想最小化10个方格的总和Σf_i(p)^ 2,所以你的func(p)是10向量[f0(p)... f9(p)],
并且也想要0 <= p_i 3个参数<= 1.
考虑"浴缸功能"max( - p,0,p - 1),其在0 .. 1内为0,在外面为正,如_ _____/tub.
如果我们给出leastsq13长矢量

[ f0(p), f1(p), ... f9(p), w*tub(p0), w*tub(p1), w*tub(p2) ]
Run Code Online (Sandbox Code Playgroud)

当w = 100时,它将使批次的平方和最小化:桶将约束0 <= p <= 1.一般lo <= p <= hi是相似的.
下面的代码只是一个包装器,它leastsq 与例如13个长向量一起运行以最小化.

# leastsq_bounds.py
# see also test_leastsq_bounds.py on gist.github.com/denis-bz

from __future__ import division
import numpy as np
from scipy.optimize import leastsq

__version__ = "2015-01-10 jan  denis"  # orig 2012


#...............................................................................
def leastsq_bounds( func, x0, bounds, boundsweight=10, **kwargs ):
    """ leastsq with bound conatraints lo <= p <= hi
    run leastsq with additional constraints to minimize the sum of squares of
        [func(p) ...]
        + boundsweight * [max( lo_i - p_i, 0, p_i - hi_i ) ...]

    Parameters
    ----------
    func() : a list of function of parameters `p`, [err0 err1 ...]
    bounds : an n x 2 list or array `[[lo_0,hi_0], [lo_1, hi_1] ...]`.
        Use e.g. [0, inf]; do not use NaNs.
        A bound e.g. [2,2] pins that x_j == 2.
    boundsweight : weights the bounds constraints
    kwargs : keyword args passed on to leastsq

    Returns
    -------
    exactly as for leastsq,
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html

    Notes
    -----
    The bounds may not be met if boundsweight is too small;
    check that with e.g. check_bounds( p, bounds ) below.

    To access `x` in `func(p)`, `def func( p, x=xouter )`
    or make it global, or `self.x` in a class.

    There are quite a few methods for box constraints;
    you'll maybe sing a longer song ...
    Comments are welcome, test cases most welcome.

"""
    # Example: test_leastsq_bounds.py

    if bounds is not None  and  boundsweight > 0:
        check_bounds( x0, bounds )
        if "args" in kwargs:  # 8jan 2015
            args = kwargs["args"]
            del kwargs["args"]
        else:
            args = ()
#...............................................................................
        funcbox = lambda p: \
            np.hstack(( func( p, *args ),
                        _inbox( p, bounds, boundsweight ))) 
    else:
        funcbox = func
    return leastsq( funcbox, x0, **kwargs )


def _inbox( X, box, weight=1 ):
    """ -> [tub( Xj, loj, hij ) ... ]
        all 0  <=>  X in box, lo <= X <= hi
    """
    assert len(X) == len(box), \
        "len X %d != len box %d" % (len(X), len(box))
    return weight * np.array([
        np.fmax( lo - x, 0 ) + np.fmax( 0, x - hi )
            for x, (lo,hi) in zip( X, box )])

# def tub( x, lo, hi ):
#     """ \___/  down to lo, 0 lo .. hi, up from hi """
#     return np.fmax( lo - x, 0 ) + np.fmax( 0, x - hi )

#...............................................................................
def check_bounds( X, box ):
    """ print Xj not in box, loj <= Xj <= hij
        return nr not in
    """
    nX, nbox = len(X), len(box)
    assert nX == nbox, \
        "len X %d != len box %d" % (nX, nbox)
    nnotin = 0
    for j, x, (lo,hi) in zip( range(nX), X, box ):
        if not (lo <= x <= hi):
            print "check_bounds: x[%d] %g is not in box %g .. %g" % (j, x, lo, hi)
            nnotin += 1
    return nnotin
Run Code Online (Sandbox Code Playgroud)

  • @f_ficarola,1)SLSQP直接绑定(box bounds,== <=),但最小化标量func(); leastsq最小化一个平方和,完全不同.你有哪些,有多少参数和变量?2)什么是`np.shape(bounds)`?它应该是nparam x 2 - 首先运行`leastsq_bounds.check_bounds(x0,bounds)` (3认同)

mat*_*att 9

scipy在scipy.optimize中有几个约束优化例程.受约束的最小二乘变体是scipy.optimize.fmin_slsqp


div*_*nex 5

Scipy 长期以来一直缺少以 mpfit 那样的最佳方式解决有界非线性最小二乘问题的能力。

这个备受期待的功能最终在 Scipy 0.17 中引入,新函数scipy.optimize.least_squares

这个新函数可以使用合适的信任域算法来处理边界约束,并优化利用非线性函数的平方和性质进行优化。

笔记:

@denis 提出的解决方案的主要问题是引入了不连续的“浴缸功能”。这使得scipy.optimize.leastsq 为平滑函数设计的优化非常低效,并且在跨越边界时可能不稳定。

使用scipy.optimize.minimizewith method='SLSQP'(如@f_ficarola 建议)或scipy.optimize.fmin_slsqp(如@matt 建议)的主要问题是不利用要最小化的函数的平方和性质。这些函数都旨在最小化标量函数(对于 fmin_slsqp 也是如此,尽管名称具有误导性)。这些方法的效率和准确度都低于适当的方法。