2012-03-26 206 views
21

我正在寻找一个scipy/numpy内的优化程序,它可以解决非线性最小二乘类型问题(例如,将参数函数拟合到大型数据集),但包括边界和约束条件(例如,要优化的参数的最小值和最大值)。目前我使用的是mpfit的python版本(翻译自idl ...):这显然不是最佳的,虽然它工作得很好。scipy.optimize.leastsq有约束约束

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

谢谢!

回答

9

scipy在scipy.optimize中有几个constrained optimization routines。受限最小二乘变体是scipy.optimize.fmin_slsqp

+0

谢谢!将在未来几天测试这个对mpfit我的问题,并会尽快报告! – user1293231 2012-03-26 22:19:31

+0

刚刚试过slsqp。我可能没有正确使用它,但基本上它没有太大的好处。当使用太低的epsilon值时,似乎会崩溃。否则,不会改变我的输入参数中的任何内容(或差不多)。我会做一些调试,但看起来并不那么容易使用(到目前为止)。将进一步尝试。 – user1293231 2012-04-03 12:41:11

+0

事实上,我只是得到以下错误==> linesearch的正方向派生(退出模式8)。这就是为什么我没有得到任何地方....不是很有用。任何提示? – user1293231 2012-04-03 13:14:46

20

scipy.optimize.least_squares in scipy 0.17(2016年1月) 句柄bounds;使用,而不是这个黑客。


束缚约束可以容易地进行二次, 并通过leastsq与其余部分一起最小化。假设你想最小化10个方块的总和,所以你的func(p)是一个10-矢量[f0(p)... f9(p)],
想要0 < = p_i < = 1的3个参数。
考虑“桶功能”最大( - p,0,p - 1), 这是0内部0和外部正面,像一个\ _____ /浴缸。
如果我们给leastsq 13长的矢量

[ f0(p), f1(p), ... f9(p), w*tub(p0), w*tub(p1), w*tub(p2) ] 

与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 
+0

我已经收到这个错误,当我试图实现它(Python 2.7):'文件“[/ PHPF]”,至少49行, ) 文件“[...]/minpack.py”,第369行,最小格数 shape,dtype = _check_func('leastsq','func',func,x0,args,n) File“[... ])/minpack.py“,第20行,在_check_func中 res = atleast_1d(thefunc(*((x0 [:numinputs]),+ args))) TypeError:()只需要1个参数(给出5)' – 2015-01-08 11:19:57

+1

@f_ficarola,对不起,args =是越野车;请剪切/粘贴并再次尝试 – denis 2015-01-08 16:03:46

+0

感谢您的快速回复,denis。然而,在此期间,我发现了这个:'scipy.optimize.minimize(residualsModel,x0,args =(arg1,arg2,...),method ='SLSQP',bounds = [(xmin,xmax)] )'。你的代码有什么不同吗? – 2015-01-08 18:40:28

3

看一看: http://lmfit.github.io/lmfit-py/,它应该解决您的问题。

+0

感谢您的提示:一个问题是,我希望能够有一个自洽的Python模块,包括有界非线性最小平方部分。这意味着要么用户将不得不安装lmfit,要么我将整个软件包包含在我的模块中。我将首先尝试fmin_slsqp,因为这是一个已经集成在scipy中的函数。但lmfit似乎正是我所需要的! – user1293231 2012-04-01 11:28:57

+0

考虑到您已经依赖SciPy,它不在标准库中。 lmfit在pypi上,对大多数用户来说应该很容易安装。 – chthonicdaemon 2015-01-10 15:56:06

+0

链接已损坏! – denfromufa 2016-10-18 22:21:39

4

长久以来,Scipy一直缺乏以最佳方式解决非线性最小二乘问题的能力,如mpfit所做的那样。

这个功能强大的功能终于在Scipy 0.17中引入,并且新功能scipy.optimize.least_squares

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

注:

通过@denis提出的解决方案具有引入不连续的“浴盆功能”的重大问题。这会导致为平滑函数设计的scipy.optimize.leastsq优化,效率非常低,并且可能不稳定,当边界交叉时。

采用scipy.optimize.minimizemethod='SLSQP'(如@f_ficarola建议的)或scipy.optimize.fmin_slsqp(如@马特建议的),必须被最小化不利用的功能的平方和的-性质的主要问题。这些函数都是为了尽量减少标量函数而设计的(尽管误导性名称也适用于fmin_slsqp)。这些方法效率较低,并且不如适当的方法准确。