4

我想将洛伦兹峰拟合到一组数据 x 和 y,数据很好。OriginLab 等其他程序非常适合它,但我想用 python 自动拟合,所以我有以下基于http://mesa.ac.nz/?page_id=1800的代码

我遇到的问题是 scipy.optimize.leastsq 作为最适合我传递给它的初始猜测参数返回,基本上什么都不做。这是代码。

#x, y are the arrays with the x,y  axes respectively
#defining funcitons
def lorentzian(x,p):
  return p[2]*(p[0]**2)/(( x - (p[1]) )**2 + p[0]**2)

def residuals(p,y,x):
  err = y - lorentzian(x,p)
  return err      

p = [0.055, wv[midIdx], y[midIdx-minIdx]]   
pbest = leastsq(residuals, p, args=(y, x), full_output=1)
best_parameters = pbest[0]
print p
print pbest

p 是初始猜测,best_parameters 是从 leastsq 返回的“最佳拟合”参数,但它们始终相同。

这是由 full_output=1 返回的(长数值数组已缩短但仍具有代表性)

    [0.055, 855.50732, 1327.0]
    (array([  5.50000000e-02,   8.55507324e+02,   1.32700000e+03]), 
    None, {'qtf':array([ 62.05192947,  69.98033905,  57.90628052]), 
    'nfev': 4, 
    'fjac': array([[-0.,  0.,  0., 0.,  0.,  0.,  0.,],
    [ 0., -0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.],
    [ 0.,  0., -0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
    0.,  0.]]), 
    'fvec': array([  62.05192947,   69.98033905,   
    53.41218567,   45.49879837,   49.58242035,   36.66483688,
    34.74443436,   50.82238007,   34.89669037]), 
    'ipvt': array([1, 2, 3])},  
    'The cosine of the angle between func(x) and any column of the\n  Jacobian 
    is at most 0.000000 in absolute value', 4)

谁能看到有什么问题?

4

1 回答 1

5

快速的谷歌搜索提示数据为单精度的问题(您的其他程序几乎肯定也向上转换为双精度,尽管这显然也是 scipy 的问题,另请参阅此错误报告)。如果您查看您的full_output=1结果,您会看到雅可比在任何地方都近似为零。因此,明确给出雅可比行列式可能会有所帮助(尽管即使那样你也可能想要向上转型,因为你可以通过单精度获得的相对误差的最小精度非常有限)。

解决方案:最简单和数值最佳的解决方案(当然,给出真正的雅可比也是一个奖励)是将你的xy数据转换为双精度(x = x.astype(np.float64)例如)。

我不建议这样做,但您也可以epsfcn通过手动设置关键字参数(以及可能的容差关键字参数)来修复它epsfcn=np.finfo(np.float32).eps。这似乎在某种程度上解决了这个问题,但是(因为大多数计算都是使用标量,并且标量不会在您的计算中强制向上转换)计算是在 float32 中完成的,并且精度损失似乎相当大,至少在没有的时候提供 Dfunc。

于 2012-09-18T12:36:27.487 回答