scipy.optimize.leastsq无法适应简单的模型

时间:2013-10-01 07:27:14

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

我一直在尝试使用python的scipy.optimize库来估计模型的参数但到目前为止还没有成功。我试图使用scipy.optimize.leastsq使用levenberg-marquardt算法。不幸的是,即使我将初始参数设置为非常接近最佳拟合,它总是找不到我的模型函数的最小值。实际上,它总是返回初始猜测的参数。所以,我认为我做错了什么。我的模型是一个简单的圆,但为了使事情更简单,只有半径是实际参数,数据中圆的中心是已知的并且是硬编码的。数据是一个10x10像素的浮点图像,带有一个圆心,中心为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函数应该返回什么。根据文档,它应该返回一个数组。一阵什么?在我的代码中,我假设我必须为每个数据点返回一个残差数组。那是对的吗?我的数据是一个二维数组,因为它是一个图像但我​​的残差是一个平坦的2D残差数组。这可以吗?有人能告诉我究竟是做错了什么吗?有人可以修改和修复代码吗?如上所述,代码应该在安装了scipynumpy的任何计算机上开箱即用。如果scipy.optimize.leastsq无法实现我想要实现的目标,您能否使用levenberg-marquardt算法建议其他适合模型的库?

1 个答案:

答案 0 :(得分:1)

我担心您无法使用leastsq解决您的特定问题。 leastsq是FORTRAN库minipack的回绕,它调用MINPACK的{​​{1}}和lmdif算法。重要的是,它基于雅可比和最小二乘目标函数的Hessian。由于以下原因,您的目标函数没有平滑导数:

lmder

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

,因此math.fabs(......) 将始终返回初始启动参数。

您应该尝试使用一些不需要渐变/衍生的方法,例如Powell的方法leastsq或Nelder-Mead fmin_powell

关于fmin中发生了什么。它首先生成一个大小为model101() {1}的1D数组,称为width*height。然后迭代g_data,计算每个元素的data_r,并将该值放入1D数组g_data。最后,它返回math.fabs(data_o[y,x]-evaluate_model01(xnew,ynew,r))

您的解释是正确的,data_r会为您的2D数据返回展平的1D残差数组。