我正在使用 scipy.least_squares 最小化算法来将复杂模型拟合到某些数据。该模型本身使用前向欧拉方法来求解微分方程,在 3 组不同的初始条件下,每组都对应于我试图拟合的一组数据。误差函数计算每组初始条件的数据与模拟之间的差异,并将它们连接起来。目标是优化 4 个均为正值的参数。当我运行最小二乘算法时,它返回错误“ValueError:残差在初始点不是有限的。”。然而,我的测试表明情况并非如此。
为了简单起见,我将省略模型本身的细节,但我有一个名为 errfunc 的预定义函数,它将参数数组作为第一个参数,并将 t(时间)和 y 数据集作为附加参数。该函数返回一个一维残差数组(模型 - 数据),它由每组初始条件的残差串联组成。为了运行优化,我的代码看起来有点像这样:
param = np.array([param1_init, param2_init, param3_init, param4_init])
result = least_squares(errfunc, param, bounds=(0,np.inf), args=(t_data1, y_data1, t_data2, y_data2, t_data3, y_data3))
据我了解,这个错误表明,当第一次评估错误函数的值时,返回了一些 NaN 或无限值。然而,我知道情况并非如此,当我自己在初始点运行错误函数时,它返回一个有限数组,使得
residual = errfunc(param, t_data1, y_data1, t_data2, y_data2, t_data3, y_data3)
print(np.all(np.isfinite(residual)))
返回 True。我还可以绘制初始参数的残差,这表明它们相当小并且具有预期的形状,表明模型正在按设计工作。
plt.plot(residual)
返回: 初始参数值处的残差图
我的问题是是否有任何我没有考虑到的事情可能会返回此错误?
对于与此非常相似的模型,优化效果非常好。模型中的唯一区别是微分方程中的附加项和需要优化的额外参数。我唯一的想法是非常大和非常小的参数值可能发挥了作用。我引入的附加参数具有非常小的正值(通常约为 1e-29),但正如我所示,此范围内的值会从模型中产生合理的结果。这是否会影响最小二乘算法并导致其引发此错误?
我找到了解决问题的方法。当将参数值的下限设置为 0 时,least_squares 似乎正在更改给予误差函数的初始参数,使它们大于或等于 1e-10。因此,我的模型(预期参数值要小得多)无法正常工作并返回非有限值。
删除边界并不能解决这个问题,因为误差函数第一次会正确评估,但对于后来的迭代,它使最小参数的值增加太多,并且引发了相同的错误。
为了解决这个问题,我在将参数传递给最小二乘之前手动放大了参数,并在将其传递给模型之前取消了错误函数中的缩放。
根据Scipy文档,least_squares中的x_scale参数执行这种缩放,但我发现使用这种方法我的参数初始值仍然被改变,并且错误仍然被引发。
嗨:我发现边界的格式也影响了这个错误。输入 1.0 而不是 1,它可能会消除错误