使用最小二乘法(Levenberg-Marquardt算法)将双曲线拟合到线性数据的程序不能按预期工作

问题描述 投票:0回答:1

我有一个1D数组数据,我试图使用三个参数建模为双曲线。我正在尝试使用scipy.optimize库中的leastsq函数实现Levenberg Marquardt算法。但是,我的程序陷入了一个迭代,其中一个数字除以零,我不明白为什么。

一些背景:1D阵列数据基本上是不同盒子尺寸的空隙值。我从一些声音文件the context to which can be found here.生成了空隙数据

在算法中,最小二乘函数需要三个输入: (a)对三个参数的初步猜测 (b)最小二乘问题的x坐标 - 在我的问题中基本上是从1到100的1D整数数组 (c)最小二乘问题的y坐标 - 这是存储空隙度值的一维数组。因此,空隙度值是x的函数,其中x从1到100变化。

双曲线使用三个参数a,b和c建模

enter image description here

该代码给出以下错误: “OverflowError:无法将浮点无穷大转换为整数”

代码:

#import
from scipy import *
from scipy.optimize import leastsq
import matplotlib.pylab as plt
import numpy as np
import codecs, json
from math import *

# Define your function to calculate the residuals. 
#The fitting function holds your parameter values.  
def residuals(p, y, x):
        err = y-pval(x,p)
        return err

def pval(x, p):
        z = x
        for i in range(100):
                print(x)
                print(x[i]**p[1])
                z[i] = p[0]/(x[i]**p[1])+p[2]
        return z

#read in your data
obj_text = codecs.open('textfiles\CC1.json', 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
data = np.array(b_new)
x = np.arange(1,101)
y = data[1:101]

#guess at initial parameters
A1_0=1.0
A2_0=1.0
A3_0=0.5

#leastsq package calls the Levenberg-Marquardt algorithm
pname = (['A1','A2','A3'])
p0 = array([A1_0 , A2_0, A3_0])
plsq = leastsq(residuals, p0, args=(y, x), maxfev=2000)

# Now, plot your data
plt.plot(x,y,'xo',x,pval(x,plsq[0]),'x')
title('Least-squares fit to data')
xlabel('x')
ylabel('y')
legend(['Data', 'Fit'],loc=4)

# Your best-fit paramters are kept within plsq[0].
print(plsq[0])

根据该错误,x的值在迭代中的某个点处变为0,并且第一个参数a最终被除以零,这给出了错误。

要进行故障排除,我在执行代码and you can see the values here时打印了值x [i] ^ b和数组x。我看到数组x正在被修改,这不应该发生。 x应该保持从1到100的1D自然数组,并且不会在迭代中被修改。我无法确定修改数组x的代码究竟在哪里。

我希望数组x保持不变,并且代码打印参数a,b和c的最后三个值。

编辑:我对我的代码进行了一些更改,之后它成功运行。以下是任何人都会感兴趣的编辑:

  1. 没有将z定义为z = x,而是将其定义为z = np.arange(1,101)。结果是数组x不再改变,这是预期的。
  2. 将数组x和y的数据类型更改为float
x = np.array(x, dtype=np.float64)
  1. 我再次陷入困境,在绘制数据的代码片段上。我得到错误“'标题'没有定义。对于xlabel,ylabel也有类似的错误。所以我只是删除了这些行并且只是坚持了
plt.plot(x,y,'red',x,pval(x,plsq[0]),'blue')
plt.show()
python python-3.x least-squares
1个回答
0
投票

不是你的问题的直接答案,但由于你正在使用取幂(**),我强烈建议您事先将所有数字转换为Decimal,以避免浮点运算对大值的固有精度损失。

例如:

import decimal
decimal.getcontext().prec = 100

A1_0=Decimal("1.0")
A2_0=Decimal("1.0")
A3_0=Decimal("0.5")

x = [Decimal(f) for f in x]
y = [Decimal(f) for f in y]

也许你的零点会“变成”一个接近于零的小值......

© www.soinside.com 2019 - 2024. All rights reserved.