使用lmfit最小化以适应3D点数据集上的3D线

时间:2017-06-30 05:20:27

标签: python 3d scipy minimize lmfit

我正在使用lmfit最小化以在3D点的数据集上拟合3D线。

from lmfit import minimize, Parameters, report_fit,fit_report, printfuncs
import numpy as np

#Parameters of parametric equations:  
#x = p[0] + p[1]*t;
#y = p[2] + p[3]*t;
#z = t;
params = Parameters()
params.add('x0',   value= 1)
params.add('x1',   value= 1)
params.add('y0',   value= 1)
params.add('y1',   value= 1)

#Function to be minimized - sum of distances between the line and each point    
def fun(params,x,y,z):
    x0 = params['x0'].value; x1 = params['x1'].value 
    y0 = params['y0'].value; y1 = params['y1'].value
    d = 0  

    v0 = np.array([x0, y0, 0.0])
    v1 = np.array([x0+x1, y0+y1, 1.])
    for point in range(len(x)):           
        p = np.array([x[point], y[point], z[point]])
        d += np.linalg.norm(np.cross(v1-v0,v0-p))/np.linalg.norm(v1-v0)  
    return d


result = minimize(fun, params,args=(x,y,z)))
result.params.pretty_print()
print(fit_report(result))

错误是TypeError:输入不当:N = 4不得超过M = 1.

据我所知,这是因为只有1个残差(距离)和4个参数,但这正是我所需要的。我想优化4个参数以获得最小距离之和。

3 个答案:

答案 0 :(得分:1)

问题是在你的情况下fun会返回一个标量。这对于某些方法来说没什么问题,但正如你所说的那样least_squares需要一个数组。我认为重写你的目标函数以便它返回一个数组应该解决这个问题 - 看一下描述和例子here

答案 1 :(得分:0)

似乎是一个方法问题。

  

目标函数应返回要最小化的值。对于来自leastsq()或least_squares()的> Levenberg-Marquardt算法,此>返回值必须是一个数组,其长度大于或等于>模型中拟合变量的数量。

使用Nelder,我得到了结果。 虽然不正确。所以仍然不确定代码。

答案 2 :(得分:0)

对于使用Levenberg-Marquardt最小化(lmfit.minimize()的默认方法),您应该返回距离的ndarray。也就是说,不要自己制作最小二乘法。通过返回完整数组(对特定参数值集的所有距离观察),您可以使拟合算法更好地探索参数对拟合质量的影响。