我正在寻找scipy / numpy中的优化例程,它可以解决非线性最小二乘类型问题(例如,将参数函数拟合到大型数据集),但包括边界和约束(例如,最小值和最大值)要优化的参数)。目前我使用的是pyfit版本的mpfit(从idl ...翻译过来):虽然效果很好,但这显然不是最佳的。
python / scipy / etc中的高效例程可能很棒! 这里非常欢迎任何意见: - )
谢谢!
答案 0 :(得分:21)
scipy.optimize.least_squares 处理边界;使用它,而不是这个黑客。
约束约束很容易成为二次约束,
最小化由minimalsq和其余部分组成。
假设你想最小化10个方格的总和Σf_i(p)^ 2,
所以你的func(p)是10矢量[f0(p)... f9(p)],
并且对于3个参数也希望0< = p_i< = 1
考虑“浴缸功能”max( - p,0,p - 1),
0:1内部为0,外部为正,如_ _____ / tub
如果我们给leastsq
13长矢量
[ f0(p), f1(p), ... f9(p), w*tub(p0), w*tub(p1), w*tub(p2) ]
<=> w = 100,它将最小化该批次的平方和:
桶将约束0 <= p <= 1。
一般lo&lt; = p&lt; = 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
答案 1 :(得分:9)
scipy在scipy.optimize中有几个constrained optimization routines。约束最小二乘变量为scipy.optimize.fmin_slsqp
答案 2 :(得分:4)
Scipy长期以来一直缺乏以mpfit最佳方式解决带边界的非线性最小二乘问题的能力。
这个要求很高的功能最终在Scipy 0.17中引入,新功能scipy.optimize.least_squares。
这个新函数可以使用适当的信赖域算法来处理约束约束,并优化使用非线性函数的平方和性质进行优化。
注意:
@denis提出的解决方案存在引入不连续“浴缸功能”的主要问题。这使得scipy.optimize.leastsq
优化设计用于平滑函数,效率非常低,并且在跨越边界时可能不稳定。
使用scipy.optimize.minimize
与method='SLSQP'
(如@f_ficarola建议)或scipy.optimize.fmin_slsqp
(如@matt建议的那样),主要问题是不使用总和 - {要最小化的函数的平方性质。这些函数都旨在最小化标量函数(对于fmin_slsqp也是如此,尽管名称具有误导性)。这些方法效率低,准确度低于正确方法。
答案 3 :(得分:3)
看看: http://lmfit.github.io/lmfit-py/,它应该可以解决您的问题。