使用非常大或非常小的数字时scipy.optimize.fmin_slsqp出现问题
有没有人遇到过在使用 fmin_slsqp(或者 scipy.optimize 中的其他东西)时,只有在处理非常大或非常小的数字时才会出现问题?
我正在写一些 Python 代码,目的是处理一张灰度图像和一个掩膜,生成直方图,然后给直方图拟合多个高斯分布。为了开发这段代码,我用了一张小样本图像,经过一番努力,代码运行得非常好。然而,当我先对直方图进行归一化处理,生成的箱子值小于1,或者在处理超大图像时,生成的箱子值达到几十万,fmin_slsqp() 就开始偶尔出错。它在大约5次迭代后就停止了,通常只是返回我给的初始猜测的一个稍微修改的版本,并且返回退出模式8,这意味着“线搜索的正方向导数”。如果我在开始时检查箱子计数的大小,并将它们缩放到大约100到1000的范围内,fmin_slsqp() 就能正常工作。我只是在返回结果之前再把它们缩放回去。我想我可以这样做,但感觉有点像是变相解决问题。
我查了一下,发现有人提到 epsilon 值,这基本上是用来近似导数的 dx,但调整这个值并没有帮助。除此之外,我还没有找到其他有用的信息。如果有任何想法,我将非常感激。提前谢谢大家。
james
3 个回答
我也遇到过这个问题,不过我在我的项目中解决了它。我不确定这是否是一个通用的解决方案。
问题的原因是,当参数 jac
设置为 False
或使用默认值时,scipy.optimize.fmin_slsqp
会用一种近似的方法来计算梯度。这个近似方法得到的梯度没有经过标准化(数值比较大)。在计算步长时,梯度的较大值会影响线搜索的表现和精度。这可能就是我们看到 Positive directional derivative for linesearch
的原因。
你可以尝试将雅可比矩阵的闭式形式应用到目标函数中,并把它传递给 jac
参数。更重要的是,你应该对雅可比矩阵的值进行重新缩放(比如标准化),以避免影响线搜索。
祝好。
当你的基础数据发生大幅度变化时,你有没有更新你最初的猜测("x0")呢?对于任何需要反复计算的线性优化问题,如果你的初始猜测离你想要拟合的数据太远,就会出现这些问题。这其实更多是一个优化的问题,而不是scipy库的问题。
我遇到过类似的问题,使用 optimize.leastsq 这个函数时。我的数据通常非常小,比如 1e-18 这样的数字,我发现 leastsq 在这种情况下无法找到最合适的参数。只有当我把数据缩放到更常见的范围(比如几百、几千等,能够用整数保持分辨率和动态范围)时,leastsq 才能收敛到一个比较合理的结果。
我尝试过调整一些可选的容差参数,这样就不需要在优化之前缩放数据,但运气不太好,没能成功...
有没有人知道一个好的通用方法,可以避免在 scipy.optimize 包中的函数出现这个问题?如果能分享一下,我会很感激... 我觉得这个问题的根源和提问者的情况是一样的。