numpy - scipy.optimize.leastsq 无法拟合简单模型

标签 numpy scipy least-squares model-fitting levenberg-marquardt

我一直在尝试使用Python的scipy.optimize库来估计模型的参数,但到目前为止没有成功。我尝试使用 scipy.optimize.leastsq ,它使用 levenberg-marquardt 算法。不幸的是,即使我将初始参数猜测设置得非常接近最佳拟合,它总是无法找到模型函数的最小值。实际上,它总是返回初始猜测的参数。所以,我认为我做错了什么。我的模型是一个简单的圆,但为了让事情变得更简单,只有半径是实际参数,数据中圆的中心是已知的并且是硬编码的。该数据是一个 10x10 像素的 float 图像,其圆心为 5,5,半径为 4。实际上,数据是使用我试图拟合的模型生成的。因此,存在完美契合。这是我的代码:

import math
import numpy
import scipy.optimize

# ========================================================================

g_data_width = 10
g_data_height = 10
g_xo = 5.0
g_yo = 5.0

def evaluate_model01(x,y,r):
    x2 = x*x
    y2 = y*y
    r2 = r*r
    v = 0.0
    if(x2 + y2 <= r2):
        v = 20.0
    return v

def model01(params,data_o):
    data_r = numpy.zeros(g_data_height*g_data_width)
    r = params[0]
    for y in range(g_data_height):
        for x in range(g_data_width):
            xnew = x - g_xo
            ynew = y - g_yo
            data_r[y*g_data_width+x] = math.fabs(data_o[y,x]-evaluate_model01(xnew,ynew,r))
    return data_r

# ========================================================================

g_data_o = numpy.array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
                        [ 0,  0,  0,  0,  0, 20,  0,  0,  0,  0],
                        [ 0,  0,  0, 20, 20, 20, 20, 20,  0,  0],
                        [ 0,  0, 20, 20, 20, 20, 20, 20, 20,  0],
                        [ 0,  0, 20, 20, 20, 20, 20, 20, 20,  0],
                        [ 0, 20, 20, 20, 20, 20, 20, 20, 20, 20],
                        [ 0,  0, 20, 20, 20, 20, 20, 20, 20,  0],
                        [ 0,  0, 20, 20, 20, 20, 20, 20, 20,  0],
                        [ 0,  0,  0, 20, 20, 20, 20, 20,  0,  0],
                        [ 0,  0,  0,  0,  0, 20,  0,  0,  0,  0]],dtype=numpy.float32)
g_params = numpy.array([8.0])
print(scipy.optimize.leastsq(model01,g_params,args=(g_data_o),full_output=1))

# ========================================================================

我对数据进行了硬编码,以消除任何数据依赖性,并允许代码在任何安装了 scipy 的计算机上开箱即用地运行。我不太明白的是 model01 函数应该返回什么。根据文档,它应该返回一个数组。什么的数组?在我的代码中,我假设我必须返回每个数据点的残差数组。那是对的吗?我的数据是一个二维数组,因为它是一个图像,但我的残差是一个扁平的二维残差数组。这可以吗?有人能告诉我我到底做错了什么吗?有人可以修改和修复代码吗?正如我上面提到的,代码应该在任何安装了 scipy 和 numpy 的机器上开箱即用。如果我想要实现的目标无法通过 scipy.optimize.leastsq 实现,您能否建议一些其他适合使用 levenberg-marquardt 算法的模型的库?

最佳答案

恐怕您无法使用leastsq解决您的特定问题。 leastsq 是 FORTRAN 库 minipack 的包装,它调用 MINPACKlmdiflmder算法。重要的是,它基于最小二乘目标函数的雅可比行列式和海森行列式。您的目标函数没有平滑导数,因为:

if(x2 + y2 <= r2):
    v = 20.0

math.fabs(......)

,因此leastsq将始终返回初始启动参数。

您应该尝试使用一些不需要梯度/导数的方法,例如 Powell 方法 fmin_powell 或 Nelder-Mead fmin

关于您的 model101() 中发生的情况。它首先创建一个 g_data 大小为 width*height 的一维数组,称为 data_r。然后它迭代 g_data,计算每个元素的 math.fabs(data_o[y,x]-evaluate_model01(xnew,ynew,r)) 并将该值放入一维数组data_r。最后,它返回date_r

您的解释是正确的,model101() 返回 2D 数据的展平一维残差数组。

关于numpy - scipy.optimize.leastsq 无法拟合简单模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19110355/

相关文章:

python - 我应该如何使用 Numpy 的样式记录类和对象属性?

python - 在 Python 中对矩阵的选定元素求和

python - 如何对 SciPy 曲线拟合施加约束?

c++ - 特征矩阵相乘断言失败

Python 最小二乘法与 scipy.integrate.quad

python - 围绕python中的点旋转(矩阵)

python - 测试 Numpy 数组是否包含给定行

python - 将元组中的列表转换为numpy数组?

python - 用均值减去当前像素时如何处理负值

c++ - 图像曲线拟合的多项式最小二乘法