python - scipy.optimize.leastsq 使用 NaN 调用目标函数

标签 python numpy scipy mathematical-optimization

我正在使用 scipy.optimize.leastsq尝试在存在噪声的情况下将许多参数拟合到真实世界的数据中。偶尔会从 minpack 中使用 NaN 调用目标函数。这是 scipy.optimize.leastsq 的预期行为吗?有没有比在这种情况下只返回 NaN 残差更好的选择?

以下代码演示了该行为:

import scipy.optimize
import numpy as np

xF = np.array([1.0, 2.0, 3.0, 4.0]) # Target value for fit
NOISE_LEVEL = 1e-6 # The random noise level
RETURN_LEN = 1000  # The objective function return vector length

def func(x):
    if np.isnan(np.sum(x)):
        raise ValueError('Invalid x: %s' % x)
    v = np.random.rand(RETURN_LEN) * NOISE_LEVEL
    v[:len(x)] += xF - x
    return v

iteration = 0
while (1):
    iteration += 1
    x = np.zeros(len(xF))
    y, cov = scipy.optimize.leastsq(func, x)
    print('%04d %s' % (iteration, y))

正在对雅可比行列式进行数值计算。在生产代码中,优化通常有效,除非初始估计太好,表面非常平坦,并且噪声压倒了用于数值计算雅可比行列式的增量。在这种情况下,目标函数的残差就像上面的代码示例一样表现为随机噪声,我不希望优化收敛。

在此代码示例中,小的 NOISE_LEVEL 值 (<1e-10) 总是会收敛。在 1e-6,ValueError 通常会在几百次尝试中抛出。

一种可能的解决方法是返回高度惩罚的残差(NaN 或 INF),例如:

v = np.empty(RETURN_LEN)
v.fill(np.nan)
return v

如果变脏,此解决方法似乎很有效。首先有没有更好的替代方法或方法来防止 NaN?

此行为是在 Windows 7 上运行的 Python 2.7.9 x32 下观察到的。

最佳答案

由于您的问题定义在非线性问题(噪声)上使用线性求解器,求解器会崩溃,除非噪声水平低于明显阈值。

为了解决这个问题,您可以尝试使用非线性求解器。 例如使用 broyden1 求解算法而不是 leastsq:

import scipy.optimize
import numpy as np

xF = np.array([1.0, 2.0, 3.0, 4.0]) # Target value for fit
NOISE_LEVEL = 1.e-6 # The random noise level
RETURN_LEN = 1000  # The objective function return vector length

def func(x):
    if np.isnan(np.sum(x)):
        raise ValueError('Invalid x: %s' % x)
    v = np.random.rand(RETURN_LEN) * NOISE_LEVEL

    v[:len(x)] += xF - x

    return v[:len(x)]

iteration = 0
while iteration < 10:
    iteration += 1
    x = np.random.rand(len(xF))
    y = scipy.optimize.broyden1(func, x)
    print('%04d %s' % (iteration, y))

作为输出返回:

0001 [ 1.00000092  2.00000068  3.00000051  4.00000097]
0002 [ 1.0000012   2.00000214  3.00000272  4.00000369]
0003 [ 0.99999991  1.99999931  2.99999815  3.9999978 ]
0004 [ 1.00000097  2.00000198  3.00000345  4.00000425]
0005 [ 1.00000047  1.99999983  2.99999938  3.99999922]
0006 [ 1.00000024  2.00000021  3.00000071  4.00000136]
0007 [ 1.00000116  2.00000102  3.00000225  4.00000357]
0008 [ 1.00000006  2.00000002  3.00000017  4.00000039]
0009 [ 1.0000002   2.00000034  3.00000062  4.00000051]
0010 [ 1.00000137  2.0000015   3.00000193  4.00000344]

关于python - scipy.optimize.leastsq 使用 NaN 调用目标函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29375166/

相关文章:

python - 使用 curve_fit 拟合梯形

python - SciPy 凸包错误

python - 如何从密集的 Pandas 数据帧中制作完整的矩阵

python - 为什么 ThreadPoolExecutor 比 for 循环慢?

python - 来自数组和 np.dtype 对象的结构化数组

python - 向曲面图添加图例

python - 需要使用 `non-ndarray sequence` 进行 numpy 基本索引的示例

python - append 到函数内部列表时出现问题

python - 需要运行 python sftp 服务器

python - 在 2x2 网格中绘制形状图